代码回滚:Reset、Checkout、Revert 的选择

git reset、git checkout 和 git revert 是你的 Git 工具箱中最有用的一些命令。它们都用来撤销代码仓库中的某些更改,而前两个命令不仅可以作用于提交,还可以作用于特定文件


Git 仓库有三个主要组成——工作目录,缓存区和提交历史

提交层面的操作

你传给 git reset 和 git checkout 的参数决定了它们的作用域。如果你没有包含文件路径,这些操作对所有提交生效,注意,git revert 没有文件层面的操作。

Reset

在提交层面上,reset 将一个分支的末端指向另一个提交。这可以用来移除当前分支的一些提交。比如,下面这两条命令让 hotfix 分支向后回退了两个提交。

git checkout hotfix
git reset HEAD~2

如果你想扔掉这两个提交,你可以这么做

如果你的更改还没有共享给别人,git reset 是撤销这些更改的简单方法
除了在当前分支上操作,你还可以通过传入这些标记来修改你的缓存区或工作目录:

  • soft – 缓存区和工作目录都不会被改变
  • mixed – 默认选项。缓存区和你指定的提交同步,但工作目录不受影响
  • hard – 缓存区和工作目录都同步到你指定的提交

这些标记往往和 HEAD 作为参数一起使用。比如,git reset --mixed HEAD 将你当前的改动从缓存区中移除,但是这些改动还留在工作目录中。另一方面,如果你想完全舍弃你没有提交的改动,你可以使用 git reset --hard HEAD。这是 git reset 最常用的两种用法。

Checkout

当传入分支名时,可以切换到那个分支。

git checkout hotfix

上面这个命令做的不过是将HEAD移到一个新的分支,然后更新工作目录.

这对于快速查看项目旧版本来说非常有用。但如果你当前的 HEAD 没有任何分支引用,那么这会造成 HEAD 分离。
在为分离的 HEAD 添加新的提交的时候你应该创建一个新的分支.

Revert

Revert 撤销一个提交的同时会创建一个新的提交。这是一个安全的方法.
因为它不会重写提交历史。比如,下面的命令会找出倒数第二个提交,然后创建一个新的提交来撤销这些更改,然后把这个提交加入项目中。

git checkout hotfix
git revert HEAD~2

git reset,它不会改变现在的提交历史。因此,git revert 可以用在公共分支上,git reset 应该用在私有分支上

你也可以把 git revert 当作撤销已经提交的更改,而 git reset HEAD 用来撤销没有提交的更改
Git 会在你执行 revert 之前要求你提交或者缓存你工作目录中的更改。

文件层面的操作

git reset 和 git checkout 命令也接受文件路径作为参数。这时它的行为就大为不同了。它不会作用于整份提交,参数将它限制于特定文件。

Reset

检测到文件路径时,git reset 将缓存区同步到你指定的那个提交。比如,下面这个命令会将倒数第二个提交中的 foo.py 加入到缓存区中,供下一个提交使用。

git reset HEAD~2 foo.py

通常我们使用HEAD而不是某个特定的提交。运行 git reset HEAD foo.py 会将当前的 foo.py 从缓存区中移除出去,而不会影响工作目录中对 foo.py 的更改.

如果你缓存并且提交了 checkout 的文件,它具备将某个文件回撤到之前版本的效果。注意它撤销了这个文件后面所有的更改,而 git revert 命令只撤销某个特定提交的更改。

总结

命令 作用域 常用情景
git reset 提交层面 在私有分支上舍弃一些没有提交的更改
git reset 文件层面 将文件从缓存区中移除
git checkout 提交层面 切换分支或查看旧版本
git checkout 文件层面 舍弃工作目录中的更改
git revert 提交层面 在公共分支上回滚更改
git revert 文件层面 (然而并没有)
posted @ 2017-11-03 15:39  张建斌  阅读(691)  评论(0编辑  收藏  举报