自建站 外贸,国外优秀网站欣赏,背景 网站建设,海南工程网站建设参考文档#xff1a;https://juejin.cn/post/7129333439299321887 丹尼尔#xff1a;Hi#xff0c;蛋兄#xff0c;周杰伦都出新专辑了#xff0c;你咋还不更新啊#xff0c;真的打算半年一更啊#xff1f; 蛋先生#xff1a;好像确实是这样#xff0c;要不#xff0… 参考文档https://juejin.cn/post/7129333439299321887 丹尼尔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 vbnet复制代码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 的原因。 丹尼尔除了 recursivegit merge 还有哪些合并策略呢 蛋先生这个就要看你安装的 git 的版本了。git merge 可以指定合并策略。这里有个小技巧你可以故意给个不存在的策略名称git 就会显示出所有可用的策略名称如下所示 sh复制代码$ git merge -s dx Could not find merge strategy dx. Available strategies are: octopus ours recursive resolve subtree. 最后 丹尼尔要不是我买了周杰伦的专辑才想起你也好久没更新了也就不会有今天这一出了 蛋先生感谢提醒合作愉快 丹尼尔真快又到了说再见的时候了 蛋先生See you next time! 丹尼尔看到这里的童鞋们要不点个赞鼓励一下 (▽ ) 作者蛋先生DX 链接https://juejin.cn/post/7129333439299321887 来源稀土掘金 著作权归作者所有。商业转载请联系作者获得授权非商业转载请注明出处。