您说的没错,您确实想利用git的合并能力。目前有几种可能性。最有可能发生的应该是合并,但是产生一个在D
之上应用了修改版本的E
的方法也不错。让我们来谈谈如何做到这一点!
如果补丁包包含它所适用的blob(即git format-patch
的输出),那么git am
可以尝试进行三方合并!差异中的blob SHA1记录如下:
diff --git a/foo.txt b/foo.txt
index ca1df77..2c98844 100644
如果你已经掌握了这个技巧,那就太幸运了。只需要使用git am --3way <patch>
即可。不过,git am
确实需要类似电子邮件的头部信息,而这是由format-patch生成的。所以,如果补丁来自于git diff
而不是git format-patch
,你需要稍微修改一下。你可以自己添加头部信息:
From: Bobby Tables <bobby@drop.org>
Date: 2 Nov 2010
Subject: [PATCH] protect against injection attack
<original diff>
git am
应该可以处理这个问题,如果你没有完全按照预期的方式得到它,你总是可以使用
git commit --amend
来修复它。(你也可以尝试使用
git apply --build-fake-ancestor=foo.txt <patch>
,但它真的不太友好。我认为欺骗
git am
更容易。)
如果补丁中不包含任何blob SHA1(即它是通过diff而不是git命令创建的),同样告诉你的朋友如何使用git,我相信你仍然可以把它搞定。你知道补丁应该应用于哪个版本的foo.txt!要从提交B中获取其SHA1,请使用:
git ls-tree <SHA1 of B>:<directory containing foo.txt>
这将是列出的一组blob之一。(我知道有一种直接的方法,但我现在想不起来了。)然后,您可以添加一个虚假的git diff头。假设它的哈希值为abcdef12:
diff --git a/foo.txt b/foo.txt
index abcdef12..
Git实际上只需要第一个哈希值; 尽管git diff输出将具有最终哈希和模式,但am
不需要它,因此您可以省略它。(是的,我刚测试了一下。以前我从来没有这样做过!)
这将导致类似于A-B-C-D-E'
的历史记录,其中E'
是您朋友的补丁,但应用于D
; 这是在D
,B
和您朋友的补丁之间进行三方合并的结果。
最后,如果您不想深入研究任何内容,您可以像您所说的那样操作:
git checkout -b bobby <SHA1 of B>
# apply the patch
git commit --author="Bobby Tables <bobby@drop.org>"
git checkout master
git merge bobby
# or `git cherry-pick bobby` to grab the single commit and apply to master
# or `git rebase bobby master` to rebase C and D onto B