首页/系统/Linux 运维命令速查/diff -u 生成统一格式补丁
文本处理77 条

diff -u 生成统一格式补丁

-u 输出带上下文与文件头的统一格式,是 patch、git apply 与代码评审的标准格式;-ruN 常用于「旧版本目录 → 新版本目录」的整树补丁。

Linux 运维命令速查系统更新于 2026-10-13

diff -u 是什么

diff 比较两个文件或目录的差异,-u 让它输出统一格式(unified diff):带 --- 与 +++ 文件头、@@ 区块位置,以及若干行上下文。这个格式被 patch、git apply 与各类代码评审工具共同采用,是「变更如何被描述与传输」的通用语言。

基本信息

适用平台Linux/Unix(diffutils;GNU diff 与 BSD diff 选项略有差异)
命令语法diff -u 旧文件 新文件 > 变更.patch
常用选项-u 统一格式 -r 递归比较目录 -N 缺失文件当空文件 -q 只报告是否不同 --label 自定义文件名标签
典型组合diff -ruN 旧目录 新目录 > 整树补丁
退出码0 无差异、1 有差异、2 出错,脚本里要注意 1 不是失败

典型使用场景

  • 比较配置改动:把备份与当前配置 diff 一下,确认改了什么
  • 生成补丁交付:把修复整理成 .patch 发给对方应用
  • 代码评审准备:目录对目录比较,先看清整体改动范围
  • 排查「改过但没生效」:确认当前文件确实与预期版本一致
  • 版本核对:确认两台机器上的同一配置是否一致

常用示例

常用示例
diff -u app.conf.bak app.conf > app.patch          # 单文件补丁
diff -ruN conf.old conf.new > site.patch           # 整目录补丁,含新增与删除
diff -u --label a/app.conf --label b/app.conf old new > app.patch   # 固定路径标签
diff -q conf.old/app.conf conf.new/app.conf        # 只想知道是否不同
diff -u <(sort a.txt) <(sort b.txt)                # 排序后再比内容集合

补丁头字段读法

标记含义注意
--- 旧文件被比较的源文件与时间戳路径里通常带 a/ 前缀
+++ 新文件目标文件与时间戳对应 b/ 前缀
@@ -x,y +m,n @@区块在两侧文件中的起止行号应用时的定位依据
以空格开头上下文行两侧一致,用于校验位置
以 - 开头删除的行只在旧文件中存在
以 + 开头新增的行只在新文件中存在
Binary files differ二进制文件无法生成文本差异需改用 cmp 或校验和对比
补丁头里的 a/ b/ 前缀决定应用时 patch 的 -p 参数:a/ b/ 风格对应 -p1,没有前缀的本地文件对应 -p0。用 --label 可以把路径固定成想要的形态,避免因为临时目录不同而生成难以应用的补丁。
比较目录时加 -N:否则新建的文件不会出现在补丁里,应用时会缺文件。git diff --no-index 也可以用来比较两个不在仓库里的目录,输出同样可以用 git apply。
上下文行数可以调:默认 3 行,-U0 只输出改动本身适合机器处理,-U5 或更多上下文适合给人评审。上下文越多,补丁越容易读,但在原文稍有偏移时越难应用成功;给自动化用的补丁可以酌情减少上下文,给人看的则相反。

易错点

  • 补丁里的路径与时间戳是元数据,工作目录不对会「找不到文件」,先看补丁头再定 -p 取值
  • 二进制文件 diff 无意义(只提示 Binary files differ),要用 cmp 或 sha256sum 对比
  • diff 的退出码 1 表示「有差异」而不是失败,脚本里把它当错误会让整条流水线误判
  • 编码或行尾不同(CRLF 与 LF、BOM)会让 diff 认为整个文件都被改写,先统一格式再比较
  • 目录比较不加 -N 时新增文件不会进补丁,应用后会出现文件缺失

数据来源与参考

  • man 1 diff(GNU diffutils 手册)
  • man 1 patch

相关工具

​‌‌​​‌​​​‌‌​‌‌‌‌​‌‌​​​‌‌​‌‌‌​​‌‌​​‌​‌‌‌​​‌‌‌​​​‌​‌‌​‌​​‌​‌‌‌​​​‌​‌‌​‌​​‌​‌‌​​​‌‌​‌‌‌​‌​​​‌‌​‌‌‌‌​​‌​‌‌‌​​‌‌​​​‌‌​‌‌​‌‌‌‌​‌‌​‌‌​‌