git-reset的效果是重置当时分支的HEAD指针,将HEAD指针指向特定的状况。
运用概述
git reset [<tree-ish>] [--] <pathspec>
git reset [--pathspec-from-file=<file> [--pathspec-file-nul]] [<tree-ish>]
git reset (--patch | -p) [<tree-ish>] [--] [<pathspec>]
git reset [--soft | --mixed [-N] | --hard | --merge | --keep] [<commit>]
前三行reset指令的效果是将指定的<tree-ish>内容作为参考依据,然后把内容拷贝到方针的缓存区中。
<tree-ish>便是像树相同的东西,git中是有很多都能组成树的,比方commit树或者tag树。
最后一行reset指令的效果是将当时分支的HEAD指针指向<commit>,一起能够运用多种可选项来操控是否修正缓存区或作业区。
在以上一切的指令方式中,都是把<tree-ish>或<commit>默认作为HEAD指针。
git reset [<tree-ish>] [–] <pathspec>
该方法有如下规矩:
- 会将与<pathspec>相匹配的途径资源在缓存区中重置成<tree-ish>中的状况。不了解<pathspec>是什么?
- 被提交到缓存区中的改动会被复原到作业区中。
举个
假定项目中有一个coffee.txt文件,文件内容如下:
卡布奇诺纳瑞冰-19.9¥
规范美式-14.9¥
香草拿铁-19.9¥
生椰爱摩卡-19.9¥
...
咱们运用git的tag指令将当时的版别标记成v1.0.0(这儿运用tag标签作为)。
随后修正coffee.txt文件,修正内容如下:
卡布奇诺纳瑞冰-19.9¥ --> 卡布奇诺纳瑞冰-14.9¥
规范美式-14.9¥ --> 规范美式-9.9¥
香草拿铁-19.9¥ --> 香草拿铁-14.9¥
生椰爱摩卡-19.9¥ --> 生椰爱摩卡-14.9¥
...
改变了coffee.txt文件后,再运用git tag打上了v1.0.1标记。
假定此刻想将coffee.txt文件复原成v1.0.0版别中的文件,就能够运用git reset指令并指定为v1.0.0,操作如下:
git reset v1.0.0 coffee.txt
运用VSCode查看缓存区的文件变化: 能够看到图中的右侧的代码改动对比,此刻缓存区中的coffee.txt文件现已成功被重置成v1.0.0版别中文件的状况(规矩1)。而且此刻v1.0.1现已提交到缓存区中的变化也被复原到了作业树中(规矩2)。
能够看出git reset指令与git add指令效果相反,一个是将指定的资源添加到缓存区,另一个则是从缓存区中移除。而且这个指令与git restore [–source=<tree-ish>] –staged <pathspec>具有相同的效果,对restore感兴趣的能够看看这篇文章。
上面说过了,在运用reset指令后,此刻缓存区中文件内容是v1.0.0的,能够合作git restore指令将缓存区中的内容复原到作业区中然后进行修正:
git restore coffee.txt --staged
也能够根据需求挑选复原作业区的内容:
git restore coffee.txt --worktree
git reset[–pathspec-from-file=<file> [–pathspec-file-nul]] [<tree-ish>]
在上面的比如中每次进行reset和restore的都是想同的<pathspec>途径(coffee.txt)。由于该文件途径比较简略,所以每次操作都比较便利输入。但是在一些情况下,或许需求reset比较复杂的<pathspec>途径,比方项目目录层次较深,那么很或许需求输入一长串的<pathspec>途径,这样每次进行操作就会很麻烦,所以git供给了一个–pathspec-from-file选项,让咱们能够直接指定一个文件,这个文件就包含了或许需求重复运用的<pathspec>途径。这儿有更具体的用法。
该文件每一行都是一个<pathspec>,假定有多个<pathspec>运用换行符作为分隔。当然也能够运用–pathspec-file-nul让NUL作为每一个<pathspec>的分隔符。
git reset (–patch | -p) [<tree-ish>] [–] [<pathspec>]
交互式的挑选<tree-ish>与缓存区之间的差异而发生的hunks。这些被挑选的hunks将会撤销缓存区中的发生的修正。这儿有更具体的–patch选项用法。
git reset [<mode>] [<commit>]
该指令会把当时分支的HEAD指针指向某个<commit>,然后由<mode>决议是否一起更新缓存区或作业区的内容。<mode>默认值是–mixed,且必须是以下几种:
–soft
作业区和缓存区中的文件变化都将被保存,然后将HEAD指针指向<commit>。
还是以咖啡菜单为,假定第一次commit到仓库中的文件内容如下:
卡布奇诺纳瑞冰-19.9¥
规范美式-14.9¥
香草拿铁-19.9¥
生椰爱摩卡-19.9¥
...
然后做第二次commit操作,删去规范美式,增加生椰拿铁:
卡布奇诺纳瑞冰-19.9¥
-规范美式-14.9¥
+生椰拿铁-19.9¥
香草拿铁-19.9¥
生椰爱摩卡-19.9¥
...
在commit后,修正卡布奇诺纳瑞冰的价格,添加到缓存区。再修正香草拿铁的价格,保存在作业区:
-卡布奇诺纳瑞冰-19.9¥
+卡布奇诺纳瑞冰-14.9¥ // 添加到缓存区中
生椰拿铁-19.9¥
-香草拿铁-19.9¥
+香草拿铁-14.9¥ // 保存在作业区
生椰爱摩卡-19.9¥
...
此刻我想保存作业区和缓存区做的改动,而且将HEAD指针指向第一次commit。这时能够运用–soft选项实现:
git reset HEAD^ --soft // 这儿运用HEAD^表明上一个commit,相同也能够运用hash id
运用git log查看当时HEAD指针确实现已指向第一个commit,第二个commit被扔掉了: 一起一切的作业区和缓存区的改动都被保存了:
当时只要两次的commit,是为了便利演示–soft选项的效果。但是在实践开发中,咱们或许会commit多次,尤其是在测验环境改几个BUG就要提交到发布平台,这样会导致很多无意义的commit。这时候就能够运用–soft选项,重置HEAD到指定的<commit>只保存一到两个重要的commit。
–mixed
重置缓存区,但是会保存作业区的内容,这是<mode>的默认值。
相信有了解了–soft效果后,了解–mixed不难,上面比如中假定是运用–mixed那么最终成果如下: 该选项会重置缓存区,但是保存作业区的改动,并将当时指针指向<commit>。
–hard
重置缓存区和作业区中的一切的变化,而且将指针指向<commit>。
–hard愈加的简略粗犷,咱们将–soft比如改为–hard来查看成果: 如图所示,作业区和缓存区的内容都被重置了。不止是如此,就连Untracked文件相同也会被删去。
–merge
该选项的效果,看字面意思就知道大概便是把当时分支和指定的<commit>进行兼并,规矩如下:
- 重置缓存区,任何现已添加到缓存区的改动都将被扔掉
- 假定<commit>和HEAD之间有文件存在不同(这个不同指的是文件被删去或者新增),那么将会把该文件重置成<commit>中的状况(新增或删去)。
- 假定<commit>和HEAD之间有文件存在不同(这个不同是指文件内容的不同),且此刻作业区也存在未提交的改动,那么本次的reset将会被停止。
- 假定一个文件在<commit>和HEAD中完全相同,但是它的作业区存与缓存区存在着不同(也便是改动未提交到缓存区),那么该文件在作业区的改动在重置之后就会被保存。
咱们举个比如来验证一下以上列出的规矩,假定此刻的咖啡店项目有如下的几个commit。
第一个commit和文件内容如下: 第一个commit中只要一个coffee.txt菜单文件,此刻假定咖啡店引进了新品种开始卖果汁,那么就需求新增果汁菜单文件fruits.txt,所以就有了第二个commit: 此刻咱们做一些改动来验证1,2,4这几点的规矩,改动后的文件如下: 首要修正coffee.txt文件,新增一款生椰拿铁咖啡,保存在作业区中。然后增加咖啡豆菜单文件beans.txt,将其添加到缓存区中。
假定因需求变化,咖啡豆菜单文件在缓存区中需求清除,果汁菜单文件需求删去,只要咖啡菜单中新增的生椰拿铁的改动需求保存。那么就能够运用git reset –merge将HEAD和commit-1进行兼并,操作如下:
git reset --merge HEAD^
成果如下: 执行指令reset指令发生了如下效果:
- 将当时HEAD指针指向了commit-1
- 将缓存区中的beans.txt文件扔掉(规矩1)
- HEAD(commit-2)和commit-1中的fruits.txt文件存在不同(commit-2中新增fruits.txt),所以会将fruits.txt删去(规矩2)
- coffee.txt文件新增生椰拿铁的改动被保存在作业区中(规矩4)
再来验证一下第3点规矩,假定咖啡店项目此刻第一个commit如下: 接下去相同新增水果茶菜单,然后再修正coffee.txt文件,第二个commit如下: 然后在HEAD中再修正coffee.txt文件,删去掉规范美式品种: 此刻,假定咱们再运用git reset –merge HEAD^就无法再进行重置,该操作会被git停止(规矩3)。而且操控台会进行报错提示:
–keep
该选参的效果和–merge类似,仅有的差异便是缓存区中被重置的会被保存在作业区中。
结构如下第一个commit: 改造第二个commit: 在HEAD中进行修正 运用git reset –keep指令: 从成果上来看,只要fruits.txt文件被删去了,beans.txt文件被重置回了作业区中。coffee.txt文件的改动也被保存了。
–[no-]recurse-submodules
运用该选项能够操控是否递归的重置submdoule。假定想要更具体了解,查看这篇文章。
总结
git-reset指令的效果便是重置缓存区和作业区,一起它也供给多个选项来做更具体的操控,使得该指令愈加灵敏多变。git-reset指令在咱们的作业中经常运用,因而熟练掌握该指令是非常重要的。