当我使用git format-patch
时,它似乎不包含合并。如何执行合并,然后将其作为一组补丁通过电子邮件发送给某人?
例如,假设我合并了两个分支并在合并之上执行另一个提交:
git init
echo "initial file" > test.txt
git add test.txt
git commit -m "Commit A"
git checkout -b foo master
echo "foo" > test.txt
git commit -a -m "Commit B"
git checkout -b bar master
echo "bar" > test.txt
git commit -a -m "Commit C"
git merge foo
echo "foobar" > test.txt
git commit -a -m "Commit M"
echo "2nd line" >> test.txt
git commit -a -m "Commit D"
这将创建以下树:
B
/ \
A M - D
\ /
C
现在我尝试检查初始提交并重播上述更改:
git checkout -b replay master
git format-patch --stdout master..bar | git am -3
这会产生合并冲突。在这种情况下,git format-patch master..bar
仅生成3个补丁,省略“Commit M”。我该如何处理?
-Geoffrey Lee
答案 0 :(得分:28)
似乎没有一个解决方案可以生成单个提交({1}},但是FWIW,您可以格式化包含有效合并提交的补丁,适合/兼容git format-patch
:
显然,Git Reference指南提供了第一个提示:
git log -p 显示每次提交时引入的补丁
[...]这意味着对于任何提交,您都可以获得提交给项目的提交补丁。您可以通过使用特定提交SHA运行
git am
来执行此操作,也可以运行git show [SHA]
,它告诉Git在每次提交后放置补丁。 [...]
现在,git-log的手册页给出了第二个提示:
git log -p
...显示包含更改差异的历史记录,但仅限于“主分支”透视图,跳过来自合并分支的提交,并显示合并引入的完整变更差异。只有当遵循严格的合并所有主题分支的策略时,这才有意义。
反过来又意味着具体步骤:
git log -p -m --first-parent
这可以按预期应用:
# Perform the merge:
git checkout master
git merge feature
... resolve conflicts or whatever ...
git commit
# Format a patch:
git log -p --reverse --pretty=email --stat -m --first-parent origin/master..HEAD > feature.patch
同样,这不会包含单个提交,但会从合并提交中生成git am feature.patch
兼容的修补程序。
当然,如果您首先不需要git am
兼容补丁,那么它会更简单:
git am
但我想你已经想到了,如果你在这里登陆这个页面,你实际上正在寻找我上面描述的解决方法/解决方案。 ;)
答案 1 :(得分:9)
请注意,裸git log -p
不会显示合并提交“M”的任何修补程序内容,但使用git log -p -c
会将其哄骗。但是,git format-patch
不接受与-c
接受的--combined
(或-cc
,git log
)类似的任何论据。
我也很难过。
答案 2 :(得分:5)
如果您检查前两个补丁的内容,您将看到问题:
diff --git a/test.txt b/test.txt
--- a/test.txt
+++ b/test.txt
@@ -1 +1 @@
-initial file
+foo
diff --git a/test.txt b/test.txt
index 7c21ad4..5716ca5 100644
--- a/test.txt
+++ b/test.txt
@@ -1 +1 @@
-initial file
+bar
从您当时正在处理的分支(foo和bar)的角度来看,这两个提交都删除了“初始文件”行并完全替换了其他内容。 AFAIK,当你生成一个具有重叠变化的非线性进程的补丁时,没有办法避免这种冲突(在这种情况下你的分支提交B和C)。
人们通常使用补丁来添加单个功能或修复已知良好的先前工作状态的错误 - 补丁协议根本不够复杂,无法像Git本身那样处理合并历史。如果你想让某人看到你的合并,你需要在分支之间推/拉而不是退回差异/补丁。
答案 3 :(得分:5)
扩展sun
的答案,我找到了一个命令,可以生成一系列补丁,类似于git format-patch
会产生的补丁,并且可以提供给git am
通过个人提交生成历史记录:
git log -p --pretty=email --stat -m --first-parent --reverse origin/master..HEAD | \
csplit -b %04d.patch - '/^From [a-z0-9]\{40\} .*$/' '{*}'
rm xx0000.patch
将修补程序命名为xx0001.patch
到xxLAST.patch
答案 4 :(得分:0)
根据Philippe De Muyter的解决方案,我制作了一个版本,以与git-format-patch相同的方式格式化补丁(据我所知)。只需将RANGE设置为所需的提交范围(例如origin..HEAD),然后转到:
{
name: 'whatever',
translations: {
ru: 'без разницы',
he: 'οτιδήποτε',
de: 'was auch immer'
}
}
请注意,如果您使用git-quiltimport,那么您将需要排除任何空的合并提交,否则您将收到错误“Patch为空。它是否错误?”。
答案 5 :(得分:0)
在 Git 2.32(2021 年第二季度)中,“format-patch
”文档更加清晰:它跳过合并。
参见commit 8e0601f的Jeff King (peff
)(2021 年 5 月 1 日)。
(2021 年 5 月 11 日于 Junio C Hamano -- gitster
-- 被 commit 270f8bf 合并)
docs/format-patch
:提及合并处理签字人:Jeff King
<块引用>Format-patch 无法通过 git-am
(或任何其他工具)可以应用的方式来格式化合并,因此它只是省略了它们。
然而,对于不熟悉该工具如何工作的用户来说,这可能是一个令人惊讶的暗示。
让我们在文档中添加一条注释,使其更加清晰。
git format-patch
现在包含在其 man page 中:
准备每个非合并提交及其“补丁”
git format-patch
现在包含在其 man page 中:
请注意,format-patch
将省略输出中的合并提交,即使
如果它们是请求范围的一部分。
一个简单的“补丁”不会
包括足够的信息让接收端重现相同的信息
合并提交。