guide/diff-algorithms.md

Myers、Patience、Histogram — diff 算法比较

结合示例比较 git diff 的 --diff-algorithm 选项(myers、minimal、patience、histogram)各自如何工作,以及结果为何不同。

最后更新: 2026-09-23

即使比较的是同样两个文件,采用不同的 diff 算法,结果也可能不同。它们给出的都是“正确”的 diff,只是在把哪些行视为相同并配对这一点上做法不同,因而可读性不同。git 通过 --diff-algorithm 选项提供四种算法。

取值git 文档中的说明特点
myers (default)基本的贪心(greedy)算法,目前的默认值速度快,结果通常接近最小
minimal多花时间以生成尽可能小的 diff总是最小;输入很大时可能较慢
patiencepatience diff 算法以唯一出现的行为锚点
histogram扩展 patience,支持出现次数少的公共元素以少见的行为锚点

也可以使用 git diff --patiencegit diff --histogram 这样的简写选项,并可通过 git config diff.algorithm histogram 修改默认值。

Myers:寻找最小编辑的默认算法

Myers 算法寻找使删除与新增数量最少的路径(原理见 diff 的工作原理)。问题出在把哪些行视为相同存在多种选择时。代码里有大量非常常见的行,如 }{、空行、return,因此算法即使把语义上毫无关系的行配成一对,编辑数也可能同样是最小的。

同一处修改,两种结果

假设像下面这样,在函数 fg 之间新插入了函数 h。下面两个 diff 都是新增 4 行,编辑数相同。

@@ -1,6 +1,10 @@ int f() {     return 1; }++int h() {+    return 3;+}  int g() {     return 2;
@@ -1,5 +1,9 @@ int f() {     return 1;+}++int h() {+    return 3; }  int g() {

第一个把新函数完整地显示出来;第二个则把原有函数 f 的右括号当成了新函数的括号,新增部分被切得很别扭。这种形态由搜索顺序造成。较新的 git 会根据缩进把变更区块的边界移到更易读的位置(--indent-heuristic,默认启用),从而修正其中很大一部分。

Patience:先对齐唯一的行

patience diff 由 Bram Cohen 提出,它先寻找在两个文件中都各自只出现一次的行。像函数声明 int h() { 这样唯一的行,对应关系是确定的。算法从这些唯一的行中选出顺序一致的最长列表(最长递增子序列)作为锚点,然后只对锚点之间的小区间再做比较。

Histogram:优先考虑少见的行

histogram 算法最初在 JGit(用 Java 编写的 git 实现)中开发,后来也被纳入 git。patience 只看“恰好出现一次的行”,而 histogram 会统计每一行的出现次数,选出出现最少的行作为锚点。因此,即使没有唯一的行,它也能以相对少见的行为基准。git 文档将其描述为“扩展 patience 算法以支持出现次数少的公共元素”。实际使用中,它和 patience 一样,往往能较好地保留代码结构。

该用哪一种

无论使用哪种算法,按结果还原出的文件都相同。改变的只是人阅读时看到的样子。

在本工具中

本站先用 Myers 系列算法按行比较,再根据变更行之间内容的相似度把它们配对为“修改”,并对行内内容再比较一次。因此,即使按行比较的结果切得有点别扭,也能一眼看出哪个词改了。把上面的例子放进 文本对比工具,比较一下合并视图和分栏视图的显示效果吧。结果的阅读方法整理在 unified diff 阅读指南 中。

前往文本对比工具