develop ----1 3-----revert a------
\ /
branch a a
如此看来,git reset
和git revert
都能实现我现在的需求,那这两个到底有什么区别呢,在网上查了这个问题,我觉得说的有些抽象,看的不是很明白,于是自己实践了之后才明白。
git revert是用一次新的commit来回滚之前的commit,git reset是直接删除指定的commit。
这个很好理解,在刚才的操作中我们看日志已经可以看到这个现象。
git reset
操作之后,我们查看上面例子的network已经可以看到network中只有commit 1
,分支a
和合并分支后的commit 3
都消失了;
git revert
操作之后,network中还是可以看到a分支和合并a分支的操作,只不过在其基础上又增加了一个revert的commit而已。
git reset 是把HEAD向后移动了一下,而git revert是HEAD继续前进,只是新的commit的内容和要revert的内容正好相反,能够抵消要被revert的内容。
这个也是可以清晰明了的看到,我就不做过多的解释了
在回滚这一操作上看,效果差不多。但是在日后继续merge以前的老版本时有区别。因为git revert是用一次逆向的commit“中和”之前的提交,因此日后合并老的branch时,导致这部分改变不会再次出现,但是git reset是直接把某些commit在某个branch上删除,因而和老的branch再次merge时,这些被回滚的commit应该还会被引入。
git revert
现在的需求是我之前已经把a分支revert了,但是我现在又需要a分支的代码了,我之前都写过一遍总不能再重新写一遍了。我首先想到的方法,把a分支再merge到develop不就好了。
git merge a
Already up-to-date
啥?因为我们之前提交合并的a分支的代码还在,因此我们并不能在重新合并a分支。
解决办法:使用revert之前revert的commit号。在上面的例子中就是git revert 4
。于是又新增了一个commit,把之前revert的代码又重新revert回来了。具体参考
git reset
依旧是上面的需求。
develop -----1-----4-------5------6
\ / \ / \ /
feature b c d
现在我将develop reset到commit 4这里,继续提交我以后的代码
develop -----1-----4-------7------8
\ / \\ /
feature b \ e
\------5----d
\-c-/
我现在想重新合并d分支的代码
develop -----1-----4-------7------8------9
\ / \\ / /
feature b \ e /
\------5----d/
\-c-/
合并过来大概是这个样子的。也就是说d分支之前已经合并过c分支,因此如果还想要合并d分支的话,c分支的代码就会同步的带过来。
讲到这里大部分常用的应用场景也就应该是比较清晰的了。
如果回退分支的代码以后还需要的话用git revert
就再好不过了;
如果分支我就是提错了没用了还不想让别人发现我错的代码,那就git reset
吧
例如:develop分支已经合并了a、b、c、d四个分支,我忽然发现b分支没用啊,代码也没必要,这个时候就不能用reset了,因为使用reset之后c和d的分支也同样消失了。这时候只能用git revert b分支commit号
,这样c和d的代码依然还在。
我能想到的大概就是这些了,当然在具体项目上我们会遇到很多没遇到过的情形。我的建议是不要盲目的查找类似问题后就去修改,因为他的问题并不一定就等同于你的问题。我建议去创建测试的分支,等真正整明白了,再去整线上的分支也不迟。
第一次写了这么详细的一篇文章,主要也是因为网上查到的知识,对git知识体系一般的人来说,看的比较费解。