Git Reset 三种模式
有时候,我们用Git的时候有可能commit提交代码后,发现这一次commit的内容是有错误的,那么有两种处理方法:
1、修改错误内容,再次commit一次 2、使用git reset 命令撤销这一次错误的commit
第一种方法比较直接,但会多次一次commit记录。
而我个人更倾向第二种方法,错误的commit没必要保留下来。
那么今天来说一下git reset。它的一句话概括
git-reset - Reset current HEAD to the specified state
意思就是可以让HEAD这个指针指向其他的地方。例如我们有一次commit不是不是很满意,需要回到上一次的Commit里面。那么这个时候就需要通过reset,把HEAD指针指向上一次的commit的点。
它有三种模式,soft,mixed,hard,具体的使用方法下面这张图,展示的很全面了。
刚开始 working tree 、 index 与 repository(HEAD)里面的內容都是一致的
阶段1
当git管理的文件夹里面的内容出现改变后,此時 working tree 的內容就会跟 index 及 repository(HEAD)的不一致,而Git知道是哪些文件(Tracked File)被改动过,直接将文件状态设置为 modified (Unstaged files)。
阶段2
当我們执行 git add 后,会将这些改变的文件內容加入 index 中 (Staged files),所以此时working tree跟index的內容是一致的,但他们与repository(HEAD)內容不一致。
阶段3
接着执行 git commit 後,將Git索引中所有改变的文件內容提交至 Repository 中,建立出新的 commit 节点(HEAD)后, working tree 、 index 與与repository(HEAD)区域的内容 又会保持一致。
阶段4
实战演示reset --hard:重置stage区和工作目录:reset --hard 会在重置 HEAD 和branch的同时,重置stage区和工作目录里的内容。当你在 reset 后面加了 --hard 参数时,你的stage区和工作目录里的内容会被完全重置为和HEAD的新位置相同的内容。换句话说,就是你的没有commit的修改会被全部擦掉。
例如你在上次 commit 之后又对文件做了一些改动:把修改后的ganmes.txt文件add到stage区,修改后的shopping list.txt保留在工作目录
git status
最初状态
然后,你执行了reset并附上了--hard参数:
git reset --hard HEAD^
你的 HEAD 和当前 branch 切到上一条commit 的同时,你工作目录里的新改动和已经add到stage区的新改动也一起全都消失了:
git status
reset --hard head^之后
可以看到,在 reset --hard 后,所有的改动都被擦掉了。 reset --soft:保留工作目录,并把重置 HEAD 所带来的新的差异放进暂存区reset --soft 会在重置 HEAD 和 branch 时,保留工作目录和暂存区中的内容,并把重置 HEAD 所带来的新的差异放进暂存区。
什么是「重置 HEAD 所带来的新的差异」?就是这里:
由于 HEAD 从 4 移动到了 3,而且在 reset 的过程中工作目录和暂存区的内容没有被清理掉,所以 4 中的改动在 reset 后就也成了工作目录新增的「工作目录和 HEAD 的差异」。这就是上面一段中所说的「重置 HEAD 所带来的差异」。
此模式下会保留 working tree工作目录的內容,不会改变到目前所有的git管理的文件夹的內容;也会
保留 index暂存区的內容,让 index 暂存区与 working tree 工作目录的內容是一致的。就只有 repository 中的內容的更变需要与 reset 目标节点一致,因此原始节点与reset节点之间的差异变更集合会存在与index暂存区中(Staged files),所以我们可以直接执行 git commit 將 index暂存区中的內容提交至 repository 中。当我们想合并「当前节点」与「reset目标节点」之间不具太大意义的 commit 记录(可能是阶段性地频繁提交)時,可以考虑使用 Soft Reset 来让 commit 演进线图较为清晰点。
所以在同样的情况下,还是老样子:把修改后的ganmes.txt文件add到stage区,修改后的shopping list.txt保留在工作目录
git status
最初状态
假设此时当前 commit 的改动内容是新增了 laughters.txt 文件:
git show --stat
git show --stat
如果这时你执行:
git reset --soft HEAD^
那么除了 HEAD 和它所指向的 branch1 被移动到 HEAD^ 之外,原先 HEAD 处 commit 的改动(也就是那个 laughters.txt 文件)也会被放进暂存区:
git status