必须用 -u 选项,因为默认 diff 输出 ed 风格指令无上下文、难读且无法直接打补丁;-u 输出统一格式,含文件信息、上下文及明确增删标记,便于人眼识别和 patch 自动应用。

直接用 diff -u 就能看清具体哪几行变了,还能生成可直接用 patch 应用的补丁文件。别用默认不带参数的 diff,输出难读、没法直接打补丁。
为什么必须用 -u 选项看差异
默认 diff file1 file2 输出的是 ed 风格指令(比如 3c3、7d6),它告诉你“怎么改 file1 才能得到 file2”,但不显示上下文,人眼很难定位实际改了什么内容。而 -u 输出的是统一格式(unified diff),包含:
- 文件名和时间戳(--- / +++ 行)
- 差异块前后的几行上下文(默认 ±3 行)
- 每个变更点明确标出 -(删)和 +(增)
这样一眼就能看出“原内容是什么、改成什么样了”,也方便后续用 patch 自动应用。
diff -u 生成补丁文件的实操要点
生成补丁本质就是把 diff -u 的输出重定向到文件,但有三个关键细节容易出错:
- 顺序不能反:
diff -u old.txt new.txt > fix.patch,old.txt必须在前,否则补丁方向反了,patch会报错Reversed (or previously applied) patch detected! - 路径要相对一致:如果
old.txt和new.txt在不同目录下,补丁里会带绝对或相对路径;应用时若目录结构不匹配,得用-p参数剥离前缀,比如patch -p1 < fix.patch会去掉开头一个层级(如src/main.c→main.c) - 别漏掉
.patch后缀:虽然不是强制,但加后缀能避免误执行;且多数 IDE 或 CI 工具(如 GitHub Actions)默认识别*.patch
比较目录时 diff -ur 的坑
用 diff -ur dir1 dir2 看整个目录差异时,注意:
-
-r是递归,但默认只比同名文件;如果dir1有a.txt而dir2没有,diff不会提示“文件缺失”,只会静默跳过 —— 这时候得加-q先扫一遍:diff -rq dir1 dir2,它会列出所有不一致的文件名(含新增/删除) -
-u和-r一起用(即-ur)时,每个文件的差异块之间用diff -ur分隔,但补丁文件仍可被patch -p1正确处理 - 如果目录里有二进制文件(如图片、编译产物),
diff会直接报Binary files X and Y differ,不会输出具体内容;真要确认二进制是否一致,该用cmp或sha256sum
补丁应用前必须验证的两件事
patch 命令本身不校验原始文件是否匹配补丁预期,容易 silently 失败:
- 先用
patch --dry-run -p1 < fix.patch测试:如果有行号偏移、内容不匹配,它会报Hunk #1 FAILED at XX,而不是直接改坏文件 - 确保目标文件没被其他进程修改过:如果
old.txt在生成补丁后又被手动编辑过,哪怕只多了一个空格,patch也可能失败或部分应用,导致状态不一致
真正麻烦的不是命令敲错,而是补丁生成时的上下文(比如某行前后空格、换行符、编码)和应用时环境不一致 —— 这类问题往往要对比 diff -u 输出里的 @@ 行范围和实际文件内容才能定位。


















