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

问题描述 投票:2回答:2

最近我不得不做一些改变来使用git rebase master来解决一些合并冲突。 Git,令我惊讶的是忽略了合并提交导致很多令人头痛的问题,代码就会消失。最终我发现-p是我正在寻找的但是为什么git rebase的默认行为忽略了合并提交?

git rebase
2个回答
4
投票

来自man git-rebase,据说:

交互式rebase命令最初设计用于处理单个补丁系列。因此,从todo列表中排除合并提交是有意义的,因为开发人员可能在处理分支时合并当时的主设备,但最终将所有提交重新绑定到master上(跳过合并提交)。

我想补充一点,如果你使用git rebase --interactive合并,你应该(根据man git-rebase)使用--rebase-merges而不是--preserve-merges。它会阻止你很多其他的麻烦。


3
投票

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

第一个原因是,重新定位背后的最初想法是,这是个人在合并到某种更权威的存储库之前或期间所做的事情。

让我们发明两个球员,爱丽丝和鲍勃。 Alice有authoritative版本:任何想要最新和最好版本软件的人都会去Alice。

在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

鲍勃然后从他的feature/short开发了他的功能master,所以他有:

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

他认为他已经准备好将他的结果交给Alice了。所以他运行git fetch origin以获得她的任何更新,现在他有这个:

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

他现在可能会更新他自己的master,以便它指向与他的origin/master(Alice目前的master尖端)相同的提交:

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

在向Alice发送他的A--B系列提交之前,他应该确保它们正常工作。所以他可以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

鲍勃可以测试M并看到它有效 - 所以现在可以安全地在A的顶端重新设置Bmaster,给出:

           [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实际上做的事情:他们只是确定合并发生在哪里,并做一个新的 - 如果新的合并基础是不同的 - 可能会有非常不同的结果 - 只要有意义。

新合并的两个父项之一是显而易见的:它是来自原始合并的父级的一些原始提交的重新定位的复制提交。另一个父 - 假设一个双父合并 - 无论如何 - 实际上并不那么明显:有时它是一个未更改的原始提交,有时它是一个重新提交的提交。所以这项工作比起初看起来更难。旧的,非-p rebase代码简单地说:这很难,而且在大多数情况下我们根本不想这样做,所以让我们懒得去尝试。

(我认为这是错误的 - 如果你天真地重新定义涉及合并的链,你可能也想复制合并 - 但与此同时,我会争辩说,如果你天真地重新定位一个链涉及合并,你没有充分考虑你正在做什么。所以默认行为排序是有道理的。如果它检测到它将跳过的合并,并警告或需要一个标志,它可能更有意义。)

© www.soinside.com 2019 - 2024. All rights reserved.