前面讲到,在最新的commit写错时,可以用reset --hard来把commit撤销:
git reset --hard HEAD^用这行代码可以撤销掉当前
commit
现在就说说reset命令的本质,分析它在撤销提交之外的用途。
reset 的本质:移动 HEAD 以及它所指向的 branch
reset这个指令虽然可以用来撤销commit,但它的实质行为并不是撤销,而是移动HEAD,并且「捎带」上HEAD所指向的branch(如果有的话)。也就是说,reset这个指令的行为其实和它的字面意思 "reset"(重置)十分相符:它是用来重置HEAD以及它所指向的branch的位置的。
而reset --hard HEAD^之所以起到了撤销commit的效果,是因为它把HEAD和它所指向的branch一起移动到了当前commit的父commit上,从而起到了「撤销」的效果:
Git 的提交历史只能往回看,不能向未来看,所以把
HEAD和branch往回移动,就能起到撤回commit的效果。
reset使用--hard选项不仅可以撤销提交,还可以用来把HEAD和branch移动到其他任何地方。
git reset --hard branch2那么reset后面总是跟着的那个--hard是什么意思呢?
reset指令可以重置HEAD和branch引用的commit ID,不过在重置它们的同时,对工作目录可以选择不同的操作,对工作目录不同操作,就是通过reset后面跟不同的参数来确定的。
reset --hard:重置工作目录,重置暂存区
当你在reset后面加了--hard参数时,你工作目录里的内容会被完全重置为和HEAD的新位置相同的内容,你工作目录中未提交的修改也会被全部擦除掉。
例如你在上次commit之后对文件做了一些改动:
git status然后,你执行了reset并附上了--hard参数:
git reset --hard HEAD^结果就是你的HEAD和当前branch切到上一条commit的同时,你工作目录里的新改动也一起全都消失了,不管它们是否被放进暂存区(因为暂存区也和工作目录一样会被新位置的内容替换):
git status可以看到,在reset --hard后,所有的改动都被擦掉了。
reset --soft:保留工作目录,差异放到暂存区
reset --soft会在重置HEAD和branch时(更改指向的commit),保留工作目录和暂存区中的内容,并把重置HEAD所带来的新的差异放进暂存区。
什么是「重置HEAD所带来的新的差异」?就是这里:
由于HEAD从4移动到了3,而且在reset的过程中工作目录的内容没有被清理掉,所以4中的改动在reset后就也成了工作目录新增的「工作目录和HEAD的差异」。
所以在同样的情况下:
git status当前commit的改动内容是新增了laughters.txt文件:
git show --stat如果这时你执行:
git reset --soft HEAD^那么除了HEAD和它所指向的branch1被移动到HEAD^之外,原先HEAD处commit的改动(也就是那个laughters.txt文件)也会被放进暂存区:
git status这就是--soft和--hard的区别:--hard会清空工作目录的改动,而--soft则会保留工作目录的改动,并把因为保留工作目录内容所带来的新的文件差异放进暂存区。
reset 不加参数:保留工作目录,并清空暂存区
reset如果不加参数,那么默认使用--mixed参数。它的行为是:保留工作目录,并且清空暂存区。也就是说,工作目录的修改、暂存区的内容以及由reset所导致的新的文件差异,都会被放进工作目录。简而言之,就是「把所有差异都混合(mixed)放在工作目录中」。
还以同样的情况为例:
git status修改了
games.txt和shopping list.txt,并把games.txt放进了暂存区。
git show --stat最新的
commit中新增了laughters.txt文件。
这时如果你执行无参数的reset:
git reset HEAD^工作目录的内容和--soft一样会被保留,但和--soft的区别在于,它会把暂存区清空:
git status小结
本节内容讲了reset指令的本质:重置HEAD及其所指向branch的位置。同时,介绍了reset的三种参数:
--hard:重置HEAD指向位置的同时,清空工作目录的所有改动;--soft:重置HEAD指向位置的同时,保留工作目录和暂存区的内容,并把重置HEAD指向位置所导致的新的文件差异放进暂存区。--mixed:重置HEAD指向位置的同时,保留工作目录的内容、清空暂存区,并把重置HEAD指向位置所导致的新的文件差异都混合放进工作目录中(默认操作)。
除了上面这三种参数,还有一些没有列出的较为不常用的参数;另外除了这三种功能外,其实reset其实也还有一些别的功能和用法。不过reset最关键的功能、用法和本质原理就是上面这些,想了解更多的话,可以去官网了解一下。