为什么git rebase忽略合并提交?

时间:2019-04-26 18:22:34

标签: git rebase

最近,我不得不做一些基础工作,以使用git rebase master解决一些合并冲突。令我惊讶的是,Git忽略了合并提交,这引起了很多麻烦,使代码消失了。最终,我发现我正在寻找-p,但是为什么git rebase的默认行为是忽略合并提交?

2 个答案:

答案 0 :(得分:4)

man git-rebase说:

  

交互式rebase命令最初旨在处理各个修补程序系列。因此,将合并提交从todo列表中排除是有道理的,因为开发人员在分支上工作时可能已经合并了当前的master,最终只是将所有提交重新归类到master(跳过合并提交)。

我想补充一点,如果您使用git rebase --interactive进行合并,则应该(也根据man git-rebase)使用--rebase-merges而不是--preserve-merges。它将防止您其他很多头痛。

答案 1 :(得分:2)

每当您问一个为什么问题时,您都会进入哲学领域,这可能非常棘手。但是无论如何,我可以提出两个答案(如padawin's answer所示,其中一个是文档支持的。

首先,变基背后的原始想法是,这是个人在合并到某种更具权威性的存储库之前或之中所做的事情。

让我们发明两个球员,爱丽丝和鲍勃。爱丽丝拥有authoritative版本:任何想要该软件最新,最好的版本的人都可以使用爱丽丝。

在Alice的存储库中,有多种开发方式:

...--o--o--o--o--o   <-- master
            \
             o--o--o   <-- feature/tall

,依此类推。鲍勃在某个时候克隆了爱丽丝的存储库,也许在这个时候:

...--o--o--o   <-- master, origin/master
            \
             o--o--o   <-- origin/feature/tall

在Alice添加到她的权威master中的最后两个提交之前。

Bob随后从他的 feature/short开发了他的功能master,因此他具有:

             A--B   <-- feature/short
            /
...--o--o--o   <-- master, origin/master
            \
             o--o--o   <-- origin/feature/tall

他认为他已经准备好将结果提交给爱丽丝。因此,他运行git fetch origin来获取她的任何更新,现在他有了:

             A--B   <-- feature/short
            /
...--o--o--o   <-- master
           |\
           | o--o   <-- origin/master
            \
             o--o--o   <-- origin/feature/tall

他现在可以更新自己的master,以使其指向与他的origin/master相同的提交(爱丽丝目前master的提示):

             A--B   <-- feature/short
            /
...--o--o--o--o--o   <-- master, origin/master
            \
             o--o--o   <-- origin/feature/tall

在将他的A--B系列承诺提交给Alice之前,他应确保它们能起作用。因此,他可以git checkout master && git merge feature/short生成以下内容:

             A---B
            /     \
           |       M   <-- feature/short
           |      /
...--o--o--o--o--o   <-- master, origin/master
            \
             o--o--o   <-- origin/feature/tall

鲍勃(Bob)可以测试M并查看它的工作原理,因此现在可以安全地将AB设置在master顶端,给出:

           [old commits, no longer in use]
           |
           |       A'-B'  <-- feature/short
           |      /
...--o--o--o--o--o   <-- master, origin/master
            \
             o--o--o   <-- origin/feature/tall

请注意,提交M已从重新设置的提交feature/short中删除:Bob现在应该向Alice提供新的和改进的A'-B'提交链,并且Alice可以选择是否合并他们,或者快进B',或者她喜欢的任何东西。

这里的第二个想法是实际上不可能复制合并提交。将提交A复制到A'只是与父项进行A相同的更改。将B复制到B'只是对BA所做的相同更改。但是您不能复制合并;您必须进行全新的合并。那当然是可能的;这就是旧的-p或新的--rebase-merges的实际作用:他们只是确定合并之前发生过的地方,然后进行新的合并-如果新合并的基础不同,结果可能会大不相同-在任何有意义的地方。

很明显,新合并的两个父级之一:是原始合并的父级的某个原始提交中的基于副本的复制提交。 other 父级(无论如何,假定为双亲合并)并不十分明显:有时是未更改的原始提交,有时是基于重新提交的提交。因此,这项工作比起初看起来要难。古老的,非-p的非基准代码只是简单地说:这很难,而且在大多数情况下我们也根本不愿意这样做,因此,我们不必费心尝试。

(我会说这是错误的-如果您天真地对涉及合并的链进行基础调整,您可能也希望复制该合并-但同时,我会认为,如果您天真地对基础进行调整在涉及合并的链中,您对自己的工作没有足够的考虑,因此默认的行为是有道理的。如果检测到合并,它将跳过,警告或要求标记可能更有意义。 )