我已经从“ master”分支中检出两个分支,分别是“ feature1”和“ feature2”。 假设“ C1”是“ master”的头提交,“ feature1”分支具有新提交“ C2”,“ feature2”分支具有新提交“ C3”。
如果可能的话,如何以快进方式在“功能1”分支中合并“功能2”?
请帮助尽可能避免递归合并。
预先感谢...
答案 0 :(得分:2)
让我们把您的文字图片转换成真实的图片。您的分支名称为master
,它指向一系列提交中的最后一个提交。我将其称为master
的最后一次提交,它在此处具有一些笨拙的哈希ID,H
。提交H
记录其父提交的实际哈希ID,我将其称为G
,依此类推。我们说主控指向 H
,H
指向 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
,而master
和feature2
仍然指向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}},以便它指向H
或C1
。这使它前后滑动,或者从我们着陆的地方开始,再向后退到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'
,然后返回到C1
和H
和G
等。
制作F
的简单方法是使用复制副本的C2'
。 2 使用分支git cherry-pick
的简单方法是使用feature2
,它使用git rebase
复制提交,然后移动分支名称指向复制的提交,放弃了原始文件,转而使用新副本。但这是另一个问题的主题(并且在其他StackOverflow帖子中已经充分介绍了重新定标)。
1 从技术上讲,递归合并是Git中一种特殊的合并策略。还有其他一些内置策略-git cherry-pick
,resolve
和octopus
-但是在这种情况下,它们都将无济于事。
2 这种通过Cherry-pick进行的复制使用了Git的合并引擎,因此您仍在合并!您无法摆脱合并。拥抱合并!学习并喜欢它,因为您会经常使用它。