网易首页 > 网易号 > 正文 申请入驻

码住!Git Merge 小技巧

0
分享至

作者:dxweixiao,腾讯CSIG前端开发工程师

丹尼尔:Hi,蛋兄,周杰伦都出新专辑了,你咋还不更新啊,真的打算半年一更啊?

蛋先生:好像确实是这样,要不,择日不如撞日,今天聊聊?

丹尼尔:好啊,那聊些啥呢?

蛋先生:最近搞的事情需要实现两个应用项目的代码合并,逻辑就完全参照 git merge 的基本原则,那就聊聊 git merge 吧

丹尼尔:git merge 我倒是经常用,不过却从未关心过它内部是怎么实现的。那你跟我讲一下它的工作原理呗。

合并的基本原则: three-way

蛋先生:git merge 的基本原则是 three-way

丹尼尔:3 条路?啥东东?

蛋先生:简单讲就是有 3 个分支。假设就叫 a, o, b,其中 a 和 b 都来自于 o,如下所示:

丹尼尔:嗯,然后呢?

蛋先生:现在 a 和 b 要进行合并。假设你当前在 a 分支,然后运行 git merge b,那么合并结果是根据 a, o, b 之间的内容比较结果分析得出的。

丹尼尔:哦,嗯,比较逻辑是什么呢?

蛋先生:Very 简单。只要 a, o, b 任意两个的内容一致,就放弃 o 的内容;如果都不一样,就冲突。如下图所示

丹尼尔:只要...

蛋先生:我还是列举下所有的场景吧,然后你就会明白了

1). o == a, o != b

假设内容如下: o: daniel a: daniel b: dx-b

a merge b 的结果: dx-b

2). o == b, o != a

假设内容如下: o: daniel a: dx-a b: daniel

a merge b 的结果: dx-a

3). a == b, o != a

假设内容如下: o: daniel a: dx-ab b: dx-ab

a merge b 的结果: dx-ab

4). o != a, o != b, a != b

假设内容如下: o: dx-o a: dx-a b: dx-b

a merge b 的结果: 冲突

<<<<<<< a dx-a ======= dx-b >>>>>>> b

丹尼尔:哦,懂了,就是以 o 为基准来判断该保留哪个分支的内容,如果判断不了,就提示冲突,自行解决。

蛋先生:没错

丹尼尔:上面是假设 3 个分支要对比的文件都存在,那如果某个分支的文件被删除或有新文件,该怎么处理呢?

蛋先生:你可以把缺少的文件当作空内容文件来处理。嗯,这样说好像也不太准确。我还是再列举下场景吧。以下假设要比较各分支的 dx.txt 文件

1). o 有, a 有, b 没

  • 假设 1: o == a

合并结果:删除文件

因为 o == a,所以取 b 的结果
  • 假设 2: o != a

合并结果:保留文件,内容为 a 的内容

因为 o, a, b 互不相同,结果为冲突,但 b 没有文件,所以冲突结果直接取 a 的内容

2). o 有, a 没, b 有

与(1)类似,相当于把 a 换成 b

3). o 有, a 没, b 没

合并结果:删除文件

a == b,所以取 a 或 b 的结果,即删除

4). o 没, a 有, b 没

合并结果:取 a 的内容

o == b,所以取 a 的内容

5). o 没, a 没, b 有

与 (4) 类似,相当于把 a 换成 b

6). o 没, a 有, b 有

  • 假设 1: a == b

合并结果:取 a(或 b)的内容

  • 假设 2: a != b

合并结果:冲突

丹尼尔:漂亮,这下我完全搞懂了合并逻辑了。

Diff 的实现算法:最长公共子序列

丹尼尔:但我还有一个疑问,对比文件内容的时候,是一行一行内容对比的吧

蛋先生:那是当然了

丹尼尔:那如果我加多一行,故意错开,岂不是都对不上了

蛋先生:当然...是不会犯这样低级的错误的。在实现 diff 的时候,是利用了 LCS(Longest Common Sequence,即最长公共子序列)的算法。用下图来简单了解一下

假设有两个字符串 S1 和 S2,那它们的最长公共子序列就是 abcd

S1: "abcde" S2: " a1bc2d"

丹尼尔:哦。但这是字符串,该怎么应用到文件内容的 diff 上呢?

蛋先生:把图转一转,每个方块代表文件的一行内容,是不是就一样了

丹尼尔:是哦。通过 LCS 的算法,就算我故意错开了行,也不影响比较,因为相同内容的行总是能对得上

蛋先生:恩,不过这里只是两个文件的比较,而 three-way 是三个文件内容的比较,要稍微多做点事

丹尼尔:能讲得具体一点吗?

蛋先生:上个图吧。假设我们要合并 a 和 b 分支的 dx.txt 文件,先使用 LCS 来计算三个分支该文件内容的最长公共子序列(下图就是连线的内容为a,c,e的行),然后以这些子序列对各个文件的内容行进行分割,分割的块(下图中杂乱曲线的部分)就是不相同的部分,对这些块的内容进行 three-way 分析,即可得出这些内容块合并后的结果

丹尼尔:恩,终究还是有图有真相啊,图一看就明白了。讲了这么多,要不直接 show 下代码吧

蛋先生:一样的思路,可以有各种各样的实现。我自个实现了一个简单的版本,请移步到 codepen.io 查看。也可以去瞧瞧 node-diff3 的代码实现,它比较严谨,毕竟是一个可上生产的模块

丹尼尔:好咧,等会就去观摩观摩

小插曲

丹尼尔:我刚刚特意上网查了一下,git merge 的默认策略是 recursive,为啥叫递归呢?

蛋先生:还记得 git merge 的基本原则是 three-way 吗?a 和 b 的共同祖先是 o,但有些情况下,a 和 b 的共同祖先可能不止一个,这时就需要将这些共同祖先通过 three-way 进行合并,这个动作会一直往上递归到根祖先分支,所以这也是策略叫 recursive 的原因。

丹尼尔:除了 recursive,git merge 还有哪些合并策略呢?

蛋先生:这个就要看你安装的 git 的版本了。git merge 可以指定合并策略。这里有个小技巧,你可以故意给个不存在的策略名称,git 就会显示出所有可用的策略名称,如下所示:

$ git merge -s dxCould not find merge strategy 'dx'.Available strategies are: octopus ours recursive resolve subtree. 最后

丹尼尔:要不是我买了周杰伦的专辑,才想起你也好久没更新了,也就不会有今天这一出了

蛋先生:感谢提醒,合作愉快

丹尼尔:真快,又到了说再见的时候了

蛋先生:See you next time!

特别声明:以上内容(如有图片或视频亦包括在内)为自媒体平台“网易号”用户上传并发布,本平台仅提供信息存储服务。

Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.

相关推荐
热点推荐
世界杯:荷兰点球3-4无缘16强!创队史最差战绩 摩洛哥踢加拿大

世界杯:荷兰点球3-4无缘16强!创队史最差战绩 摩洛哥踢加拿大

念洲
2026-06-30 11:55:27
女篮功臣终身未婚,26岁强制退役,病逝时还穿着队服

女篮功臣终身未婚,26岁强制退役,病逝时还穿着队服

乐趣纪史
2026-06-30 19:22:34
赵继伟地位改变,世预赛郭士强确立三大核心,首发阵容呼之欲出

赵继伟地位改变,世预赛郭士强确立三大核心,首发阵容呼之欲出

徐觳解说
2026-07-01 00:38:18
WTT大冷门,王曼昱被横扫,诞生3个意想不到,打削球还看孙颖莎

WTT大冷门,王曼昱被横扫,诞生3个意想不到,打削球还看孙颖莎

南海浪花
2026-07-01 10:21:49
韩旭WNBA总裁杯第2冠!自由人力克王牌加冕 斯图尔特MVP

韩旭WNBA总裁杯第2冠!自由人力克王牌加冕 斯图尔特MVP

醉卧浮生
2026-07-01 09:25:44
黎巴嫩真主党真不经打:经营近二十年的博福特岭,几小时就陷落

黎巴嫩真主党真不经打:经营近二十年的博福特岭,几小时就陷落

民间马后炮
2026-06-29 01:51:44
不统而统!社科院专家首提新概念,或成两岸统一“第三条路”?

不统而统!社科院专家首提新概念,或成两岸统一“第三条路”?

时光漫游志
2026-06-30 06:34:18
世界杯“点球之王”爆冷出局!德国曾在12码罚球点“打遍群雄无敌手”

世界杯“点球之王”爆冷出局!德国曾在12码罚球点“打遍群雄无敌手”

上游新闻
2026-06-30 13:32:37
日本赢不了巴西,问题不出在技术,出在最后5分钟

日本赢不了巴西,问题不出在技术,出在最后5分钟

乐乐哥
2026-06-30 13:24:51
科里纳谈德国进球被吹:进攻球员没有奔球而去,干扰防守就是犯规

科里纳谈德国进球被吹:进攻球员没有奔球而去,干扰防守就是犯规

懂球帝
2026-07-01 10:13:28
中纪委怒批:公务员也是人,正常生活不应问责处理!

中纪委怒批:公务员也是人,正常生活不应问责处理!

细说职场
2026-06-24 10:55:30
姆巴佩:我不会看射手榜,相信梅西还会继续进球

姆巴佩:我不会看射手榜,相信梅西还会继续进球

懂球帝
2026-07-01 08:37:30
马伊琍带火了一种“极简风”穿法:白T恤+黑半裙,时髦减龄还高级

马伊琍带火了一种“极简风”穿法:白T恤+黑半裙,时髦减龄还高级

蓓小西
2026-07-01 10:07:49
世界杯:英格兰vs刚果(金)

世界杯:英格兰vs刚果(金)

足球赛事交流解析
2026-07-01 09:00:03
4年2400万美金!尼克斯第2笔签约达成!冠军中锋成抢手货

4年2400万美金!尼克斯第2笔签约达成!冠军中锋成抢手货

世界体育圈
2026-06-30 16:51:23
74个国家免签,唯独让中国交五倍签证费,选亚运会开幕前何意味?

74个国家免签,唯独让中国交五倍签证费,选亚运会开幕前何意味?

深析古今
2026-06-30 13:54:46
美国大满贯:首个冷门诞生,2大世界冠军出局,王曼昱大战佐藤瞳

美国大满贯:首个冷门诞生,2大世界冠军出局,王曼昱大战佐藤瞳

潋滟晴方DAY
2026-06-30 14:11:15
王晶没说谎,58岁久居日本农村的郑伊健,印证了他的评价

王晶没说谎,58岁久居日本农村的郑伊健,印证了他的评价

陈意小可爱
2026-06-20 15:03:28
降维打击到底有多恐怖 看网友讲述 原来换个招数可以这样玩学到了

降维打击到底有多恐怖 看网友讲述 原来换个招数可以这样玩学到了

侃神评故事
2026-06-30 18:15:03
日本没料到,模拟攻击辽宁舰会惹这么大麻烦,中俄轰炸机都出动了

日本没料到,模拟攻击辽宁舰会惹这么大麻烦,中俄轰炸机都出动了

半壁胭脂色
2026-07-01 07:31:46
2026-07-01 12:11:00
腾讯技术工程
腾讯技术工程
不止于技术
1416文章数 601关注度
往期回顾 全部

科技要闻

美国放行,Anthropic两款顶级模型将恢复

头条要闻

老人获帮助后车祸去世 孙子:视频里他笑得合不拢嘴

头条要闻

老人获帮助后车祸去世 孙子:视频里他笑得合不拢嘴

体育要闻

德国足球,脸都不要了

娱乐要闻

罗晋大孤山素颜照,秃顶白发引热议

财经要闻

新氧贷款:宣传年化15%,实际顶格24%

汽车要闻

奇瑞风云A9探店 五个理由一定来看看

态度原创

房产
游戏
健康
本地
公开课

房产要闻

突发!万亿资本巨头,悄悄杀入海棠湾!

魔兽世界:WLK25人奥杜尔最无争议的5大极品,你觉得还有哪些?

狂吃“糯叽叽”小心肠梗阻!

本地新闻

贵州小城的新目标:举办“村超”世界杯!

公开课

李玫瑾:为什么性格比能力更重要?

无障碍浏览 进入关怀版