ChatGPT解决这个技术问题 Extra ChatGPT

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

我需要编写一个脚本,为 SHA-1 提交号列表创建补丁。

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

有没有办法只为特定的 SHA-1 值生成补丁?


P
Peter Mortensen

尝试:

git format-patch -1 <sha>

或者

git format-patch -1 HEAD

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

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

使用以下命令应用补丁:

git am < file.patch

应用补丁:git apply --stat file.patch # 显示统计信息。 git apply --check file.patch # 申请前检查错误。 git am < file.patch # 最后应用补丁。
如果最后一次提交是来自另一个分支的合并,它似乎不起作用。
使用 git am -3 < file.patch 应用三向合并,这样您就可以在之后使用 git mergetool(或手动编辑)found here 解决冲突。
此命令也仅适用于提交中的特定文件:git format-patch -1 <sha> path/to/file.js 这将创建一个仅包含 file.js 差异的补丁
如果您解释了 -1 的目的,将会非常有帮助
F
Farid

从特定 SHA-1 哈希的最顶层 提交生成补丁:

git format-patch -<n> <SHA-1> --stdout > <name_of_patch_file>.patch

单个补丁文件中 head 的最后 10 个补丁:

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

能否请您提供第一个命令的示例
git format-patch -1 HEAD 将为最近的提交生成补丁
请原谅我问这个问题,所以当它是 -2 时,它会为最近的 2 次提交生成补丁,还有一件需要澄清的事情是命令 got format-patch -2 HEAD 与行 git format-patch HEAD~2 相同
P
Peter Mortensen

假设您在提交 1 之后有提交 id 2,您将能够运行:

git diff 2 1 > mypatch.diff

其中 2 和 1 是 SHA-1 哈希值。


谢谢dookehster的回复。这意味着我需要脚本来找到我感兴趣的提交之前的提交。我希望我可以避免这种情况。
@elle,不,你不 - git diff hash^ hash 。 “hash^”给出了之前的提交。 (但是,当然,manojlds 的答案更好)
git show HEAD > mypatch.diff 在提交时也应该这样做。
@dookehester 是正确的还是相反的,git diff 1 2
这将无法在 diff 中包含任何二进制文件。
3
3 revs, 3 users 78%

此命令(如 @Naftuli Tzvi Kay 已建议),

git format-patch -1 HEAD

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

将为格式化为类似于 Unix 邮箱格式的最新提交生成补丁文件。

- - 从最上面的 次提交中准备补丁。

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

git am -3k 001*.patch

请参阅:man git-format-patch


谢谢!我认为值得注意的是,应用补丁将创建一个带有以 [PATCH] 为前缀的提交消息的提交。不过这很容易解决
现象级的。 OP,你还没有接受这个,因为......? @MikeS 不,与任何其他 git 格式的补丁相比,它不会,至少如果用户以正确的方式应用它。
@MikeS 我并没有真正调查原因,但是省略了 -k 标志 (git am -3) 修复了这个表单(没有 PATCH[0/10] 提交消息)。 Git 版本 2.20.1.windows.1
i
iamantony
git format-patch commit_Id~1..commit_Id  
git apply patch-file-name

快速简单的解决方案。


也不要忘记在应用补丁之前调用 git apply --check patch-file-name。这将有助于避免问题。
V
VonC

如果您想确保(单个提交)补丁将应用于特定提交之上,您可以使用新的 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 (``)commit bb52995commit 3de6651commit fa2ab86commit ded2c09(2016 年 4 月 26 日)。
(由 Junio C Hamano -- gitster --commit 72ce3ff 中合并,2016 年 5 月 23 日)

格式补丁:添加“--base”选项来记录基础树信息

维护人员或第三方测试人员可能想知道补丁系列适用的确切基础树。教 git format-patch 一个“--base”选项来记录基础树信息并将其附加在第一条消息的末尾(求职信或系列中的第一个补丁)。基本树信息由“基本提交”和零个或多个“必备补丁”组成,这是一个众所周知的提交,它是项目历史稳定部分的一部分,其他人都在使用它们,这是众所周知的尚未成为“基本提交”一部分的正在运行的补丁,需要在可以应用补丁之前以拓扑顺序在“基本提交”之上应用。 “基本提交”显示为“base-commit:”,后跟提交对象名称的 40 位十六进制。 “必备补丁”显示为“prerequisite-patch-id:”,后跟 40 位十六进制“补丁 id”,可以通过“git patch-id --stable”命令传递补丁来获得。

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

请参阅 Stephen Boyd (akshayka)commit a8f6855commit 6f93d26(2019 年 4 月 26 日)。
(由 Junio C Hamano -- gitster --commit 8202d12 中合并,2019 年 6 月 13 日)

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

每次我们在 diff.c 中处理补丁 ID 生成代码中的块时,我们都不会刷新上下文,但是当我们使用“补丁 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 (bertwesarg)commit edefc31(2019 年 10 月 11 日)。
(由 Junio C Hamano -- gitster --commit f1afbb0 中合并,2019 年 10 月 18 日)

格式补丁:创建输出目录的主要组件签名者:Bert Wesarg

'git format-patch -o' 相当于 'mkdir ' 而不是 'mkdir -p ',正在纠正中。

避免在可能有安全隐患的主要目录上使用“adjust_shared_perm”。通过像 'git init' 那样暂时禁用 'config.sharedRepository' 来实现。

在 Git 2.25(2020 年第一季度)中,“git rebase”在设置 format.useAutoBase 配置变量时无法正常工作,已更正。

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

rebase:修复 format.useAutoBase 损坏报告人:Christian Biesinger 签名人:Denton Liu 使用 format.useAutoBase = true,运行 rebase 导致错误:致命:无法获取上游,如果您想自动记录基本提交,请使用 git branch --set-upstream-to 来跟踪远程分支。或者您可以通过 --base= 手动指定基本提交错误:git 在准备补丁以重播这些修订时遇到错误:ede2467cdedc63784887b587a61c36b7850ebfac..d8f581194799ae29bf5fa72a98cbae98a1198b12 结果,git 无法重新设置它们。通过始终将 --no-base 从 rebase 传递给 format-patch 来解决此问题,这样 format.useAutoBase 的效果就会被否定。

在 Git 2.29(2020 年第四季度)中,“git format-patch(man) 学会将“whenAble”作为 format.useAutoBase 配置变量的可能值,以便在以下情况下变为无操作自动计算的基数没有意义。

请参阅 Jacob Keller (jacob-keller)commit 7efba5f(2020 年 10 月 1 日)。
(由 Junio C Hamano -- gitster --commit 5f8c70a 中合并,2020 年 10 月 5 日)

格式补丁:教 format.useAutoBase "whenAble" 选项签名者:Jacob Keller

format.useAutoBase 配置选项的存在是为了允许用户默认为 format-patch 启用“--base=auto”。由于尝试格式化旧补丁时出现意外失败,这有时会导致工作流程不佳: $ git format-patch -1 致命:基本提交不应该在修订列表中用户请求 --base 不一定立即显而易见(因为这是在配置中,而不是在命令行中)。我们确实希望 --base=auto 在它无法提供合适的基础时失败,因为如果格式化的补丁在请求时不包含基础信息,这同样会令人困惑。教授 format.useAutoBase 一种新模式,“whenAble”。此模式将导致 format-patch 在可能的情况下尝试包含基本提交。但是,如果找不到有效的基本提交,则 format-patch 将继续格式化补丁而无需基本提交。为了避免使用 --base 使另一个分支名称无法使用,不要教 --base=whenAble 或 --base=whenable。相反,重构 base_commit 选项以使用回调,并依赖全局配置变量 auto_base。这确实意味着用户无法从命令行请求此可选的基本提交生成。然而,这可能不是太有价值。如果用户手动请求基本信息,他们将立即被告知未能获取合适的基本提交。这允许用户就是否继续该格式做出明智的选择。添加测试以涵盖 --base 的新操作模式。

git config 现在在其 man page 中包含:

默认为格式补丁。也可以设置为“whenAble”以允许启用 --base=auto 如果合适的基础可用,但跳过添加基础信息,否则格式不会消失。

在 Git 2.30(2021 年第一季度)中,“git format-patch --output=there(man) 没有按预期工作,而是崩溃了。

现在支持该选项。

请参阅 Jeff King (peff)commit dc1672dcommit 1e1693bcommit 4c6f781(2020 年 11 月 4 日)。
(由 Junio C Hamano -- gitster --commit 5edc8bd 中合并,2020 年 11 月 18 日)

格式补丁:支持 --output 选项 报告人:Johannes Postler 签名人:Jeff King

我们从未打算在格式补丁中支持 diff 的 --output 选项。并且直到 baa4adc66a (parse-options: disable option abbreviation with PARSE_OPT_KEEP_UNKNOWN, 2019-01-27, Git v2.22.0-rc0),才无法触发。我们首先解析格式补丁选项,然后将其余部分交给 setup_revisions()。在提交之前,我们接受“--output=foo”作为“--output-directory=foo”的缩写。但之后,我们不检查缩写,并且 --output 被传递给 diff 代码。这会导致无意义的行为和错误。 diff 代码将在 rev.diffopt.file 中打开一个文件句柄,但我们将用我们为每个单独的补丁文件打开的句柄覆盖它。所以 --output 文件总是空的。但更糟糕的是,差异代码还设置了 rev.diffopt.close_file,因此 log_tree_commit() 将自行关闭文件句柄。然后 cmd_format_patch() 中的主循环将尝试再次关闭它,从而导致双重释放。最简单的解决方案是使用格式补丁禁止 --output,因为没有人打算让它工作。但是,我们不小心记录了它(因为格式补丁包含差异选项)。它确实适用于 "git log"(man) ,它将整个输出写入指定的文件。也很容易使它适用于格式补丁:它实际上与 --stdout 相同,但指向特定文件。我们可以通过“close_file”标志检测到 --output 选项的使用(请注意,我们不能使用 rev.diffopt.file,因为 diff 设置会将其设置为 stdout)。所以我们只需要取消设置该标志,而不必做任何其他事情。我们的情况与 --stdout 完全一样(请注意,我们不会 fclose() 文件,但 stdout 情况也不会;退出程序会为我们解决这个问题)。


M
Maik Lowrey

使用 commit-id 创建一个 git 补丁

$ git format-patch -1 commit-id

此命令使用以下文件名创建补丁

0001-commit-message.patch

要应用补丁:

$ git am 0001-commit-message.patch

您能否澄清 -1 论点?我无法在文档或在线找到对它的引用。
@brainbag 我在手册页中找到它:-<n> Prepare patches from the topmost <n> commits
如果您将 -1 更改为任何 >1 数字,您仍然会在每次提交时获得补丁。这甚至如何回答这个问题?
P
Peter Mortensen

要从特定提交(不是最后一次提交)生成补丁:

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

P
Peter Mortensen

如果你只想区分指定的文件,你可以使用:

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


P
Peter Mortensen

在我的 Mercurial 背景下,我打算使用:

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

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


P
Peter Mortensen

仅针对特定 SHA-1 值生成补丁的方法是什么?

这很简单:

选项 1。git show commitID > myFile.patch

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

注意:将 commitID 替换为实际的提交 ID(SHA-1 提交代码)。


选项1是完全错误的,与问题无关。
选项 2 也是无效命令。 You will get error like: git a5f4bcaeb7fa7de27ae79d9522332e872889bbf0~1..a5f4bcaeb7fa7de27ae79d9522332e872889bbf0 git: 'a5f4bcaeb7fa7de27ae79d9522332e872889bbf0~1..a5f4bcaeb7fa7de27ae79d9522332e872889bbf0' is not a git command.请参阅“git --help”。请在发布答案之前检查
选项 1 实际上是我在搜索如何执行此操作时正在寻找的。 +1 来自我!
@AnshumanManral 我不太明白为什么 git show 是错误的且不相关;除了声称之外,也许可以解释一下。