Git patch生成以及更新的命令

本文详细介绍了如何使用gitformat-patch生成补丁文件,并通过gitapply命令应用这些补丁。包括如何从特定提交生成补丁、应用补丁、处理冲突以及在应用过程中遇到问题时的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

1 使用git format-patch生成所需要的patch:
当前分支所有超前master的提交:
git format-patch -M master
某次提交以后的所有patch:
git format-patch 4e16 --4e16指的是commit名
从根到指定提交的所有patch:
git format-patch --root 4e16
某两次提交之间的所有patch:
git format-patch 365a..4e16 --365a和4e16分别对应两次提交的名称
某次提交(含)之前的几次提交:
git format-patch –n 07fe --n指patch数,07fe对应提交的名称
故,单次提交即为:
git format-patch -1 07fe
git format-patch生成的补丁文件默认从1开始顺序编号,并使用对应提交信息中的第一行作为文件名。如果使用了-- numbered-files选项,则文件名只有编号,不包含提交信息;如果指定了--stdout选项,可指定输出位置,如当所有patch输出到一个文件;可指定-o <dir>指定patch的存放目录;


2应用patch:
先检查patch文件:git apply --stat newpatch.patch
检查能否应用成功:git apply --check newpatch.patch
打补丁:git am --signoff < newpatch.patch

(使用-s或--signoff选项,可以commit信息中加入Signed-off-by信息)


如果应用patch出现问题:

比如,一个典型的git am失败,可能是这样的:
$ git am PATCH
Applying: PACTH DESCRIPTION
error: patch failed: file.c:137
error: file.c: patch does not apply
error: patch failed: Makefile:24
error: libavfilter/Makefile: patch does not apply
Patch failed at 0001 PATCH DESCRIPTION
When you have resolved this problem run "git am --resolved".
If you would prefer to skip this patch, instead run "git am --skip".
To restore the original branch and stop patching run "git am --abort".

正如你所见,如果冲突发生,git只是输出上述信息,然后就停下来。一个小冲突会导致整个patch都不会被集成。

处理这种问题的最简单方法是先使用 git am --abort,然后手动的添加此patch, patch -p1 < PATCH,手动解决掉代码冲突,最后使用 git commit -a 提交代码。但是这样做有个问题就是你会失去PATCH中原本包含的commit信息(比如From,Date,Subject,Signed-off-by等)。应该有一种更聪明的方法。

在 .git/rebase-apply 目录下,存放着相应的补丁文件,名字是“0001” (在更新的git版本中,存放补丁文件的目录名有所改变,这里使用的git版本是 1.7.4.1)。

事实上,你可以使用 git apply 命令打patch(git apply 是git中的patch命令)。如同使用 patch -p1 命令时一样,然后手动解决代码冲突(检视生成的 .rej 文件,与冲突文件比较,修改冲突内容,并最终把文件加入到index中):

$ git apply PATCH --reject
$ edit edit edit
(译注:根据.rej文件手动解决所有冲突)
$ git add FIXED_FILES
$ git am --resolved

就这么简单!
想多一些解释,好吧。git am 并不改变index,你需要使用 git apply --reject 打patch(保存在 .git/rebase-apply),手动解决代码冲突,(译注:使用 git status 列出所有涉及文件),把所有文件(不仅仅是引起冲突的文件)添加到(git add)index,最后告诉 git am 你已经解决(--resolved)了问题。这样做的好处是你不需要重新编辑commit信息。而且,如果你正在打的是一系列patch(就是说你在打的是多个patch,比如 git am *.patch)你不需要使用 git am --abort,然后又 git am。

参考资料:

git-format-patch(1) - Linux man page http://linux.die.net/man/1/git-format-patch

How to create and apply a patch with Git http://ariejan.net/2009/10/26/how-to-create-and-apply-a-patch-with-git

 

转自: 点击打开链接

### 如何解析由 Git 生成patch 文件 Git 生成patch 文件是一种文本文件,用于描述代码库中两个版本之间的差异。这些差异通常包括文件的新增、修改和删除操作,以及具体的行号和内容变化。以下是关于如何解析 Git 生成patch 文件的详细说明: #### Patch 文件的基本结构 Patch 文件通常包含以下几部分: 1. **头部信息**:描述补丁的基本信息,例如提交者、提交时间、提交消息等。 2. **文件差异信息**:列出每个受影响文件的差异。 3. **具体行差异**:显示每行的具体变化(添加、删除或修改)。 #### 示例 Patch 文件格式 以下是一个典型的 patch 文件示例[^2]: ```diff diff --git a/Test.java b/Test.java --- a/Test.java +++ b/Test.java @@ -1,3 +1,4 @@ public class Test { - public static void main(String[] args) { + // Added a comment + public static void main(String[] args) { System.out.println("Hello World"); } } ``` #### 解析 Patch 文件的关键点 1. **文件路径**: - `diff --git a/Test.java b/Test.java` 表示文件 `Test.java` 的旧版本(`a/Test.java`)和新版本(`b/Test.java`)之间的差异[^2]。 2. **文件状态**: - `--- a/Test.java` 和 `+++ b/Test.java` 分别表示旧文件和新文件的状态。如果文件被删除,则 `---` 后可能为空;如果文件是新增的,则 `+++` 后可能为空[^2]。 3. **行号和内容变化**: - `@@ -1,3 +1,4 @@` 表示旧文件从第 1 行开始,共 3 行的内容被替换为新文件从第 1 行开始,共 4 行的内容。 - `-` 开头的行表示删除的行,`+` 开头的行表示新增的行,未加符号的行表示未发生变化的上下文内容[^2]。 4. **提交信息**(可选): - 如果使用 `git format-patch` 生成patch 文件,通常会在文件开头包含提交信息,例如提交者、日期、提交消息等[^3]。 #### 使用工具解析 Patch 文件 除了手动解析外,还可以通过工具来处理 patch 文件。以下是几种常见的方式: 1. **应用 Patch 文件**: - 使用 `git apply` 或 `git am` 将 patch 文件应用到代码库中。`git apply` 只会应用代码更改,而 `git am` 还会保留原始的提交信息[^1]。 ```bash git apply path/to/patchfile.patch ``` 2. **查看 Patch 内容**: - 使用 `cat` 或 `less` 查看 patch 文件内容。 ```bash cat path/to/patchfile.patch ``` 3. **生成 Patch 文件**: - 使用 `git diff` 或 `git format-patch` 生成 patch 文件。例如: ```bash git format-patch -1 HEAD -o output_directory/ ``` #### 注意事项 - 如果 patch 文件中的路径与当前代码库的路径不匹配,`git apply` 可能会失败。可以通过 `--directory` 参数指定路径偏移。 - 某些 patch 文件可能包含二进制文件的差异,这种情况下无法直接查看具体内容,但可以通过工具应用它们。 ```python # 示例:读取 patch 文件并提取关键信息 def parse_patch(file_path): with open(file_path, 'r') as file: lines = file.readlines() for line in lines: if line.startswith('diff --git'): print(f"File difference: {line.strip()}") elif line.startswith('@@'): print(f"Line changes: {line.strip()}") elif line.startswith('-'): print(f"Deleted line: {line.strip()}") elif line.startswith('+'): print(f"Added line: {line.strip()}") # 调用函数 parse_patch('path/to/patchfile.patch') ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值