快速合并两个分支的结帐

时间:2018-09-11 13:55:52

标签: git git-merge git-rebase

我已经从“ master”分支中检出两个分支,分别是“ feature1”和“ feature2”。 假设“ C1”是“ master”的头提交,“ feature1”分支具有新提交“ C2”,“ feature2”分支具有新提交“ C3”。

如果可能的话,如何以快进方式在“功能1”分支中合并“功能2”?

请帮助尽可能避免递归合并。

预先感谢...

1 个答案:

答案 0 :(得分:2)

让我们把您的文字图片转换成真实的图片。您的分支名称为master,它指向一系列提交中的最后一个提交。我将其称为master的最后一次提交,它在此处具有一些笨拙的哈希ID,H。提交H记录其父提交的实际哈希ID,我将其称为G,依此类推。我们说主控指向 HH 指向 G,依此类推。

... <-F <-G <-H   <--master

这些指向实际上是提交的一部分,除了最后一个直接来自名称master的指针。提交一旦完成就无法更改,因此H永远指向G。但是,分支名称可以随时更改!由于内部提交的内容永远固定下来,并且我想绘制指向后方(向左)但又向上或向下的内容,因此我们将它们与线连接起来,并为分支名称保留可移动的箭头。 (如果我可以使用不同类型的箭头来绘制文本,则内部提交箭头将使用坚硬,菱形,不变的箭头,分支名称应使用柔软易弯的大箭头。但是我必须使用这里是文字艺术。)

...--F--G--H   <-- master

您添加了一个新的分支名称feature1和另一个新的分支名称feature2,以便所有三个名称都指向提交H

...--F--G--H   <-- master, feature1, feature2

然后,在feature1上进行新提交时,您正在调用C1

$ git checkout feature1
... do work, git add files ...
$ git commit

导致以下结果:

             C1   <-- feature1 (HEAD)
            /
...--F--G--H   <-- master, feature2

请注意,feature1已附加了HEAD。这就是Git知道的,当它创建指向当前提交C1的新提交H时,要移动的名称feature1。名称HEAD现在仍附加到feature1上,名称feature1指向C1,而masterfeature2仍然指向H

现在运行:

$ git checkout feature2

其中-与准备工作区域以再次进行提交H一样-将HEAD附加到名称feature2

             C1   <-- feature1
            /
...--F--G--H   <-- master, feature2 (HEAD)

提交H是您现在提取到Git的 index 和工作树中的一个,因此现在您再次进行一些工作,git add来更新索引,和git commit从更新的索引中制作快照C2。这会将名称feature2移动到指向提交C2的位置:

             C1   <-- feature1
            /
...--F--G--H   <-- master
            \
             C2   <-- feature2 (HEAD)

现在你这样说:

  

如果可能的话,如何以快进方式在“功能1”分支中合并“功能2”?

快进操作包括采用这些分支名称之一,例如master,然后“向前滑动”(在我们的图片中,向右滑动,与内部箭头相反) go),使其指向其他提交。从 new 提交中,我们必须能够以原来的方式工作。如果我们不能做到这一点,那么我们的举动就不是一个快进。

因此,我们可以快速转发当前指向master的{​​{1}},以便它指向HC1。这使它前后滑动,或者从我们着陆的地方开始,再向后退到C2。但是,如何从H滑动箭头前进,使其指向C1?您不能:这实际上是不可能的。您可以将其向下滑动 ,使其指向C2并完全忘记C2,但这不是您想要的。

因此,我们必须依靠常规合并。为此:

C1

这将进行真正的合并,而不是快进。

  

请帮助尽可能避免递归合并。

真正的合并递归合并, 1 ,因此如果不进行合并,则无法合并提交$ git checkout feature1 $ git merge feature2 C1。 / p>

有关合并工作原理的更多信息,请参见其他任何StackOverflow帖子或有关Git的好书。

请注意,您还有另一种选择:您可以复制提交C2新的和不同的提交C2。我们可以将其称为C3而不是C2',以表示它是C3的副本。假设我们对此新副本进行了两项更改:

  • 起始源树将是C2的源树。我们将根据C1-vs-H所做的任何更改都应用于此源代码树。
  • 新副本的父项将是C2,而不是C1

如果我们引入此新提交,则它看起来像这样:

H

一旦我们制作了 C2' <-- ??? / C1 <-- feature1 / ...--F--G--H <-- master \ C2 <-- feature2 的这个C2'副本,并且有一些发现提交C2的分支名称,我们将得到一个< em>可以用于快进。名称C2'现在可以前后滑动,因此feature1指向feature1:从C2'可以回到C2',然后返回到C1HG等。

制作F的简单方法是使用复制副本的C2' 2 使用分支git cherry-pick的简单方法是使用feature2,它使用git rebase复制提交,然后移动分支名称指向复制的提交,放弃了原始文件,转而使用新副本。但这是另一个问题的主题(并且在其他StackOverflow帖子中已经充分介绍了重新定标)。


1 从技术上讲,递归合并是Git中一种特殊的合并策略。还有其他一些内置策略-git cherry-pickresolveoctopus-但是在这种情况下,它们都将无济于事。

2 这种通过Cherry-pick进行的复制使用了Git的合并引擎,因此您仍在合并!您无法摆脱合并。拥抱合并!学习并喜欢它,因为您会经常使用它。