Git如何处理自动可解决的合并?执行git merge前如何预判处理逻辑?
Git merge自动合并逻辑及场景处理规则
核心基础逻辑
Git所有自动合并都基于三路合并算法:会先找到两个待合并分支的最近共同祖先commit,同时比对「共同祖先版本」、「当前所在分支版本」、「待合并分支版本」三个版本的差异,仅对三个版本存在差异的部分做处理。
合并结果和执行merge时所处的分支有关,主要体现在两点:
- 快进合并场景下,指针移动方向完全由当前所在分支决定
- 出现合并冲突时,文件中
<<<<<<< HEAD标记的内容是当前所在分支的修改,>>>>>>> 待合并分支名标记的是待合并分支的修改
无冲突的非快进自动合并结果为两个分支修改的叠加,和合并方向无关。
三个场景的具体处理结果(基于切换到master后合并test的前提)
- 场景1:master的file.txt内容和test版本完全不同
两个分支对file.txt的修改完全覆盖了相同的行范围,Git无法判断优先保留哪一方的修改,会直接触发合并冲突,需要手动选择保留的内容。 - 场景2:master的file.txt存在test版本没有的文本内容
分两种情况判断:- 这部分独有内容是master分支在共同祖先之后新增的,且test分支从未修改过对应行范围:Git会自动保留master的独有内容,同时合并test分支其他无冲突的修改,不会触发冲突
- 这部分内容是test分支在共同祖先之后主动删除的,且master分支保留/修改了对应内容:属于同一行范围的修改冲突,会触发冲突需要手动处理
- 场景3:master的file.txt内容比test版本更少
分两种情况判断:- 缺失的内容是master分支在共同祖先之后主动删除的,且test分支从未修改过对应行范围:Git会自动保留master的删除操作,同时合并test分支其他无冲突的修改
- 缺失的内容是test分支在共同祖先之后新增的,且master分支从未修改过对应行范围:Git会自动把test新增的内容合并到文件中,最终文件同时包含master原有内容和test新增内容,不会触发冲突
- 缺失的内容是master主动删除、但test分支修改了这部分内容:属于同一行范围的修改冲突,会触发冲突需要手动处理
提前预判合并逻辑的通用方法
你可以在执行merge前通过以下命令手动比对差异,提前判断合并结果:
- 先获取两个分支的最近共同祖先hash:
git merge-base master test - 分别查看两个分支从共同祖先之后的修改内容:
- 查看master分支的修改:
git diff <刚才拿到的祖先hash> master -- file.txt - 查看test分支的修改:
git diff <刚才拿到的祖先hash> test -- file.txt
- 查看master分支的修改:
- 对比两个diff的修改行范围:
- 如果修改的行范围完全不重叠:Git会自动合并两边的修改,不会有冲突
- 如果修改的行范围存在重叠:会触发合并冲突,需要手动处理
快进合并与非快进自动合并的差异
- 快进合并:待合并分支是当前分支的直接后代(当前分支从共同祖先之后没有任何新提交),Git不会生成新的合并commit,只是把当前分支的指针直接移动到待合并分支的最新commit,最终文件内容和待合并分支完全一致,不存在内容合并的判断逻辑。
- 非快进可自动合并:两个分支从共同祖先之后都有新提交,但修改的内容行范围没有重叠,Git会生成新的合并commit,自动把两边的修改整合到一起。
内容的提问来源于stack exchange,提问作者Crazy circuit
相关产品推荐
相关产品推荐

