Git 补丁 patch 使用方法

本文最后更新于:2022年11月9日 上午

Git 的 patch 功能支持开发者通过文件与别人分享自己的改动,本文记录 patch 使用方法。

简介

在同一个 git 管理仓库下,当然直接使用 git 的常用命令可以很好地和其他开发者共享工作,当开发者不处在同一个版本管理平台下,或仅作临时修改时,则可以通过 patch 打补丁的方式共享代码改动

  • Git 提供了两种补丁方案,一种是通过 git diff 生成的 .diff 文件,第二种是通过 git format-patch 生成的 .patch 文件。
  • 通过 git diff 生成的文件不含有 commit 信息,可以指定文件生成 diff,也可以指定单个 commit, 多个 commit 生成 。
  • 通过 git format-patch 生成的 .patch 文件 含有 commit 信息。一个 commit 对应一个 patch 文件。

生成 patch

git diff

  • 指定文件生成 patch 文件

  • patch 补丁即为根据 git diff 生成的文本内容文件,最简单的生成方法为 git diff > test.patch

比如我们修改了 A.java、B.java 文件,我们只想将 A.java 文件的修改打成 patch,那么我们可以使用以下的命令:

1
git diff A.java > test.patch

想把所有的修改文件打成 patch,即 A.java、B.java 文件,只需要使用下面的命令:

1
git diff > test.patch
  • 指定 commit id 生成 patch

使用命令行

1
git diff [commit sha1 id] > [diff文件名]

git format-patch

  • 当前分支所有超前 master 的提交:

    1
    git format-patch -M master
  • 某次提交以后的所有 patch:

    1
    git format-patch [commit id]
  • [commit id] 指的是 commit 名,可以通过 git log 查看。

  • 从根到指定提交的所有 patch:

    1
    git format-patch --root 4e16
  • 某两次提交之间的所有 patch:

    1
    git format-patch [commit sha1 id].. [commit sha1 id]
1
git format-patch 365a..4e16

365a4e16 分别对应两次提交的名称

  • 某次提交(含)之前的几次提交:
1
git format-patch –n [commit id]
1
git format-patch –n 07fe

–npatch 数,07fe 对应提交的名称

  • 单次提交即为:
1
git format-patch -1 [commit id]
  • git format-patch 生成的补丁文件默认从1开始顺序编号,并使用对应提交信息中的第一行作为文件名。
  • 如果使用了--numbered-files 选项,则文件名只有编号,不包含提交信息;
  • 如果指定了–stdout 选项,可指定输出位置,如当所有 patch 输出到一个文件;可指定 -o 指定 patch 的存放目录。

应用 patch

git apply

  • 应用 git apply 命令应用 patch 的原理是将 patch 中的改动添加到工作区,应用后会相当于对文件做出修改而不惊动 git
  • git apply 用于 diffformat-patch 输出的 patch
使用步骤
  • 将生成的 patch 文件放在生成时候相同的位置

  • 先检查patch文件格式:

    1
    git apply --stat xxx.patch
  • 测试patch是否能应用到当前分支

    1
    git apply --check xxx.patch
  • 应用此 patch 打补丁

    1
    git apply xxx.patch
  • 这种方式传递的修改将会丢失提交信息和作者信息,但可以兼容非 git 管理的代码。除此之外,git 还提供另一个命令更便于 git 库之间的 patch 传递。

  • 过程中如果有冲突则会停止应用,报错:

    1
    patch does not apply
解决冲突

出现冲突的时候,这个时候需要我们手动解决冲突。

  • 首先,执行以下命令,自动合入 patch 中不冲突的代码,同时保留冲突的部分

    1
    git apply --reject xxxx.patch
  • 同时会生成后缀为 .rej 的文件,保存没有合并进去的部分的内容,可以参考这个进行冲突解决。

git am

  • format-patch 生成的 patch 保存了更多提交信息。因此除了 git apply 之外,还可以用更智能的 git am 命令使用此 patch,会在修改文件的同时将 commit 信息也一起应用到 git 中。

  • git am 可以复现修改,保留作者信息,保留 commit 信息,但 commit ID 无法保留

  • git am 命令会在应用patch 失败时给出详细的错误信息,并允许手动解决冲突,是官方较为推荐的补丁应用方式。

  • 在使用 git am 之前, 需要先 git am --abort 一次,以放弃掉以前的 am 信息。

    不然可能会遇到这样的错误。

    1
    .git/rebase-apply still exists but mbox given.
  • git am 可以一次合并一个文件,或者一个目录下所有的 patch

    1
    git am *.patch
  • 再次声明,am 复现的 commitID 会和之前不同,因此建议在有仓库管理的情况下用 git pull

参考资料


Git 补丁 patch 使用方法
https://www.zywvvd.com/notes/tools/git/git-patch/git-patch/
作者
Yiwei Zhang
发布于
2022年11月8日
许可协议