一、问题

最近项目中使用git merge时遇到特性分支上部分commit内容丢失(没有合并到main分支)。本文记录一下踩坑过程。

项目git分支管理采用了main、prod-x、feat-x 三类分支(不是标准的git flow分支管理)。feat分支是特性开发分支,开发前从main分支拉取;prod分支类似产品发布分支,也是所有特性分支的合并分支。prod分支每个版本计划完成后从main分支拉取,发布前把feat特性分支合并到prod分支,联测验证没有问题后再合并到main分支发布。

一般feat特性分支合并到prod合并分支时需要走gitlab代码Merge Request流程。

发生问题的场景是一次gitlab上提代码Merge Request时错误把目的分支选择了main(应该是prod分支),评审通过并合并到了main分支。

意识到问题后我们在gitlab上点了回滚,实际就是在main分支上进行代码回滚。

到这里一切似乎一切正常。

问题发生在prod分支合并到master分支时,feat分支之前开发的内容不能合并到main分支了(git merge成功但是commit丢失)。

二、原因分析

上面git分支提交过程可以通过mermaid gitGraph图表示如下。

在main分支git merge prod-0.1分支时,公共提交是F1-任务1,因为main分支和prod分支都合并过feat分支内容,虽然main分支回滚了。

prod-0.1合并到main分支时,从公共提交F1 - 任务1开始,后面git commit记录包括M1 - 代码合并M2 - 错误合并从feat到mainC2-撤销M2的提交。可以看出最后一步的C2-撤销M2的提交会把F1 - 任务1提交回滚掉。

也可以这么理解:Git 会认为 “feat(即 F1) 的改动已经存在于 main(虽然被回滚)”,所以 M3 时不会重新引入 F1 的内容。

三、解决方法

解决方法是要修改合并分支的公共commit id。推荐方法如下:

  1. 重新从main分支拉一个feat-t1.1分支
  2. 把feat-t1分支上的F1 - 任务1通过git cherry-pick提取到feat-t1.1
  3. 合并feat-t1.1到prod-0.1
  4. 合并prod-0.1到main分支

这样F1 - 任务1中的提交内容就能合并到main分支了。

四、参考

mermaid编程式画图挺不错,文中git画图指令参考如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
gitGraph
commit id: "C1 - 初始提交"

branch prod-0.1
checkout prod-0.1
commit id: "P1 - 合并分支"

branch feat-t1
checkout feat-t1
commit id: "F1 - 任务1"

checkout prod-0.1
merge feat-t1 id: "M1 - 代码合并"

checkout main
merge feat-t1 id: "M2 - 错误合并从feat到main"
commit id: "C2 - 撤销 M2 的提交" type: REVERSE
merge prod-0.1 id: "M3 - 从dev到main"

可以通过支持mermaid的markdown平台插件来编辑和渲染,也可以简单通过在线平台https://mermaid.live/编辑和导出。