如果 git 只是一行行比较,然后把不同的行报成冲突,那么你在合并的时候可能会遇到大量的冲突;这显然不是一个好的版本管理工具。

本文介绍 git 合并分支的原理。


本文内容

  • git 的冲突表示
  • 三路合并
  • 递归三路合并
  • 快进式合并
    • 参考资料

git 的冲突表示

例如我们有这样的三个提交 a、b、c。a、b 是在 master 上的其他修改,c 是我自己基于 master 上的 a 的修改。

现在,将 master 分支合并到我自己的 t/walterlv 分支:

a 提交:

Console.WriteLine("Hello World!");

b 提交:

Console.WriteLine("Hello Master!");

c 提交:

Console.WriteLine("Hello Walterlv!");

于是现在将 c 提交合并到 master 的时候就会出现冲突。冲突的表示会是这样:

<<<<<<< HEAD
Console.WriteLine("Hello Walterlv!");
=======
Console.WriteLine("Hello Master!");
>>>>>>> master

<<<<<<< 表示冲突开头,>>>>>>> 表示冲突结尾,======= 分隔冲突的不同修改。上面是 HEAD,也就是在合并之前的工作目录上的最近提交;下面是合并进来的分支,通常是来自其他人的修改。

三路合并

加入上面的 b 提交修改的是其他文件。然后依然按照前面的方式进行合并。

当出现冲突时,如果你只能看到不同的两行,那么你根本不知道究竟应该如何修改的。就像下面这样:

<<<<<<< HEAD
Console.WriteLine("Hello Walterlv!");
=======
Console.WriteLine("Hello World!");
>>>>>>> master

只看这点你怎么知道两行应该采用哪一行?这是二路合并算法带来的问题。在此算法下,你的每次拉取代码可能都会带来大量的冲突;这显然是不能接受的。

三路合并算法会找到合并的这两个提交的共同祖先。在这里也就是 a 提交。master 的此文件对 a 没有修改,而当前分支 t/walterlv 对此文件有修改,于是就会应用此分支的修改。

当然,前一节的问题依然会冲突,因为两个分支相对于共同的祖先节点 a 对同一个文件都有修改。

递归三路合并

从上面我们可以看到三路合并解决了二路合并中对于相同行不知道用哪一个的问题。不过实际的 git 提交树会更加复杂,就像下图那样纵横交错:

相比于本文一开始,我们只是新增了两个提交而已,现在 f 提交是我们正在合并的提交。

如果现在找 e 和 d 的共同祖先,你会发现并不唯一,b 和 c 都是。那么此时怎么合并呢?

  1. git 会首先将 b 和 c 合并成一个虚拟的提交 x,这个 x 当作 e 和 d 的共同祖先。
  2. 而要合并 b 和 c,也需要进行同样的操作,即找到一个共同的祖先 a。

我们这里的 a、b、c 只是个比较简单的例子,实际上提交树往往更加复杂,这就需要不断重复以上操作以便找到一个真实存在的共同祖先,而这个操作是递归的。这便是“递归三路合并”的含义。

这是 git 合并时默认采用的策略。

快进式合并

git 还有非常简单的快进式(Fast-Forward)合并。快进式合并要求合并的两个分支(或提交)必须是祖孙/父子关系。例如上面的 e 和 d 并不满足此关系,所以无法进行快进式合并。

在上面的例子合并出了 f 之后,如果将 t/walterlv 合并到 master,那么就可以使用快进式合并。这时,直接将 master 分支的 HEAD 指向 f 提交即完成了合并。当然,可以生成也可以不生成新的 g 提交,但内容与 f 的内容完全一样。


参考资料

  • version control - Why is a 3-way merge advantageous over a 2-way merge? - Stack Overflow
  • Guiffy SureMerge - A Trustworthy 3-Way Merge
  • git merge - Which version of the git file will be finally used: LOCAL, BASE or REMOTE? - Stack Overflow
  • Git merge strategy options & examples - Atlassian Git Tutorial
  • git-merge-base (1) - Find as good common ancestors as possible for a merge

我的博客会首发于 https://walterlv.com/,而 CSDN 和博客园仅从其中摘选发布,而且一旦发布了就不再更新。

如果在博客看到有任何不懂的内容,欢迎交流。我搭建了 dotnet 职业技术学院 欢迎大家加入。

本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。欢迎转载、使用、重新发布,但务必保留文章署名吕毅(包含链接:https://walterlv.blog.csdn.net/),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系。

git 的合并原理(递归三路合并算法)相关推荐

  1. 【转】git生成diff原理:Myers差分算法

    转载:git生成diff原理:Myers差分算法 | 大艺术家_SN 什么是Myers差分算法 举一个最常见的例子,我们使用git进行提交时,通常会使用git diff --cached来查看这次提交 ...

  2. 三路合并 —— Git 学习笔记 17

    三路合并 和其他版本控制系统不同,Git 提供的合并冲突解决方案并不会聪明过头,不会尝试自动将所有问题都解决.Git 的设计哲学是智能判断一个合并是否可以非常容易地自动完成,如果自动化方案不可行,就不 ...

  3. C++非递归合并排序的通用实现算法(附完整源码)

    C++非递归合并排序的通用实现算法 C++非递归合并排序的通用实现算法完整源码(定义,实现,main函数测试) C++非递归合并排序的通用实现算法完整源码(定义,实现,main函数测试) #inclu ...

  4. Git三路合并的隐患

    我觉得最近碰到的这个情况应该不算少见,做一点总结. 这个repository的流程是 remote master 分支受保护,不直接接受push,新增feature通过pull request合并到m ...

  5. 递归排序(合并排序)

    1. 递归排序(合并) 合并排序是分而治之的排序算法.它是一种高效,基于比较的排序算法. 它的工作原理如下: 将列表划分为每次迭代中大约一半大小的子列表,直到每个子列表只有一个元素. 重复合并每个子列 ...

  6. Git工作流程和rebase与合并问题

    我和其他开发人员一起在一个项目上使用Git几个月了. 我有几年的SVN经验,所以我想我给这段关系带来了很多包袱. 我听说Git非常适合分支和合并,到目前为止,我只是没有看到它. 当然,分支很简单,但是 ...

  7. Git笔记(32) 高级合并

    Git笔记(32) 高级合并 1. 合并冲突 1.1. 中断一次合并 1.2. 忽略空白 1.3. 手动文件再合并 1.4. 检出冲突 1.5. 合并日志 1.6. 组合式差异格式 2. 撤消合并 2 ...

  8. git 如何把master分支代码合并到自己的分支

    git 如何把master分支代码合并到自己的分支 master分支的代码领先自己的分支,git 如何把master分支代码合并到自己的分支 1.首先切换到主分支 git checkout maste ...

  9. java合并两个有序链表_JS实现的合并两个有序链表算法示例

    本文实例讲述了JS实现的合并两个有序链表算法.分享给大家供大家参考,具体如下: 将两个有序链表合并为一个新的有序链表并返回.新链表是通过拼接给定的两个链表的所有节点组成的. 示例: 输入:1-> ...

最新文章

  1. 人机猜拳(这是最近的一个总结)
  2. python迭代器两个基本方法可供参考_浅析python迭代器和生成器
  3. 验证身份证和中文名字
  4. Strusts2 高危漏洞又来了,老项目自查起来!
  5. 看完就懂系列—动态规划
  6. AJAX面试题:一个页面实现增删改查(ASP.NET实现)
  7. python中的请求方法_http协议的9种请求方法
  8. SpringBoot里slf4j日志功能的默认实现
  9. SQL数据类型说明和MySQL语法示例
  10. 【RK3399Pro学习笔记】十六、ROS中的常用可视化工具
  11. python 绘制时频图 plt.specgram
  12. 拼多多:钟汉良出任“百亿补贴”星推官
  13. 在dotnetnuke中去掉显示姓名中的空格
  14. 做完自动化测试,但别让不会汇报毁了你...
  15. DB2查询主键、索引、表约束
  16. Java替换中使用正则表达式实现中间模糊匹配
  17. nginx 502 .sock failed (11: Resource temporarily unavailable) while connecting to upstream
  18. php 如何滑动,php 滑动门切换代码示例
  19. 机械专业怎么学matlab,MATLAB在机械类专业课教学中的应用
  20. 屏蔽全部统计代码(51.la cnzz 百度统计 谷歌分析师adsense、屏蔽淘宝客广告代码)的方法...

热门文章

  1. WIZnet最新产品- WIZnet以太网帽已经正式推出
  2. 微信小程序体验版,打开调试工具vConsole
  3. html5上传图片限制大小
  4. DOS 游戏编程二十一条
  5. 各大平板电视厂商的音效技术(转) ---一篇较老的文章
  6. 完整,详细的基于jquery省市三级联动和基于angular的省市三级联动对比
  7. html5 canvas基础
  8. 日本尔必达在苏州建12英寸存储芯片工厂
  9. 人工神经网络的拓扑结构,三层神经网络结构图
  10. chrom 谷歌浏览器无法翻译解决