Git生成patch和合并patch

git patch 可以将项目中的一些 commit 提取出来,生成 .patch 文件。其他分支或其他项目可以合并这些 .patch 文件,并生成与原 commit 一致的提交记录。

git patch 对于解决在错误的分支上开发了新功能特别有效。

生成 patch

使用 git format-patch 命令生成所需要的 patch。

选择超前于 Master 分支的所有提交:

git format-patch -M master

选择某个提交之后的所有提交(不包括该次提交 35ec56):

git format-patch 35ec56

选择某两个提交之间的所有提交(不包括提交 35ec56,但包括 c388c0):

git format-patch 35ec56...c388c0

选择某个提交之前的n次提交(包括该次提交 35ec56):

git format-patch -n 35ec56

选择单个提交(将 n 指定为 1):

git format-patch -1 35ec56

命令执行后,每个 commit 会生成为一个 .patch 文件,文件带有编号,编号顺序为 commit 的顺序。

合并 patch

显示 patch 的文件改动状态:

git apply --stat 0001-.patch

检查 patch 是否正常执行,大概相当于 dry-run。该命令能够检查出 patch 合并时一些常见的问题,比如 patch 中对文件进行了修改但文件不存在,patch 中创建文件但项目中已存在同名的文件。

git apply --check *.patch

合并 patch。在合并过程中 Git 如果检测到冲突,会报错并停止合并接下来的 patch,不会自动回滚,冲突处理参见下一节。

git am *.patch

冲突处理

下面是一个遇到冲突的例子:

 ~ git am *.patch
Applying: add supervisor 配置
Applying: add Nginx配置
Applying: 更新配置
Applying: 修改博客LOGO
error: aaa.txt: does not exist in index
Patch failed at 0004 修改博客LOGO
Use 'git am --show-current-patch' to see the failed patch
When you have resolved this problem, run "git am --continue".
If you prefer to skip this patch, run "git am --skip" instead.
To restore the original branch and stop patching, run "git am --abort".

可以看出,在编号为 0004 的 patch 执行时,Git 在当前项目中无法找到 aaa.txt 文件。

解决冲突的方式,一种是简单粗暴的使用 git am —abort 命令,中断合并 patch,并会滚到合并 patch 之前的版本;

另一种是手动合并该 patch,并对冲突的文件手动修改,再继续 am 命令。这种处理方式不会对 commit 记录造成影响,重点介绍该方法。

首先,手动合并该 patch。对于没有冲突的文件,会自动更新(不会自动加入缓冲区);对于有冲突的文件,会生成一个 .rej 冲突参考文件。

git apply --reject 0004.patch

.rej 文件中包含了冲突文件的 diff 信息,参考该 .rej 文件对冲突的文件进行修改,.rej 文件参考完之后可以删除。

修改好冲突的文件之后,把冲突的文件和之前更新的文件加入缓冲区:

git add aaa.txt bbb.txt

告诉 Git 冲突已解决,继续合并 patch

git am --resolved

执行时,会根据缓冲区中对文件的修改,生成本次冲突 patch(0004)的 commit。

参考链接

目录