2015-10-19 168 views
2

我有两个分支:我们称它们为masterfeature。我现在正试图将最近从主变更到功能。我通常比合并更喜欢rebase,但是这两个分支有显着的分歧,所以我决定做一个合并来记录所有的冲突解决方案。我完成了合并,并将其投入功能,并认为我完成了。一切看起来不错。成功合并后Git rebase冲突?

现在,我做了一个小改动,想把它变成功能,但git rebase master现在让我与上次合并中已经处理的较旧提交发生冲突。奇怪的是,git merge master没有按预期发生冲突。是什么赋予了?

回答

2

发生这种情况的原因是因为当您merge主入时,变更发生在的顶端/末端处。

当你变基,从master的变化在开始的feature存在。

这就是为什么当你合并顶部时,你解决了所有的冲突,你再次合并,那么这些冲突已经解决了。然而,当你重新绑定时,你必须再次合并冲突,因为你解决所有事情的前一个提交是在分支的末尾。

听起来像你最好选择合并或重新绑定,并坚持使用它的生活feature

+0

真的吗?在没有多少冲突和重组的情况下,没有合理的方式来使用合并。对于每一个简单的合并,我从这里开始做一个额外的提交看起来很糟糕。有没有其他的方式来处理这个问题?我愿意改变工作流程的建议。 – Eli

+0

是的 - 问题是Git不知道你的合并冲突提交时,因为它从你的提交历史的开始开始。说实话,我认为你现在最好重新配置,摆脱之前的合并冲突解决方案提交。 –

+1

如果重新出现冲突是一个常见问题,'git rerere'命令可能会有所帮助。 – hlovdal

2

你的短语(“rebase [对主人的一个小改变]成功能”)对我来说似乎有点不可思议,因为通常你会将feature重定为master。 (“into”一词并不适用。)除此之外,我认为绘制提交图总是有帮助的。您可以使用gitk或类似的查看器绘制它,或者使用git log --graph,也可以使用--oneline绘制垂直方向的图。但是在这里我会画一个水平的,用单个大写字母表示特别有趣的提交,并且小写字母代表更无聊的提交。

就我们的目的而言,我将忽略任何配置的上游(origin/master和/或origin/feature)。如果它们确实存在,则可能需要将它们添加到您自己的图形中,然后请注意,当git rebase提交提交副本时,它不会将任何其他标签(包括这些远程跟踪分支)指向现有提交:它只移动一个标签,即当前分支的标签。

... - A - o - o - o - F  <-- master 
     \    \ 
     B - C - D - E - G <-- HEAD -> feature 

运气好的话,这是相当接近的衍合预先设定,准确地反映了你的git merge的结果。合并之前和之后,提交Afeaturemaster分离的原始基础;承诺BE分别在feature;各种不太有趣的o提交是在master;并承诺F是主人的提示。您在分支feature(以便HEAD命名分支featuregit status表示“在分支功能”),并且您运行git merge master并做了合并并提交。

该合并创建了feature的提示最多提交,这是提交G,这是一个合并提交。

之后,你签出分支master(使HEAD点到名字master),并提出了新的提交感动的master尖端,所以我们认为添加到我们的图形那么远:

... - A - o - o - o - F - H  <-- HEAD -> master 
     \    \ 
     B - C - D - E - G  <-- feature 

最后,你想变基上(新尖)featuremaster所以你做了git checkout feature

... - A - o - o - o - F - H  <-- master 
     \    \ 
     B - C - D - E - G  <-- HEAD -> feature 

,现在你运行该命令git rebase master

rebase做的是拷贝提交。

首先,它必须找到其承诺进行复制。它应该复制的提交是那些从当前分支 - 即到达,从名字feature - 但不是从它的名字会作为上游的分支,即master

这里我们遇到了相当大的问题。看看这个(相当密集)段从recent git rebase documentation

通过提交当前分支的所有更改,但不在 <上游>被保存到一个临时区域。这与git log <upstream>..HEAD将显示的那组提交相同;或通过git log 'fork_point'..HEAD,如果--fork-point是活动的(见下文--fork-point的描述);或者通过git log HEAD,如果指定了--root选项。

叉点的东西本身有点复杂,但我们现在可以忽略它,因为使用命令git rebase master表示它已关闭。因此,您可以看到要用git log master..HEAD重新设置的提交。这是提交BCDE,并G(除了底垫通常扔出合并)。

您可能奇怪为什么B通过E包括在这里,考虑到合并基础的masterfeature是提交G。问题是,虽然合并提交G点回到提交F(可达来自主),提交F不会(也不能)“控球前锋”来G。所以,当我们从master尖端开始(新提交H)和向后工作,我们得到HF,所有的无聊o S,A,一切A前:这些都是排除的提交。当我们从feature尖端开始(提交G)和向后工作,我们得到了GEDCB之前,我们碰到的第一个排除(A)。因此这些是重新分配的候选人。

如果允许底垫中进行,并解决所有的冲突,你会拥有:

      B' - C' - D' - E' <-- HEAD -> feature 
         /
... - A - o - o - o - F - H  <-- master 
     \    \ 
     B - C - D - E - G  [abandoned] 

(假设所有的将要复制的提交有实际的变化进行复制;犯不需要复制G,因为这次不会提供任何内容)。