Git合并仅在分支内提交

时间:2020-02-04 07:59:07

标签: git

请考虑以下这棵树。不好意思,但是我想你明白了。

我有一个MASTER分支和一个MY BRANCH。我从PATCH创建了一个MASTER分支,并在此分支上进行了修复。然后,我将修订合并到两者 MASTERMY BRANCH中。当我这样做时,MY BRANCH也会得到提交CD

MASTER----A----B----C----D-------------MERGE
                \         \             /
                 \       PATCH----E----F
                  \                     \
             MY BRANCH----G----H-------MERGE

如何将补丁中的提交合并到MASTERMY BRANCH中?

3 个答案:

答案 0 :(得分:2)

正如RomainValeri指出的那样,可以更好地绘制图形。我将借用他的变体形式开始,但在尝试进行任何合并之前,请画出我们在 之前拥有的内容:

              E---F <<< patch
             /
A---B---C---D <<< master
     \
      G---H <<< my-branch

名称patch表示现有提交F,名称mastermy-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 EF到新的和改进的提交{{1 }}和E',其中F'E'在提交F'之后,您得到:

H

您现在可以将原始补丁合并到 E---F <-- patch / A---B---C---D <-- master \ G---H <-- my-branch \ E'-F' <-- patch2 中,将新的和不同的(据说经过改进)master分支合并到patch2中。

有更好的方法!好吧,经常。让我们退一步,然后问:您为什么首先编写提交my-branchE

可能是要修复提交F或提交A或两者中的错误。或者,也许它添加了一项仅缺少提交B的功能。无论哪种情况,您都相信可以在没有提交BC的情况下 进行应用。

您现在应该做的是证明这一点。新建一个分支D,但不要将其指向现有的提交patch2。而是在提交H上启动它。然后将BE复制到新改进的FE'中,得到:

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)

使用rebasecherry-pick手动将EF应用于MYBRANCH或正确创建PATCH分支EF开始。

答案 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