现象
先来看看这样一个场景,在dev分支上执行git merge feat后,内容会发生怎样的改变?
当时自己乍一看觉得第二行会发生冲突或者被更新为feat2,第4行则自动合并到dev分支中
前段时间的实习开发中就遇到了类似场景,最终的现象是没有发生合并冲突,第二行保持dev2不变,且第4行被更新为4。 也就意味着我的feat开发分支只有一部分新代码被合并到了目标dev分支中
复现
剖析
Git Merge 原理
git merge 基础是 three-way merge
想合并C4、C5,就要先找到两者的共同祖先C2,然后计算C4和C2的差异、以及C5和C2的差异,最后合并这两个差异
回顾问题
首先看下分支提交情况
确定要合并的commit分别是 192f4fbe 和 66a7b503,两者的公共祖先是 57b286a5。 看图可以猜测得到,实际可以通过执行命令
git merge-base 192f4fbe 66a7b503 验证
注意,192f4fbe 这个 commit 由 dev 和 feat 两个分支合并而来,其父commit有两个!
官方文档有对应说明
Figure 24. Three snapshots used in a typical merge.
Instead of just moving the branch pointer forward, Git creates a new snapshot that results from this three-way merge and automatically creates a new commit that points to it. This is referred to as a merge commit, and is special in that it has more than one parent.
通过 git cat-file -p 也可验证
此时答案已经浮出水面了,将 three-way merge 规则代入当前场景进行推导
- 针对第二行,公共祖先值为 feat2,dev分支值为 dev2,feat分支值为 feat2。 只有dev分支做了修改,没有冲突,值为 dev2
- 针对第四行,公共祖先和dev分支都没有值,只有feat分支新增为4,所以也没有冲突,值为4
经验教训
当前组内开发的Git分支模型大致是:
- 生产环境分支是 release
- 测试环境分支是 dev
- 个人开发功能时从 release 中切出 feat_NYRE 分支、从dev中切出 dev_NYRE 分支。开发完后将 feat_NYRE 合并到 dev_NYRE,再将 dev_NYRE 分支合并到 dev 分支中(便于本地解决与dev的冲突)进行测试
按照当前模型,是不能在个人的 dev_NYRE 分支上直接写代码的,只能在 feat_NYRE 分支上开发,然后merge到 dev_NYRE 中。
而我就是在某个需要紧急添加修复代码的时候,直接在 dev_DYRE 分支上进行开发,事后又忘记同步到开发分支 feat_NYRE 中去,从而导致部分代码合并不到 dev_DYRE 中