欢迎光临
感受代码之美

理解git revert和git reset的区别(如何安全、科学的回滚git版本历史)

准备

理解revert和reset命令的前提是理解git仓库的各个状态,如下图:

Git repo的主要组成

可以讲git仓库的三个状态分别成为:工作目录、缓存区快照、提交历史。

至于何种操作会处于这三种状态,参考下图:

git-operation.jpg

  • 新建的文件或修改的内容位于工作目录;
  • git add files把工作目录中的文件加入stage缓存区快照;
  • git commit把缓存生成一次commit,并加入commit提交历史;

git revert

git revert操作针对的是commit提交历史,而且如果进行此操作,如果当前仓库有没有添加到缓存区的文件(即没有git add),则会提示下面操作:

$ git revert HEAD
error: Your local changes to the following files would be overwritten by merge:
        readme.md
Please commit your changes or stash them before you merge.
Aborting
fatal: revert failed

如果没有进行提交(即没有git commit),则会提示下面错误:

$ git revert HEAD
error: your local changes would be overwritten by revert.
hint: commit your changes or stash them to proceed.
fatal: revert failed

进行git revert操作可能会有冲突,需要你合并一下代码,操作的结果是增加了一次commit历史。

git reset

使用reset命令时应该格外注意,因为如果你拿它来操作提交历史的话,提交历史是无法恢复的。因此它通常被用来撤销缓存区和工作目录的修改。不管是哪种情况,它应该只被用于本地修改(自己本地的缓存区或者尚未push到远程分支的提交历史),不要用来重设和他人共享的提交历史。

git reset根据不同的参数会有不同的效果,整理如下:

git reset <file>

将指定文件从缓存区移除,但不改变工作目录内容,即将文件取消git add操作。

git reset

将指定文件从缓存区移除,但不改变工作目录内容,即将所有执行了git add的文件从缓存区移出。

git reset --hard

这个就要小心了,因为此操作会重置工作目录和缓存区,而且是是使用最近的上次提交历史来重置。所以不管你执行git add没有,只要你没有执行git commit的所有更改都被重置会上次提交历史的版本。

git reset <commit>

删除了<commit>之后的提交历史,工作目录的内容保持不变,缓存区重置到<commit>这次提交的状态。

git reset --hard <commit>

删除了<commit>之后的提交历史,工作目录和缓存区都重置到<commit>这次提交的状态。

总结

撤销(revert)被设计为撤销公开的提交(比如已经push)的安全方式,git reset被设计为重设本地更改。因为两个命令的目的不同,它们的实现也不一样:重设完全地移除了一堆更改,而撤销保留了原来的更改,用一个新的提交来实现撤销。

转载请注明来源:四个空格 » 理解git revert和git reset的区别(如何安全、科学的回滚git版本历史)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址