核心概念
- 原始文件:应用补丁前的文件。
- 补丁文件:包含了从原始文件到修改后文件的所有差异信息,它通常由
diff命令生成。 - 目标文件:应用补丁后生成的文件,也就是修改后的文件。
patch 命令的工作原理就是读取补丁文件,找到对应的原始文件,然后根据补丁文件中的指令进行修改,最终生成目标文件。

如何创建补丁文件?
在使用 patch 之前,你首先需要有一个补丁文件,补丁文件通常是用 diff 命令创建的。
基本语法:
diff [选项] 原始文件 修改后文件 > 补丁文件名.patch
示例:
假设你有一个 old_file.txt,你想把它修改成 new_file.txt。
-
创建两个文件
(图片来源网络,侵删)echo "Hello, world." > old_file.txt cp old_file.txt new_file.txt echo "Hello, universe." > new_file.txt # 修改新文件
-
使用
diff创建补丁文件diff -u old_file.txt new_file.txt > my_patch.patch
-u选项会生成“统一格式的差异”(unified diff),这是最常用、最易读的格式,包含了上下文信息,即使源文件有微小变动,patch也更容易成功应用。
-
查看补丁文件内容
cat my_patch.patch
你会看到类似下面的内容:
--- old_file.txt 2025-10-27 10:00:00.000000000 +0800 +++ new_file.txt 2025-10-27 10:01:00.000000000 +0800 @@ -1 +1 @@ -Hello, world. +Hello, universe.
这个文件清晰地指出了从
old_file.txt到new_file.txt的具体改动。
(图片来源网络,侵删)
如何使用 patch 命令?
现在你有了 my_patch.patch,就可以用 patch 命令来修改文件了。
应用单个补丁到单个文件
基本语法:
patch < 补丁文件名.patch
示例:
-
先恢复到原始状态
cp old_file.txt another_file.txt cat another_file.txt # 内容是 "Hello, world."
-
应用补丁
patch < my_patch.patch
你会看到输出:
patching file another_file.txt这表示补丁已成功应用到
another_file.txt。 -
验证结果
cat another_file.txt # 内容变成了 "Hello, universe."
应用补丁到整个目录
当你修改了项目中的多个文件时,补丁文件会记录这些文件的路径,使用 patch 的 -p 选项可以正确地处理这些路径。
基本语法:
patch -p[数字] < 补丁文件名.patch
-p(或--strip): 用于剥离路径中的前导目录部分。[数字]表示要剥掉多少层目录。
示例:
假设你的项目结构如下,并且你是在 my_project 目录下运行 diff 命令的:
my_project/
├── src/
│ └── main.c
└── README.md
-
创建补丁 你在
my_project目录下运行diff -uN ...生成的补丁文件,文件路径会包含my_project/或 前缀。 -
应用补丁 你想在另一个地方(比如一个干净的代码副本)应用这个补丁,你首先需要进入该项目的根目录(即包含
src和README.md的目录),然后运行:# 假设补丁文件是 project_changes.patch patch -p1 < project_changes.patch
-p1的意思是:从补丁文件记录的路径中,去掉最前面的一层目录。- 补丁文件里可能是
--- a/my_project/src/main.c - 使用
-p1后,patch会去掉a/my_project/这部分,然后去寻找当前目录下的src/main.c文件进行修改。
- 补丁文件里可能是
如果你的补丁文件路径是
--- a/src/main.c,那么你可能需要用-p0,或者不加-p(默认为-p0)。
常用选项
| 选项 | 全称 | 描述 |
|---|---|---|
-p |
--strip |
剥离路径前缀(应用目录补丁时必备)。 |
-R |
--reverse |
反向应用补丁,如果补丁是“打上去”的,这个选项可以把它“撤销”,非常实用! |
-u |
--unified |
虽然主要是 diff 的选项,但 patch 在处理 -u 生成的补丁时效果最好。 |
-b |
--backup |
在修改文件前,先创建一个备份文件,备份文件名原文件名后加 。 |
--dry-run |
--dry-run |
试运行,只显示 patch 会做什么,但不会真正修改任何文件,用于检查补丁是否能正确应用。 |
-N |
--forward |
忽略已应用的补丁,如果补丁描述的文件已经被修改过,默认 patch 会拒绝,此选项会强制 patch 尝试向前应用补丁。 |
-i |
--input |
从指定文件读取补丁,而不是从标准输入。patch -i my_patch.patch。 |
实用技巧与最佳实践
-
永远先试运行 在不确定补丁是否能顺利应用时,先用
--dry-run。patch --dry-run -p1 < project_changes.patch
如果输出正常,没有报错,说明补丁可以被正确应用。
-
创建备份 使用
-b选项,以防补丁打错,可以轻松恢复。patch -b -p1 < project_changes.patch
这会在修改文件前创建
file.txt.orig或file.txt~这样的备份文件。 -
处理失败的补丁
patch失败,它会生成一个以.rej(reject) 结尾的文件,里面包含了无法应用上的差异部分。- 首先:尝试用
-R选项反向应用补丁,撤销已经成功修改的部分。 - 然后:手动检查
.rej文件和修改后的文件,手动合并差异,这通常意味着原始代码已经被其他人修改过,需要手动解决冲突。
- 首先:尝试用
-
从源码安装软件 这是
patch命令最经典的应用场景之一,很多开源软件在编译前,需要官方提供补丁来修复特定问题或启用特定功能。# 1. 解压源码包 tar -xvf some-software-1.0.tar.gz cd some-software-1.0 # 2. 应用官方提供的补丁文件 patch -p1 < ../some-software-1.0-important-fix.patch # 3. 继续正常的编译安装流程 ./configure make sudo make install
| 命令 | 作用 | 示例 |
|---|---|---|
diff |
创建补丁 | diff -u old.txt new.txt > fix.patch |
patch |
应用补丁 | patch < fix.patch |
patch -R |
撤销补丁 | patch -R < fix.patch |
patch --dry-run |
测试补丁 | patch --dry-run -p1 < fix.patch |
掌握 diff 和 patch 是进行代码协作、系统管理和软件定制的重要技能,希望这份详细的解释能帮助你完全理解并熟练使用它们!
