差异检查器,免费

比较两段文本,即时找出差异。

您的数据不会离开您的设备

关于文本比较

此 diff 工具使用最长公共子序列(LCS)算法逐行比较两段文本。新增部分以绿色高亮,删除部分以红色高亮。选择「内联」视图可在一栏中查看所有变化,或选择「并排」视图以同时对比原文和修改文本。

常见用途

常见问题

它是按字符比较的吗?

此工具按行比较。只要一行中有任何变化(哪怕只是一个字符),整行都会被标记为已修改。Git 和大多数 diff 工具都采用同样的方式。

有大小限制吗?

没有硬性限制,但很大的文本(超过 10,000 行)可能需要一些时间处理,因为比较完全在您的浏览器中运行。

「diff」的本义

diff描述了如何用最少的插入和删除将一段文本变为另一段文本。实现方法有无数种,最平凡的是「删除A中的每个字符,再插入B中的每个字符」。有用的diff是最短编辑脚本,这与最长公共子序列(LCS)问题互为对偶:找到在两段文本中均按顺序出现的最长行序列,其余部分即为增删内容。大多数diff算法本质上都是LCS算法的不同变体。

有一点值得留意:最长公共子序列不是最长公共子串。子序列保留顺序但不要求连续,因此「ABCDE」和「AXBYCZD」共享子序列「ABCD」,尽管两者之间没有任何连续的三字符段相同。

diff算法简史

最早被广泛使用的文件比对程序是Unix diff,由贝尔实验室的Douglas McIlroy编写,底层算法由James W. Hunt和McIlroy于1976年6月以《贝尔实验室计算科学技术报告第41号》形式发表。McIlroy本人将那四个月的开发过程称为「孤注一掷的努力」。Hunt-McIlroy方法对文件B的每一行进行哈希,索引每个唯一行的出现位置,并寻找最长的单调递增匹配链。该程序随Version 6 Unix发布,此后数十年间大多数Unix系统上 /usr/bin/diff 使用的算法基本维持原状。

Eugene W. Myers于1986年发表了现代行业标准算法,题为「一种O(ND)差分算法及其变体」,刊载于Algorithmica第1卷第2期。Myers将LCS问题重新表述为编辑图上的最短路径问题:将A沿顶部轴排布,B沿侧面轴排布,凡两行匹配处画斜向边,并寻找从左上至右下、非斜向边最少的路径。每条非斜向边对应一次插入或删除;斜向边免费通行。关键在于,该算法的时间复杂度为O((N+M)·D)(D为编辑脚本的大小),即文件越相似运行越。对于典型的版本控制diff,D相比N+M微乎其微,因此Myers在实践中远比最坏情况O(N·M)快得多。他的论文还包含一种利用分治「中间蛇」技巧实现的线性空间优化。Myers算法是GNU diff、git diff、Mercurial、Subversion、jsdiff、Python difflib 及大多数GUI diff查看器的默认实现。

Bram Cohen(后来更以BitTorrent发明者著称)在2002年前后为Bazaar版本控制系统设计了patience diff。其动机在于:Myers diff会对齐任意匹配行,包括极为常见的行,因此在C代码中移动一个函数可能产生杂乱的diff,被移动函数的结束花括号与某个无关函数的结束花括号对齐。Patience diff以每个文件中仅出现一次的行(通常是函数签名、注释头、有特征的日志消息)作为锚点,对这些锚点使用耐心排序计算LCS,再对间隙递归处理。结果是基于有意义的行对齐,阅读源代码时更清晰。Git通过 git diff --patience 支持此算法。Histogram diff是2010年前后加入git的改进版,通过建立行出现频率直方图,优先选择低频锚点而非严格唯一的锚点;从git 2.45起,它在许多配置下已成为默认算法。

莱文斯坦距离与LCS

一个值得区分的相关概念。莱文斯坦距离(Vladimir Levenshtein,1965年)计算将一个字符串变为另一个字符串所需的最少单字符插入、删除和替换次数。基于LCS的diff与之密切相关,但略有不同:经典diff将「修改」视为先删除再插入的配对操作,而非单次替换,因为这更契合以行为单位的文件。莱文斯坦距离回答「这两个字符串有多不同?」,给出一个数字;LCS回答「具体发生了什么变化?」,给出实际的编辑脚本。拼写检查器和「你是否想找」功能需要前者;diff工具需要后者。Damerau-莱文斯坦变体(1964年)在莱文斯坦距离基础上增加了转置操作,用于检测错别字。

粒度:行、词与字符

diff可以在不同粒度上计算,各有取舍:

现代diff界面中的常见模式是:先在行级计算diff,然后对每一对「相邻的删除/添加行」仅针对这两行运行二次词级diff,并高亮显示行内变化。GitHub的PR视图和diff-match-patch库正是这样运作的。

三种常见的diff显示模式

实用的git diff变体

何时会用到浏览器diff工具

如实说明的局限性

更多问题

为什么本页面不在变更行内显示字符级高亮?

因为行级处理对大多数使用场景已经足够,且对长输入运行速度快得多。词级行内高亮的两步细化处理是标准做法,但会增加延迟。如果行内差异对您很重要(法律标注修改、散文校对),使用专用的词级工具(包括命令行中的 git diff --word-diff)更合适。

统一格式diff与左右对比有什么区别?

统一格式diff是每个 .patch 文件使用的紧凑、机器可读格式:三行上下文,变更块以 @@ 标记。左右对比则以平行列形式展示两个版本,视觉审阅更轻松,但需要更多横向空间。统一格式适合邮件发送或提交;左右对比适合在宽屏显示器上阅读。

对于源代码,有比Myers更好的算法吗?

对于包含函数移动或大幅重排的源代码,有。patience diff(Bram Cohen,2002年)和histogram diff(git,2010年前后)专门设计为基于有意义的唯一行对齐,而非基于常见行,从而生成可读性更好的输出。两者均可通过 git diff --patiencegit diff --histogram 使用。difftastic等AST感知工具则更进一步,解析实际的语言结构。

在此粘贴机密文本安全吗?

安全。diff完全在您的浏览器中使用JavaScript LCS实现运行。不会上传任何内容,不分析输入,也不在服务器端记录文本日志。对于NDA文件、内部源代码或未发布的合同条款,这类工具是唯一安全的diff选择;基于云的diff服务会看到您粘贴的所有内容。

相关工具