差异检查器,免费
比较两段文本,即时找出差异。
关于文本比较
此 diff 工具使用最长公共子序列(LCS)算法逐行比较两段文本。新增部分以绿色高亮,删除部分以红色高亮。选择「内联」视图可在一栏中查看所有变化,或选择「并排」视图以同时对比原文和修改文本。
常见用途
- 在提交代码前比较代码变更
- 审阅修订过的文档或合同
- 检查翻译差异
- 校验配置文件的变更
- 比较 API 响应
常见问题
它是按字符比较的吗?
此工具按行比较。只要一行中有任何变化(哪怕只是一个字符),整行都会被标记为已修改。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可以在不同粒度上计算,各有取舍:
- 行级:每行作为一个词元,两行要么完全匹配,要么不匹配。速度快,与程序员编辑代码的方式自然契合,生成
patch(1)可应用的简洁补丁。代价是:修改200字符行中的一个字符,整行都会被标记为已更改。diff、git、SVN及本工具的默认模式。 - 词级:每个以空白分隔的词元为一个单位,因此修改了一个词的行只高亮显示该词。非常适合散文、合同、博客草稿。
git diff --word-diff、Google Docs的「建议」模式、Microsoft Word的「修订」功能以及Diffchecker的词比对模式均使用此方式。 - 字符级:每个Unicode码位为一个单位。能捕捉单字符拼写错误,适用于法律文件的逐字标注修改(一个词的差异可能颠覆含义)。对长输入较慢,长段编辑有时难以阅读。
现代diff界面中的常见模式是:先在行级计算diff,然后对每一对「相邻的删除/添加行」仅针对这两行运行二次词级diff,并高亮显示行内变化。GitHub的PR视图和diff-match-patch库正是这样运作的。
三种常见的diff显示模式
- 统一格式diff(即每个
.patch文件的格式):以@@ -oldStart,oldLen +newStart,newLen @@为首的变更块,默认在变更前后各附三行上下文。起源于1990年前后Wayne Davison为GNU diff添加的-u标志。格式紧凑且可被patch(1)解析,这也是git、内核风格邮件补丁和SVN都采用它的原因。 - 左右对比:原文在左,修改版在右,逐行对齐。
diff -y生成简陋的ASCII版本;Beyond Compare、Meld、WinMerge以及上方的「并排」视图均使用此格式。最适合视觉审阅和校对散文。 - 内联(堆叠式):单列显示,删除行与添加行交错排列。GitHub的PR视图默认采用此格式。对于窄屏幕和小幅改动,空间利用率最高。
实用的git diff变体
git diff:索引区与工作区的对比。git diff --staged:HEAD与索引区的对比。git diff main..feature:分支顶端的对比。main...feature则与合并基准对比,即PR合并后的实际影响范围。git diff --word-diff和--color-words:适合标记语言的词级diff,带彩色高亮。git diff --no-index a.txt b.txt:可对git仓库以外的文件使用,适合将git作为独立diff工具配合patience或histogram算法使用。git diff -w:忽略所有空白字符(对应上方的「忽略空白」复选框)。git diff --histogram:按命令切换diff算法。
何时会用到浏览器diff工具
- 代码审查。粘贴文件的两个版本,扫描变更内容,判断改动是否合理。
- 审查AI编辑的代码。将原始版本与LLM重构后的版本进行对比,发现漂移或幻觉。
- 法律合同逐字标注修改。确认第3版和第4版之间只有已商定的条款发生了变化。
- 翻译质量检查。对比同一段落的两个法语译本,或在只有少量字符串应发生变化时,对比本地化文件的前后版本。
- 配置漂移检测。对比生产环境与预发布环境的
nginx.conf。 - SQL结构比对。从两个数据库导出
CREATE TABLE语句并进行对比,找出缺失索引或列类型漂移。 - 规格漂移检测。对比两个版本的OpenAPI/Swagger YAML,验证破坏性变更是否已记录在案。
- Markdown博客草稿。查看共同作者的修改内容。
- 合规审计。逐月对比隐私政策,供监管机构审查。
- 锁文件分析。对比
package-lock.json或yarn.lock,了解依赖项升级的具体内容。
如实说明的局限性
- 纯文本diff不具备语义感知能力。将
foo全文改名为bar与完全无关的重写在代价上看起来别无二致。difftastic等工具解析语言的AST并生成结构化diff(「添加了函数」、「调换了参数顺序」)。本页面不具备此功能,仅提供纯LCS行级diff。 - 空白字符和行尾符导致虚假diff。CRLF与LF、行尾空格、制表符与空格的差异均会触发。上方的「忽略空白」开关对应git的
-w。 - 二进制文件不适用。diff是文本概念。处理二进制diff有
bsdiff、xdelta或VBinDiff等专用工具。 - 顺序敏感性。行级diff假设文档按行编辑。对于无序CSV或JSON对象键重排的情况,应先排序或规范化再进行对比。
- 移动检测。经典LCS diff无法识别函数在文件内被移动的情况,会将移动显示为一处删除加一处插入。Beyond Compare、Meld和difftastic尝试进行移动检测;本页面不支持。
更多问题
为什么本页面不在变更行内显示字符级高亮?
因为行级处理对大多数使用场景已经足够,且对长输入运行速度快得多。词级行内高亮的两步细化处理是标准做法,但会增加延迟。如果行内差异对您很重要(法律标注修改、散文校对),使用专用的词级工具(包括命令行中的 git diff --word-diff)更合适。
统一格式diff与左右对比有什么区别?
统一格式diff是每个 .patch 文件使用的紧凑、机器可读格式:三行上下文,变更块以 @@ 标记。左右对比则以平行列形式展示两个版本,视觉审阅更轻松,但需要更多横向空间。统一格式适合邮件发送或提交;左右对比适合在宽屏显示器上阅读。
对于源代码,有比Myers更好的算法吗?
对于包含函数移动或大幅重排的源代码,有。patience diff(Bram Cohen,2002年)和histogram diff(git,2010年前后)专门设计为基于有意义的唯一行对齐,而非基于常见行,从而生成可读性更好的输出。两者均可通过 git diff --patience 和 git diff --histogram 使用。difftastic等AST感知工具则更进一步,解析实际的语言结构。
在此粘贴机密文本安全吗?
安全。diff完全在您的浏览器中使用JavaScript LCS实现运行。不会上传任何内容,不分析输入,也不在服务器端记录文本日志。对于NDA文件、内部源代码或未发布的合同条款,这类工具是唯一安全的diff选择;基于云的diff服务会看到您粘贴的所有内容。