Git - 高级篇 (4)

     不知道碰到过没有提交有错误的情况.

reset 的本质——不止可以撤销提交

     前面讲到,在最新的 commit 写错时,可以用 reset --hard 来把 commit 撤销.

1
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 的历史只能往回看,不能向未来看,所以把 HEADbranch 往回移动,就能起到撤回 commit 的效果。

     所以同理,reset --hard 不仅可以撤销提交,还可以用来把 HEADbranch 移动到其他的任何地方。 (这个使用 checkout 就可以了, no zuo no die)

1
git reset --hard branch2


     不过…… reset 后面总是跟着的那个 --hard 是什么意思呢?
     reset 指令可以重置 HEADbranch 的位置,不过在重置它们的同时,对工作目录可以选择不同的操作,而对工作目录的操作的不同,就是通过 reset 后面跟的参数来确定的。

reset –hard:重置工作目录

     reset --hard 会在重置 HEADbranch 的同时,重置工作目录里的内容。当你在 reset 后面加了 --hard 参数时,你的工作目录里的内容会被完全重置为和 HEAD 的新位置相同的内容。换句话说,就是你的未提交的修改会被全部擦掉。
     例如你在上次 commit 之后又对文件做了一些改动:

1
git status


     然后,你执行了 reset 并附上了 --hard 参数:

1
git reset --hard HEAD^

     你的 HEAD 和当前 branch 切到上一条 commit 的同时,你工作目录里的新改动也一起全都消失了,不管它们是否被放进暂存区:

1
git status


     可以看到,在 reset --hard 后,所有的改动都被擦掉了。

reset –soft:保留工作目录

     reset --soft 会在重置 HEADbranch 时,保留工作目录和暂存区中的内容,并把重置 HEAD 所带来的新的差异放进暂存区。
     什么是「重置 HEAD 所带来的新的差异」?就是这里:



     所以在同样的情况下:

1
git status


     假设此时当前 commit 的改动内容是新增了 laughters.txt 文件:

1
git show --stat


     如果这时你执行:

1
git reset --soft HEAD^

     那么除了 HEAD 和它所指向的 branch1 被移动到 HEAD^ 之外,原先 HEADcommit 的改动(也就是那个 laughters.txt 文件)也会被放进暂存区:

1
git status


     这就是 --soft--hard 的区别:--hard 会清空工作目录的改动,而 --soft 则会保留工作目录的内容,并把因为保留工作目录内容所带来的新的文件差异放进暂存区。

reset 不加参数:保留工作目录,并清空暂存区

     reset 如果不加参数,那么默认使用 --mixed 参数。它的行为是:保留工作目录,并且清空暂存区。也就是说,工作目录的修改、暂存区的内容以及由 reset 所导致的新的文件差异,都会被放进工作目录。简而言之,就是「把所有差异都混合(mixed)放在工作目录中」。

     还是以同样的情况为例.

1
git status


这里修改了 games.txtshopping list.txt,并把 games.txt 放进了暂存区。

1
git show --stat


最新的 commit 中新增了 laughters.txt 文件。

     这时如果你执行无参数的 reset

1
git reset HEAD^

     工作目录的内容和 --soft 一样会被保留,但和 --soft 的区别在于,它会把暂存区清空:

1
git status


小结

     本节内容讲了 reset 指令的本质:重置 HEAD 以及它所指向的 branch 的位置。同时,介绍了 reset 的三种参数:

  1. --hard:重置位置的同时,清空工作目录的所有改动;
  2. --soft:重置位置的同时,保留工作目录和暂存区的内容,并把重置 HEAD 的位置所导致的新的文件差异放进暂存区。
  3. --mixed(默认):重置位置的同时,保留工作目录的内容,并清空暂存区。

     除了上面这三种参数,还有一些没有列出的较为不常用的参数;另外除了我讲的功能外,reset 其实也还有一些别的功能和用法。不过 reset 最关键的功能、用法和本质原理就是上面这些了,想了解更多的话,可以去官网了解一下。

~感谢捧场,您的支持将鼓励我继续创作~