guide/read-unified-diff.md

unified diff(patch)阅读指南 — 写给代码审查

通过示例逐一解读 git diff 和 patch 文件中的 --- +++ 文件头、@@ hunk 头中的数字、上下文行、No newline at end of file 标记以及 diff --git 扩展头。

最后更新: 2026-09-23

代码审查、问题报告以及通过邮件往来的补丁,大多采用 unified diff 格式。git diffdiff -u 和 GitHub 的“raw diff”用的都是这种格式。初看符号很多,其实规则很简单。

整体结构

diff --git a/greet.py b/greet.pyindex 3b18e51..a6f4c2d 100644--- a/greet.py+++ b/greet.py@@ -1,5 +1,6 @@ def greet(name):-    print("Hello " + name)+    message = f"Hello, {name}!"+    print(message)  def main():     greet("world")

从上到下依次是 git 扩展头文件头---+++)和 hunk(以 @@ 开头的块)。一个文件可以有多个 hunk,一个补丁也可以包含多个文件。

文件头:--- 和 +++

hunk 头 @@ -a,b +c,d @@

@@ -1,5 +1,6 @@ 的意思是:显示“修改前文件从第 1 行起的 5 行,以及修改后文件从第 1 行起的 6 行”。

亲自数一下:上例中的上下文行(以空格开头的行)有 def greet(name):、一个空行、def main():greet("world") 共 4 行。修改前的行数是 4 行上下文加 1 行 -,共 5 行;修改后的行数是 4 行上下文加 2 行 +,共 6 行,所以 hunk 头是 -1,5 +1,6

正文中的三种行

首字符含义
空格两侧都有的上下文行
-只在修改前存在的行(删除)
+只在修改后存在的行(新增)

默认上下文是变更前后各 3 行(可以像 git diff -U5 这样修改)。上下文行用于在应用补丁时找到正确的位置。即使行号稍有偏差,只要上下文吻合,patch 就会平移位置(offset)后应用。

修改了一行时,会表现为一行 - 紧接着一行 +。unified 格式没有专门表示“修改”的符号,所以阅读的诀窍是把连续的 - 块和其下的 + 块上下对照着看。

\ No newline at end of file

@@ -1,2 +1,2 @@ host=example.com-port=8080\ No newline at end of file+port=8080

这表示紧挨着的上一行是文件的最后一行,并且末尾没有换行符。在上例中内容相同,只是修改后的文件多了结尾换行符。详情请参阅 换行符与看不见的差异

git 扩展头

diff --git a/路径 b/路径 之后的几行是 git 特有的附加信息。

审查时的实用技巧

  1. 先看 hunk 头中行数的差值,就能估计变更的规模。-10,7 +10,30 表示增加了 23 行。
  2. 想过滤掉只改了空白的 hunk 时,使用 git diff -w。在查看缩进整理与实际修改混在一起的提交时尤其有用(忽略空白选项)。
  3. 想看行内具体改了什么,可以用 git diff --word-diff,或者把内容放进像本站这样支持行内高亮的工具。
  4. 应用补丁前,先用 git apply --check 文件.patch 确认能否干净地应用。如果不在 git 仓库中,则用 patch -p1 --dry-run < 文件.patch

在本工具中试一试

文本对比工具 的合并视图按与此格式相同的顺序,先显示 - 块再显示 + 块,并再次高亮行内改动的词。点击结果栏中的 patch 按钮即可复制标准的 unified diff 文本,旁边的保存按钮会下载 diff.patch 文件。在关闭所有忽略选项的状态下生成的 patch,可以用 patch -p1git apply 应用到原文件上。

前往文本对比工具