如何为特定提交生成git补丁?


1231

我需要编写一个脚本来为SHA1提交编号列表创建补丁。

我尝试使用git format-patch <the SHA1>,但是自SHA1以来,每次提交都会生成一个补丁。生成几百个补丁后,我不得不终止该过程。

有没有一种方法只能为特定的SHA1生成补丁?

Answers:


1989

尝试:

git format-patch -1 <sha>

要么

git format-patch -1 HEAD

根据上面的文档链接,该-1标志告诉git补丁中应包含多少个提交;

-<n>

     从最顶层的提交准备补丁。


使用以下命令应用补丁:

git am < file.patch

210
应用补丁程序: git apply --stat file.patch#显示统计信息。 git apply --check file.patch#申请前检查错误。 git am < file.patch#最后应用补丁。
阿德里安

3
如果最后一次提交是来自另一个分支的合并,则似乎不起作用。
Lex Li

2
要使用CRLF行尾将修补程序应用于文件:git am --keep-cr < mypatch.patch
MichaelSchmeißer,2015年

40
使用git am -3 < file.patch使用三路合并,这将让你使用解决冲突申请git mergetool之后(或手动编辑)在这里找到
马特

6
这个命令也适用于从呈交只是一个特定的文件(S):git format-patch -1 <sha> path/to/file.js这将创建一个补丁仅包含的diff为file.js
克里斯托夫Dombi

281

为了从特定sha1哈希的最高提交生成补丁:

git format-patch -<n> <SHA1>

从头开始的最后10个补丁在一个补丁文件中:

git format-patch -10 HEAD --stdout > 0001-last-10-commits.patch

2
你可以请好心提供了第一个命令的例子
Kasun Siyambalapitiya

1
git format-patch -1 HEAD将为最新提交生成补丁
Sriram Murali

1
请原谅我提出这个要求,所以当它-2生成最近2次提交的补丁时,需要澄清的是命令got format-patch -2 HEAD与命令行相同git format-patch HEAD~2
Kasun Siyambalapitiya

85

假设您在提交1之后拥有提交ID 2,则可以运行:

git diff 2 1 > mypatch.diff

其中2和1是SHA哈希。


谢谢dookehster的回复。这意味着我需要脚本来查找感兴趣的内容之前的提交。我希望可以避免这种情况。
elle

11
@elle,不,你不是- git diff hash^ hash。“ hash ^”给出优先的提交。(但是,当然,manojlds的答案更好)
J-16 SDiZ 2011年

2
git show HEAD > mypatch.diff在提交时,应该执行相同的操作。
andho 2015年

1
@dookehester是正确还是相反,git diff 1 2
Kasun Siyambalapitiya

1
这将无法在差异文件中包含任何二进制文件。
stickj

55

此命令(如@ Naftuli Tzvi Kay所建议):

git format-patch -1 HEAD

替换HEAD为特定的哈希或范围。

会为最新提交(类似于UNIX邮箱格式)生成补丁文件。

-<n> -从最顶层的提交准备补丁。

然后,您可以通过以下方式以邮箱格式重新应用补丁文件:

git am -3k 001*.patch

请参阅:man git-format-patch


谢谢!我认为值得注意的是,应用补丁程序将创建一个带有[PATCH]前缀的提交消息的提交。不过,这很容易解决
Mike S

2
现象。OP,您还没有接受,因为...?@MikeS不,git至少在用户以正确的方式应用它的情况下,它不会比任何其他格式的补丁都多。
underscore_d

2
@MikeS我并未真正调查原因,但省去了-k标志(git am -3)来修复了此表单(没有PATCH[0/10]提交消息)。Git版本2.20.1.windows.1
jannis,

30
git format-patch commit_Id~1..commit_Id  
git apply patch-file-name

快速简单的解决方案。


5
也不要忘记git apply --check patch-file-name在应用补丁之前打电话。这将有助于避免问题。
iamantony

16

如果您想确保(单次提交)修补程序将应用在特定的提交之上,则可以使用新的git 2.9(2016年6月)选项 git format-patch --base

git format-patch --base=COMMIT_VALUE~ -M -C COMMIT_VALUE~..COMMIT_VALUE

# or
git format-patch --base=auto -M -C COMMIT_VALUE~..COMMIT_VALUE

# or
git config format.useAutoBase true
git format-patch -M -C COMMIT_VALUE~..COMMIT_VALUE

请参见Xiaolong Ye(``)的提交bb52995提交3de6651提交fa2ab86提交ded2c09(2016年4月26日
(通过合并JUNIOÇ滨野- gitster-提交72ce3ff 5月23日2016)

format-patch:添加' --base'选项以记录基础树信息

维护者或第三方测试者可能想知道补丁程序系列适用的确切基础树。教git format-patch一个' --base'选项来记录基础树信息,并将其附加在第一条消息的末尾(求职信或系列中的第一个补丁)。

基本树信息包含“基本提交”(这是众所周知的提交,它是其他所有人都在其中进行工作的项目历史的稳定部分的一部分)以及零个或多个众所周知的“必备补丁程序”尚不属于“基本提交”的飞行中的修补程序,需要先以拓扑顺序在“基本提交”之上应用,然后才能应用这些修补程序。

“基本提交”显示为“ base-commit:”,后跟提交对象名称的40进制。
“先决条件补丁”显示为“ prerequisite-patch-id:”,后跟40进制的“补丁ID”,可以通过使补丁通过“ git patch-id --stable”命令获得。


Git 2.23(2019年第三季度)将对此进行改进,因为“ --base”选项的“ ”选项以不稳定的方式format-patch计算了patch-ids必备补丁,而更新后的更新方式与“ git patch-id --stable” 兼容。

参见Stephen Boyd()的commit a8f6855commit 6f93d26(2019年4月26日(通过合并JUNIOÇ滨野- -提交8202d12,2019年6月13日)akshayka
gitster

format-patch:使--base patch-id输出稳定

我们并不是在每次在中处理patch-id生成代码中的块时都刷新上下文 diff.c,但是当我们使用' patch-id'工具生成“稳定的”补丁ID时,我们就是在这样做。

让我们将类似的逻辑从头移植patch-id.c进去,diff.c以便在为“ format-patch --base=”类型的命令调用生成补丁ID时获得相同的哈希值。


在Git 2.24(2019年第四季度)之前,“ git format-patch -o <outdir>”等效于“ mkdir <outdir>”而非“ mkdir -p <outdir>”,该问题已得到纠正。

请参阅Bert Wesarg()的commit edefc31(2019年10月11日(由Junio C Hamano合并--commit f1afbb0中,2019年10月18日)bertwesarg
gitster

format-patch:创建输出目录的主要组件

签名人:Bert Wesarg

'git format-patch -o'等效于'mkdir'而不是'mkdir -p',正在纠正。

避免在adjust_shared_perm前导目录上使用“ ”,这可能会带来安全隐患。通过暂时禁用' config.sharedRepository'like' git init'做到。


在Git 2.25(2020年第1季度)中,设置了配置变量后,“ git rebase”无法正常工作format.useAutoBase,该问题已得到纠正。

请参阅Denton Liu()的commit cae0bc0commit 945dc55commit 700e006commit a749d01commit 0c47e06(2019年12月4日(由Junio C Hamano合并--71a7de7号提交中,2019年12月16日)Denton-L
gitster

rebase:修复format.useAutoBase破损

报告人:克里斯蒂安·比辛格
签名人:刘登顿

使用format.useAutoBase = true,运行rebase会导致错误:

fatal: failed to get upstream, if you want to record base commit automatically,
please use git branch --set-upstream-to to track a remote branch.
Or you could specify base commit by --base=<base-commit-id> manually
error:
git encountered an error while preparing the patches to replay
these revisions:

ede2467cdedc63784887b587a61c36b7850ebfac..d8f581194799ae29bf5fa72a98cbae98a1198b12

As a result, git cannot rebase them.

通过始终--no-base从rebase 传递给format-patch来解决此问题,以消除的影响format.useAutoBase


8

要从特定提交(而不是最后一次提交)生成路径:

git format-patch -M -C COMMIT_VALUE~1..COMMIT_VALUE

4

如果只需要diff指定的文件,则可以:

git diff master 766eceb-连接/> 000-mysql-connector.patch


0

由于我的工作背景,我将使用:

git log --patch -1 $ID > $file

但是我现在正在考虑使用git format-patch -1 $ID


-5

仅针对特定SHA1生成补丁的方法是什么?

很简单:

选项1。 git show commitID > myFile.patch

选项2。 git commitID~1..commitID > myFile.patch

注意:替换commitID为实际的提交ID(SHA1提交代码)。


3
选项1完全是错误的,与问题无关。
Anshuman Manral

3
选项2也是无效的命令。您将收到类似以下错误:git a5f4bcaeb7fa7de27ae79d9522332e872889bbf0〜1..a5f4bcaeb7fa7de27ae79d9522332e872889bbf0 git:'a5f4bcaeb7fa7de27ae79d9522332e872889ebebebebde027 参见'git --help'。发布答案之前请检查
Anshuman Manral
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.