背景

将开发分支dev兼并进主分支main以后,假如发现bug需要回滚代码时,咱们常使用git revert完结操作,可是当咱们将dev上的bug修复之后想再把它合进main却会发现,dev上的功用代码合不进去了,原因是这些功用代码的commit现已在main分支上了(尽管被revert了,但仍在),所以git会回绝合进重复的commit。本人最近就遇到了这种问题场景,查阅网上材料推荐的做法一般是把main之前的revert再revert掉然后合dev,可是实际操作过程中却产生了如下错误:

用 git rebase -i 解决「Git Revert之后再次合代码无效」的问题

不明就里,估计是由于多人协作导致main分支一日千里,revert操作产生了不行描述的抵触,翻看长串的git log已难以厘清… …但我决议不去深究这些细节,由于已想到更完美的解决方案!那便是利用git rebase -i将dev的commit们 squash(紧缩)为一个commit(首要意图是生成一个新的commit哈希),然后再去rebase main分支即可,实测效果拔群再也不必担心类似的问题了!

Demo复现该问题

  1. 初始状况:基于main分支切了dev分支并开发

用 git rebase -i 解决「Git Revert之后再次合代码无效」的问题

  1. dev兼并到main后

用 git rebase -i 解决「Git Revert之后再次合代码无效」的问题

  1. 发现bug,在main上进行回滚

用 git rebase -i 解决「Git Revert之后再次合代码无效」的问题

  1. 在dev上做bugfix并测试OK

用 git rebase -i 解决「Git Revert之后再次合代码无效」的问题

  1. dev从头兼并到main

用 git rebase -i 解决「Git Revert之后再次合代码无效」的问题

到这儿问题来了,咱们期望得到的main分支效果应该相当于以下分支:

c0 <- c1 <- c2 <- c3 <- c4

但由于c2 c3被revert掉(改动内容消失了),却现已存在于main上(从头兼并时main分支认为现已合过它俩,于是回绝重复引入c2 c3),所以到第5步得到的效果实际相当于:

c0 <- c1 <- c4

这便是标题所说「Git Revert之后再次合代码无效」的问题

用Squash方式解决该问题

在上述Demo的过程4基础上改

1、切到dev履行git rebase -i,让它自己rebase自己,意图是把dev上多个commit squash(紧缩兼并)为一个commit,这个新commit将具有新的哈希值(这样main分支就不会回绝它了)

咱们期望将c2 c3 c4兼并(即dev分支上完好的改变内容),假定c2的哈希值为c2_hash,需要履行以下shell命令

$ git checkout dev
$ git rebase -i c2_hash

2、弹出的vi编辑界面如下,根据提示squash掉dev上的commit

用 git rebase -i 解决「Git Revert之后再次合代码无效」的问题

3、填写commit信息,dev squash完结,效果如下

用 git rebase -i 解决「Git Revert之后再次合代码无效」的问题

4、再用dev去rebase main分支,此刻咱们能够彻底遗忘git revert的黑历史,就像将一个新鲜出炉的功用分支rebase主分支相同,有抵触解决抵触即可

用 git rebase -i 解决「Git Revert之后再次合代码无效」的问题

5. 再次将dev兼并到main即可,完美收官!

小结

解决git revert副作用问题,网上干流的方法是:

  1. 在main分支找到之前revert的commit(可能有多个,假如是多人协作则还可能分散)
  2. 将之前的revert再次进行revert
  3. 合dev分支,解决抵触

本文介绍的方法是:

  1. 在dev分支上找功用代码触及的commit(开发分支上一般是连续的几个commit,简单找)
  2. 将这些commit紧缩兼并为一个
  3. dev分支rebase到main分支,解决抵触

个人比较倾向于本文这种做法,一则处理起来比较舒畅,彻底不必去关心之前的revert记录;二则看起来舒畅,处理完之后dev分支较main分支只会多一个commit,这个commit包括dev上的一切功用代码改变