小工具知识网

当前位置: 首页 > 行业知识 > Git常用命令format-patch

行业知识

Git常用命令format-patch

2026-11-03 20:29:26 来源:互联网转载

Git常用命令format-patch

���们在日常的开发中,需要将自己的改动给到其他同事时,经常需要将改动打补丁 (patch) 后进行处理。

()

git format-patch 是一种帮助开发人员从其 git 提交创建补丁的命令。这个命令很有用,可以用于各种原因,如代

码审查、在分支之间共享代码更改以及向邮件列表提交补丁。对于 git format-patch 的补丁,可以使用 git am 命

()

令进行打入。

本文我们将详细解释 git format-patch 和 git am 命令以及如何有效使用它。

1、format-patch基本用法

$ git format-patch filename.patch

git format-patch 命令可以输出多种格式的补丁。默认情况下,它会以 Git 邮箱格式输出补丁。但是,您可以使用

以下选项来输出其他格式的补丁:

  • --stdout 选项将补丁输出到标准输出,而不是将其写入文件。当您想将补丁传输到其他 Git 命令或工具时,

    此选项非常有用。

  • --mbox 选项以 mbox 格式输出补丁。当通过电子邮件发送补丁时,此格式非常有用。

  • --raw 选项以原始格式输出补丁。当您想向非 Git 存储库应用补丁时,此格式非常有用。

  • --numbered 选项按顺序编号补丁。当您想生成多个补丁并保持它们的特定顺序时,此选项非常有用。

    git format-patch 命令可以通过指定提交范围或逐个指定一个或多个提交来使用。

    format-patch可以基于分支进行打包,也可以基于上几次更新内容打包。

    下面将演示其几中用法。

    # 分支的提交记录$ git log --onelineb9709d6 (HEAD -> branch_a, origin/branch_a) branch_a | update a.txt | add new.txt105370e add f.txt46409d9 add e.txt082352c add d.txtd8f4266 add c.txta5e5961 add b.txt4db21f4 add a.txt
    # 打包最近的一个patch$ git format-patch HEAD^0001-branch_a-update-a.txt-add-new.txt.patch
    # 打包最近的两个patch$ git format-patch HEAD^^0001-add-f.txt.patch0002-branch_a-update-a.txt-add-new.txt.patch
    # 打包最近的三个patch$ git format-patch HEAD^^^0001-add-e.txt.patch0002-add-f.txt.patch0003-branch_a-update-a.txt-add-new.txt.patch# 有几个^就打包几个patch的内容或# 可以使用git format-patch -n,两者是等价的
    # 打包最近的一个patch$ git format-patch -10001-branch_a-update-a.txt-add-new.txt.patch
    # 打包最近的两个patch$ git format-patch -20001-add-f.txt.patch0002-branch_a-update-a.txt-add-new.txt.patch
    # 打包版本n1与n2之间的patch$ git format-patch -n1 -n2# 可以打包版本2,3的patch# 但是测试会把最近4个包都打包出来$ git format-patch -1 -40001-add-d.txt.patch0002-add-e.txt.patch0003-add-f.txt.patch0004-branch_a-update-a.txt-add-new.txt.patch# 测试会把最近3个包都打包出来$ git format-patch -1 -30001-add-e.txt.patch0002-add-f.txt.patch0003-branch_a-update-a.txt-add-new.txt.patch# 测试会把最近2个包都打包出来$ git format-patch -1 -20001-add-f.txt.patch0002-branch_a-update-a.txt-add-new.txt.patch# 测试会把最近1个包都打包出来$ git format-patch -1 -10001-branch_a-update-a.txt-add-new.txt.patch
    # 某次提交以后的所有patch# 082352c add d.txt# 不包含此次提交$ git format-patch -s 082352c# 等价$ git format-patch 082352c0001-add-e.txt.patch0002-add-f.txt.patch0003-branch_a-update-a.txt-add-new.txt.patch
    # 某次提交之前的几次提交# 包含本次提交$ git format-patch -2 082352c0001-add-c.txt.patch0002-add-d.txt.patch
    # 某两次提交之间的所有patch# 不包含start的提交# 46409d9 add e.txt# 082352c add d.txt# d8f4266 add c.txt# a5e5961 add b.txt$ git format-patch a5e5961..46409d90001-add-c.txt.patch0002-add-d.txt.patch0003-add-e.txt.patch
    # 将所有patch输出到一个指定位置的指定文件$ git format-patch commit --stdout > filename.patch$ git format-patch d8f4266 --stdout > d8f4266.patch
    # 经常使用的格式# patch_name的格式类似于0001-bdbfc4ca3.patch$ git format-patch -1 -k commit --stdout > dir_name/patch_name$ git format-patch -1 -k d8f4266 --stdout> /tmp/0001-d8f4266.patch
    # 当前分支所有超前branch_a的提交$ git log --onelineb1786d3 (HEAD -> branch_b, origin/branch_b) branch_b | update a.txt | add new.txtb9709d6 (origin/branch_a) branch_a | update a.txt | add new.txt105370e add f.txt46409d9 add e.txt082352c add d.txtd8f4266 add c.txta5e5961 add b.txt4db21f4 add a.txt# 当前分支比较大$ git format-patch -M origin/branch_a0001-branch_b-update-a.txt-add-new.txt.patch
    # 从origin到指定提交的所有patch$ git format-patch -s --root origin0001-add-a.txt.patch0002-add-b.txt.patch0003-add-c.txt.patch0004-add-d.txt.patch0005-add-e.txt.patch0006-add-f.txt.patch0007-branch_a-update-a.txt-add-new.txt.patch0008-branch_b-update-a.txt-add-new.txt.patch0009-branch_c-update-a.txt-delete-e.txt.patch0010-develop-add-test.txt.patch
    # 要为最后两个提交生成补丁$ git format-patch HEAD~2..HEAD0001-branch_a-update-a.txt-add-new.txt.patch0002-branch_b-update-a.txt-add-new.txt.patch
    # 当前分支和某个分支差异的patch# 当前分支比价大$ git format-patch branch_a0001-branch_b-update-a.txt-add-new.txt.patch

    2、git am基本用法

    在使用 git am 前,首先要使用 git am –abort,用来放弃以前的 am 信息,否则可能会遇到这样的错误:

    .git/rebase-apply still exists but mbox given

    基本语法:

    # 打入patch$ git am filename.patch# 等价于$ git am -k filename.patch

    3、应用patch

    3.1 检查patch能否正常应用

    # 不应用修补程序,而是输出diffstat作为输入$ git apply --stat filename.patch
    # 不应用修补程序,而是查看修补程序是否适用$ git apply --check filename.patch

    3.2 应用patch

    git apply 命令通过修改现有文件或创建新文件来将补丁应用到代码库中。

    $ git apply filename.patch

    git apply 命令还可以与各种选项一起使用,例如 --check 以检查是否能干净地应用补丁,--reject以创建带有

    拒绝更改的补丁文件,以及 --index 以将更改添加到Git索引。

    git am:

    $ git am filename.patch# 一次打入多个文件$ git am *.patch

    4、git format-patch使用案例

    4.1 分支现有的情况

    touch a.txtgit add a.txtgit commit -m "add a.txt"touch b.txtgit add b.txtgit commit -m "add b.txt"touch c.txtgit add c.txtgit commit -m "add c.txt"touch d.txtgit add d.txtgit commit -m "add d.txt"touch e.txtgit add e.txtgit commit -m "add e.txt"touch f.txtgit add f.txtgit commit -m "add f.txt"$ lsa.txt  b.txt  c.txt  d.txt  e.txt  f.txt$ git log --oneline3d47274 (HEAD -> master) add f.txtf21670a add e.txt3be00b5 add d.txt8480613 add c.txt054694f add b.txt6cd2b56 add a.txt$ git show 3d47274commit 3d472749b02447f9e295bc924c95044a40a8ab42 (HEAD -> master)Author: zsx242030 Date:   Mon May 22 21:34:28 2023 +0800    add f.txtdiff --git a/f.txt b/f.txtnew file mode 100644index 0000000..e69de29

    4.2 打包最后一次提交

    $ git format-patch -1 -k 3d472740001-add-f.txt.patch$ cat 0001-add-f.txt.patchFrom 3d472749b02447f9e295bc924c95044a40a8ab42 Mon Sep 17 00:00:00 2001From: zsx242030 Date: Mon, 22 May 2023 21:34:28 +0800Subject: add f.txt--- f.txt | 0 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 f.txtdiff --git a/f.txt b/f.txtnew file mode 100644index 0000000..e69de29--2.14.1.windows.1

    如果有额外信息需要补充,但又不想放在提交消息中说明,可以编辑这些补丁文件,在第一个 --- 行之前添加说

    明,但不要修改下面的补丁正文。这样,其它开发者能阅读,但在采纳补丁时不会将此合并进来。

    4.3 恢复提交到上一次提交

    $ git reset --hard HEAD^HEAD is now at f21670a add e.txt$ git log --onelinef21670a (HEAD -> master) add e.txt3be00b5 add d.txt8480613 add c.txt054694f add b.txt6cd2b56 add a.txt

    4.4 检查patch能否正常应用

    $ git apply --stat 0001-add-f.txt.patch f.txt |    0 1 file changed, 0 insertions(+), 0 deletions(-)
    $ git apply --check 0001-add-f.txt.patch

    4.5 应用patch

    4.5.1 git am
    $ git am 0001-add-f.txt.patchApplying: add f.txt$ git log --onelineb8eafce (HEAD -> master) add f.txtf21670a add e.txt3be00b5 add d.txt8480613 add c.txt054694f add b.txt6cd2b56 add a.txt
    4.5.2 git apply
    # git apply执行之后需要自己提交文件$ git apply 0001-add-f.txt.patch$ lsa.txt  b.txt  c.txt  d.txt  e.txt  f.txt$ git log --onelineb8eafce (HEAD -> master) add f.txtf21670a add e.txt3be00b5 add d.txt8480613 add c.txt054694f add b.txt6cd2b56 add a.txt$ git statusOn branch masterUntracked files:  (use "git add ..." to include in what will be committed)        0001-add-f.txt.patch        f.txtnothing added to commit but untracked files present (use "git add" to track)
    $ git add f.txt$ git commit -m "add f.txt"[master de26d5b] add f.txt 1 file changed, 0 insertions(+), 0 deletions(-) create mode 100644 f.txt$ git log --onelinede26d5b (HEAD -> master) add f.txtf21670a add e.txt3be00b5 add d.txt8480613 add c.txt054694f add b.txt6cd2b56 add a.txt

    如果只是想生效改动而不需要直接提交代码,可以使用 git apply 代替 git am。

    5、git am时有冲突

    5.1 分支情况

    # mastertouch a.txtgit add a.txtgit commit -m "add a.txt"touch b.txtgit add b.txtgit commit -m "add b.txt"$ git log --oneline4ac5e82 (HEAD -> master) add b.txtce93e86 add a.txt
    # featurea$ cat >> a.txt  featurea) update a.txt4ac5e82 (master) add b.txtce93e86 add a.txt
    # featureb$ cat >> a.txt  featureb) update a.txt4ac5e82 (master) add b.txtce93e86 add a.txt

    featurea 分支和 featureb 分支的内容是有冲突的,featurea 先开发完了,然后 featureb 又进行了修改,会导致

    a.txt 文件冲突。

    5.2 featurea打最后一次的patch

    # featureb$ git format-patch -10001-update-a.txt.patch

    5.3 featureb打入patch

    # featurea$ git am 0001-update-a.txt.patcherror: patch failed: a.txt:0error: a.txt: patch does not applyhint: Use 'git am --show-current-patch=diff' to see the failed patchApplying: update a.txtPatch failed at 0001 update a.txtWhen 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".

    由于两个分支都同时操作了某个文件,导致冲突,这种情况下可以使用下面的方法解决冲突:

    1、执行命令 git apply --reject finame.patch 自动合入 patch 中不冲突的代码改动,同时保留冲突的部分。这些

    存在冲突的改动内容会被单独存储到目标源文件的相应目录下,以后缀为 .rej 的文件进行保存。

    $ git apply --reject 0001-update-a.txt.patchChecking patch a.txt...error: while searching for:error: patch failed: a.txt:0Applying patch a.txt with 1 reject...Rejected hunk #1.

    会生成一个 a.txt.rej 文件:

    $ cat a.txt.rejdiff a/a.txt b/a.txt    (rejected hunks)@@ -0,0 +1,6 @@+aa+11+bb+22+cc+33

    2、依据上面生成的 *.rej 文件内容逐个手动解决冲突,然后删除这些 *.rej 文件。

    我们解决 a.txt 文件中的冲突,将内容替换为两者的合并:

    11aaaa1122bbbb2233cccc33

    然后删除 a.txt.rej 文件:

    $ rm -rf a.txt.rej

    完成这一步骤的操作后,我们就可以继续执行 git am 的过程了。

    $ git am 0001-update-a.txt.patchfatal: previous rebase directory .git/rebase-apply still exists but mbox given.# 如果报上面的错误# 解决方法$ git am --abort# 继续执行$ git am 0001-update-a.txt.patcherror: a.txt: does not match indexhint: Use 'git am --show-current-patch=diff' to see the failed patchApplying: update a.txtPatch failed at 0001 update a.txtWhen 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".

    3、执行完上述命令之后执行 git status 查看当前改动过的以及新增的文件,确保没有多添加或少添加文件。

    $ git statusOn branch featureaYou are in the middle of an am session.  (fix conflicts and then run "git am --continue")  (use "git am --skip" to skip this patch)  (use "git am --abort" to restore the original branch)Changes not staged for commit:  (use "git add ..." to update what will be committed)  (use "git restore ..." to discard changes in working directory)        modified:   a.txt

    4、执行命令 git add 添加所有有改动的文件,将文件都添加到暂存区。

    $ git add a.txt

    5、执行命令 git am --continue 或者是 git am --resolved 继续被中断的 patch 合入操作。合入完成后,会有提示

    信息输出。

    $ git am --continueApplying: update a.txt

    6、执行命令 git log 确认合入状态。

    $ git log --oneline1add6d0 (HEAD -> featurea) update a.txt11ea22f update a.txt4ac5e82 (master) add b.txtce93e86 add a.txt

    7、至此,带有冲突代码的 patch 合入就操作完成了。如果要修改 commit 信息,执行 git commit --amend 命令

    即可。

    $ git commit --amend -m "second update a.txt"$ git log --oneline3c27164 (HEAD -> featurea) second update a.txt11ea22f update a.txt4ac5e82 (master) add b.txtce93e86 add a.txt

    5.4 冲突解决的另一种方式

    如果想让 Git 更智能地处理冲突,可以用 -3 选项进行三方合并。如果当前分支未包含该补丁的基础代码或其祖

    先,那么三方合并就会失败,所以该选项默认为关闭状态。一般来说,如果该补丁是基于某个公开的提交制作而成

    的话,你总是可以通过同步来获取这个共同祖先,所以用三方合并选项可以解决很多麻烦。

    还是以上面的冲突为例进行演示:

    # featurea$ git am -3 0001-update-a.txt.patchApplying: update a.txterror: Failed to merge in the changes.Using index info to reconstruct a base tree...M       a.txtFalling back to patching base and 3-way merge...Auto-merging a.txtCONFLICT (content): Merge conflict in a.txtPatch failed at 0001 update a.txtThe copy of the patch that failed is found in: .git/rebase-apply/patchWhen 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".
    $ cat a.txt> update a.txt
    # 解决冲突$ cat a.txt11aaaa1122bbbb2233cccc33
    $ git add a.txt$ git am --continueApplying: update a.txt$ git commit --amend -m "second update a.txt"$ git log --onelinebf7a56b (HEAD -> featurea) second update a.txtb7622ab update a.txt2dc23a3 (master) add b.txtb568674 add a.txt

    对于一次应用多个补丁时所用的 mbox 格式文件,可以用 am 命令的交互模式选项 -i,这样就会在打每个补丁前

    停住,询问该如何操作:

    $ git am -3 -i 0001-update-a.txt.patchCommit Body is:--------------------------update a.txt--------------------------Apply? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all: v--- a.txt | 6 ++++++ 1 file changed, 6 insertions(+)diff --git a/a.txt b/a.txtindex e69de29..c1ba934 100644--- a/a.txt+++ b/a.txt@@ -0,0 +1,6 @@+aa+11+bb+22+cc+33--2.14.1.windows.1Commit Body is:--------------------------update a.txt--------------------------Apply? [y]es/[n]o/[e]dit/[v]iew patch/[a]ccept all: n

    在多个补丁要打的情况下,这是个非常好的办法,一方面可以预览下补丁内容,同时也可以有选择性的接纳或跳过

    某些补丁。

上一篇:前端URL拼接路径参数

下一篇:ifuirt下载攻略,轻松获取,无忧操作!