最近,我不得不做一些基础工作,以使用git rebase master
解决一些合并冲突。令我惊讶的是,Git忽略了合并提交,这引起了很多麻烦,使代码消失了。最终,我发现我正在寻找-p
,但是为什么git rebase
的默认行为是忽略合并提交?
答案 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
并查看它的工作原理,因此现在可以安全地将A
和B
设置在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'
只是对B
对A
所做的相同更改。但是您不能复制合并;您必须进行全新的合并。那当然是可能的;这就是旧的-p
或新的--rebase-merges
的实际作用:他们只是确定合并之前发生过的地方,然后进行新的合并-如果新合并的基础不同,结果可能会大不相同-在任何有意义的地方。
很明显,新合并的两个父级之一:是原始合并的父级的某个原始提交中的基于副本的复制提交。 other 父级(无论如何,假定为双亲合并)并不十分明显:有时是未更改的原始提交,有时是基于重新提交的提交。因此,这项工作比起初看起来要难。古老的,非-p
的非基准代码只是简单地说:这很难,而且在大多数情况下我们也根本不愿意这样做,因此,我们不必费心尝试。
(我会说这是错误的-如果您天真地对涉及合并的链进行基础调整,您可能也希望复制该合并-但同时,我会认为,如果您天真地对基础进行调整在涉及合并的链中,您对自己的工作没有足够的考虑,因此默认的行为是有道理的。如果检测到合并,它将跳过,警告或要求标记可能更有意义。 )