GitHub上用rebase维护线性提交历史时遇冲突的原因咨询
现象是否正常?
这种冲突是正常现象,完全由rebase and merge的工作机制导致。
原因解析
先明确你的分支链路:master → develop → qa,功能分支通过rebase and merge合并到develop,再尝试用同样方式将develop合并到qa。
第一次合并
develop到qa的逻辑:
初始状态下qa从develop分出,两者提交历史完全一致。用rebase and merge合并时,Git本质是把qa的提交(此时无新提交)“挪”到develop最新提交之后——因为没有差异,所以顺利完成,合并后qa和develop提交历史完全重合。develop合并Feature-branch-2后的变化:
当你用rebase and merge把Feature-branch-2合并到develop时,Git会重写develop的提交历史:它会把Feature-branch-2的所有提交依次放到develop原有提交末尾,生成一批全新的提交(哈希值和原提交完全不同,哪怕代码内容和普通合并结果一致)。第二次合并冲突的根源:
此时qa的提交历史还是第一次合并后的旧develop提交链,而新的develop已是重写后的全新提交链。当再次尝试用rebase and merge把develop合并到qa时,Git会试图把qa的旧提交(即原来的develop提交)变基到新develop的提交后面,但这些旧提交和新develop的提交内容高度重叠,Git无法自动识别这是同一批代码的不同提交版本,因此触发合并冲突。
简单总结:rebase and merge的核心是重写提交历史,这会破坏分支间的历史关联性,导致后续跨分支rebase时出现冲突。如果改用merge commit方式,qa会保留每次合并的节点,不会重写历史,自然不会有这类冲突,但代价是提交历史会出现分叉,无法保持严格线性。
操作步骤截图说明
- 向
develop提交功能分支PR(后续通过rebase and merge合并到develop):
- 向
develop首次成功通过rebase and merge合并到qa:
- 向
develop提交Feature-branch-2的PR(后续通过rebase and merge合并到develop):
- 向
- 第二次从
develop向qa发起PR:
- 第二次从
改用merge commit方式后的qa分支状态
内容的提问来源于stack exchange,提问作者mleko

