请考虑以下这棵树。不好意思,但是我想你明白了。
我有一个MASTER
分支和一个MY BRANCH
。我从PATCH
创建了一个MASTER
分支,并在此分支上进行了修复。然后,我将修订合并到两者 MASTER
和MY BRANCH
中。当我这样做时,MY BRANCH
也会得到提交C
和D
。
MASTER----A----B----C----D-------------MERGE
\ \ /
\ PATCH----E----F
\ \
MY BRANCH----G----H-------MERGE
如何将补丁中的提交仅合并到MASTER
和MY BRANCH
中?
答案 0 :(得分:2)
正如RomainValeri指出的那样,可以更好地绘制图形。我将借用他的变体形式开始,但在尝试进行任何合并之前,请画出我们在 之前拥有的内容:
E---F <<< patch
/
A---B---C---D <<< master
\
G---H <<< my-branch
名称patch
表示现有提交F
,名称master
和my-branch
表示现有提交H
。
出现问题是因为git merge
是基于提交图而不是基于分支名称的。名称 find 提交,就目前而言还可以,但是如果您运行git merge <commit F>
,则结果将包括提交F
,其中将包括提交{{1} },其中将包含提交E
,其中将包含提交D
,其中将包含提交C
,依此类推。
也就是说,提交B
的任何成功合并都会自动包括导致F
本身并包括F
的每个提交。
您可以使用git cherry-pick
来复制单个提交。请记住,提交是一个快照,是所有文件的完整集合。但是每个提交都有一个 parent 提交
1 如果将提交E
中的快照与其父提交D
中的快照进行比较,您会在中看到更改了提交E
。如果将提交F
中的快照与提交E
中的父快照进行比较,则会在提交F
中看到所做的更改。基本上,您只能通过“樱桃选择”在其他位置“重播”这些更改。
这导致人们经常提出的建议,即在此处使用“樱桃采摘”。如果您创建了一个名为patch2
的新分支,则从提交H
开始,并 copy E
和F
到新的和改进的提交{{1 }}和E'
,其中F'
和E'
在提交F'
之后,您得到:
H
您现在可以将原始补丁合并到 E---F <-- patch
/
A---B---C---D <-- master
\
G---H <-- my-branch
\
E'-F' <-- patch2
中,将新的和不同的(据说经过改进)master
分支合并到patch2
中。
有更好的方法!好吧,经常。让我们退一步,然后问:您为什么首先编写提交my-branch
和E
?
可能是要修复提交F
或提交A
或两者中的错误。或者,也许它添加了一项仅缺少提交B
的功能。无论哪种情况,您都相信可以在没有提交B
和C
的情况下 进行应用。
您现在应该做的是证明这一点。新建一个分支D
,但不要将其指向现有的提交patch2
。而是在提交H
上启动它。然后将B
和E
复制到新改进的F
和E'
中,得到:
F'
请注意,所有现有的提交都仍然存在,完全相同。 (您尚未在任何地方合并任何内容。)但是,如果 E--F <-- patch
/
C--D <-- master
/
A--B--E'-F' <-- patch2
\
G--H <-- my-branch
确实可行,我们现在可以丢弃名为patch2
的分支,放弃提交patch
:< / p>
E-F
现在我们已经完成了,让我们停止绘制它们,并将现有分支 E--F [abandoned]
/
C--D <-- master
/
A--B--E'-F' <-- patch2
\
G--H <-- my-branch
重命名为patch2
:
patch
复制(樱桃选择或重新设置)提交 C--D <-- master
/
A--B--E'-F' <-- patch
\
G--H <-- my-branch
现在处于可以运行E'-F'
和git checkout master; git merge patch
的位置。完成后,我们将获得两个合并提交:
git checkout my-branch; git merge patch
这些合并的行为与您喜欢的方式相同:它们将仅 个补丁带入分支,而不是与该补丁无关的其他任何提交。
如果您要修复错误或添加共享功能,请在图形中查找最早的提交,该错误或功能可以在其中提交。在这种情况下,那只是在提交 C--D--M1 <-- master
/ /
A--B--E'-F' <-- patch
\ \
G--H--M2 <-- my-branch
之后。 (可以将其放在提交B
之后,如果可以,则可以这样做。但是,如果错误或功能需要提交A
的一部分,则提交B
是你可以走的最远的背部。)
这样做的原因是可以将生成的补丁干净合并到该点“下游”的任何提交中。在这种情况下,您想将补丁合并到B
下游D
的提交master
中,并合并到B
下游的H
my-branch
。由于B
在提交patch
时位于F'
的下游,因此将B
合并到任何分支中将带来提交patch
。但是提交B
是分支B
有用的第一位。在patch
下游的不在的任何分支根本无法使用补丁!因此,通过将补丁本身放置在第一位之后,可能是使用,每个可以完全使用补丁的其他分支,可以轻松,干净地使用补丁。
答案 1 :(得分:1)
使用rebase
或cherry-pick
手动将E
和F
应用于MYBRANCH
或正确创建PATCH
分支E
和F
开始。
答案 2 :(得分:1)
您可以使用范围指定目标分支上所需的提交:
git checkout my-branch
git cherry-pick master..patch
其中master..patch
的意思是:
一切 patch
减去
{em> master
作为旁注,建议采用更好的树形结构
E---F <<< patch
/ \
A---B---C---D-------I <<< master
\
G---H <<< my-branch