跳到主内容
d.devtul.fun
EN
工作流 · 2026-09-28

像高手一样对比代码和文本文件

当两个版本的文件不一致时,最糟糕的做法就是并排滚动两个文件、指望自己的眼睛。人会在第 400 行漏掉那个被改掉的字符。正确的姿势是让 diff 工具精确标出变动的部分。下面这套工具,是我每次都会用的。

为什么别直接用眼睛读两个文件

你的大脑擅长理解语义,却不擅长在两大段相似文字里揪出单个被换掉的字符。diff 工具是机械地比,只标出新增、删除和改动的那几段。它更快,而且不会疲劳。把你的判断力用在理解改动上,而不是找改动上。

值得记住的 git diff 选项

最普通的 git diff 显示未暂存的改动。几个参数能把它从嘈杂变得精准:

git diff                 # 工作区相对上次提交的改动
git diff --cached        # 已暂存的改动
git diff --stat          # 只看概要:文件与行数
git diff -w              # 忽略所有空白
git diff --ignore-blank-lines
git diff --word-diff     # 高亮改动的词,而不是整行
git diff --color-words

--word-diff 是最被人低估的一个。当一行只改了一个词时,行模式会把整行标成"删除 + 新增";词模式只标那个词。--color-words 是同一思路,用彩色行内高亮替代分隔符。

跨提交与跨分支对比

你很少只是对比工作区。两种形式覆盖了大多数需求:

git diff main..feature       # feature 上有而 main 上没有的改动
git diff main...feature      # 自 feature 从 main 分出以来的改动
git diff abc123 def456       # 两个指定提交
git diff main~3 main         # main 上最近三次提交

做 PR 评审时你通常想要三点的 main...feature:它展示 feature 相对二者共同祖先引入了什么,而不是两个分支各自 diverge 的全部。两点形式展示的是两个 tip 之间的总差异。

读懂统一格式 diff

diff -u 是补丁的通用语言,也是 Git 所说的格式。会读它,意味着你不用工具也能审一个补丁文件:

--- a/config.yaml
+++ b/config.yaml
 timeout: 30
-retries: 2
+retries: 5
 logging: true

--- 行是旧文件,+++ 是新文件。两者之间还有一行用 at 符号(@)包裹的块头,记录了行范围,比如"旧文件从第 1 行起共 4 行,新文件从第 1 行起共 4 行"——上面为了可读性省略了那行块头。带 - 的行被删了,带 + 的行被加了,没标记的行是保持不变的上下文。一个补丁就是这些块组成的集合。

并排视图与编辑器对比

想看得更细,vimdiff 会用同步的窗格打开两个文件:

vimdiff old.txt new.txt
# 窗格内:]c 下一个差异,[c 上一个差异,:diffupdate 刷新

VS Code、IntelliJ 以及大多数编辑器都内置了对比视图,从文件资源管理器或源代码管理面板就能触发。它们比肉眼强,因为会替你跳到下一个差异处。

经典事故:CRLF 与 LF

用一个 Unix 工具打开 Windows 换行(CRLF)保存的文件,或者反过来,整个文件都会显示为"全变了",尽管内容毫无差异。这就是最常见的"为什么一片红"时刻。先用 git diff -w 确认,再把换行归一化:

# 先看真正的内容差异
git diff -w

# 用 .gitattributes 归一化,以后不再复发
echo "* text=auto eol=lf" > .gitattributes
git add --renormalize .

这行 .gitattributes 告诉 Git 以 LF 存储文本、检出时再转换,于是不同平台的协作者不再为换行吵架。

对比编码不同的文件

一个 GBK 保存的文件和同样内容 UTF-8 保存的文件,字节上不同、人眼却相同。原始 diff 会大喊"全变了"。先统一成一种编码:

iconv -f GBK -t UTF-8 old.txt > old.utf8.txt
git diff --no-index old.utf8.txt new.utf8.txt

git diff --no-index 能对比仓库外任意两个文件,临时比对很方便。

对比二进制类的文件

对图片、压缩包、PDF 这种文本 diff 没意义的文件,退一步用哈希回答"它们到底一不一样":

sha256sum a.bin b.bin

哈希一致就说明字节一致;不一致的话,文本 diff 也帮不上忙,你需要的是领域专用的工具。

代码评审时该比对什么

别逐行读 diff 指望抓 bug。用 diff 定位改动,然后带着意图去评审:

  • 先看意图。改动是否正好做了工单要求的事,有没有夹带私货?
  • 边界与错误。新代码路径、空输入、差一错误、空值处理。
  • 测试。行为有没有被覆盖,而不只是函数被碰了一下。
  • 空白噪声。把格式化混进逻辑改动里,会掩盖真正的编辑 —— 要求拆成单独提交。

文件太大或太敏感,别丢给网页工具

在线 diff 站对公开片段没问题,但任何含秘密的、或体积大的东西都该留在你机器上。日常文件上面这些命令就够;对超大或结构化的数据,文本对比 在本地运行,数据不会离开你的浏览器。

要养成的习惯是:在动用眼睛之前,先伸手去拿 git diff(或 diff -u)。这中间的差别,就是"我觉得这俩一样"和"这里就是改了什么"。

继续阅读