我有两个分支:让我们称他们为master
和feature
。我现在正在尝试将最近的更改从master合并到feature。我通常更喜欢重组而不是合并,但这两个分支有很大差异,所以我决定进行合并,而不是记录所有冲突解决方案。我完成了合并,并在功能上提交了它,并认为我已经完成了。一切都很好看。
现在,我对master进行了一些小改动,并希望将其重新设置为feature,但git rebase master
现在让我与上次合并中已经处理过的旧提交冲突。奇怪的是,git merge master
没有像预期的那样发生冲突。是什么给了什么?
答案 0 :(得分:2)
这种行为正在发生,因为当您merge
掌握时,更改会在feature
的顶部/结束上进行。
当您进行变基时,来自master
的更改存在于feature
的开头。
这就是为什么当您合并顶部时,您修复所有冲突,再次合并,然后这些冲突已经解决。但是,当您重新绑定时,必须再次合并冲突,因为您解决所有内容的先前提交位于分支的末尾。
听起来你最好选择合并或变基,并坚持feature
的生命。
答案 1 :(得分:2)
你的短语(“变身[对主人做出的小改动]变成了特写”)对我来说似乎有点奇怪,因为通常你会将feature
重新定位到master
。 (“into”这个词并不适用。)除此之外,我认为绘制提交图总是有帮助的。您可以使用gitk
或类似的查看器来绘制它,也可以使用git log --graph
(也许使用--oneline
来绘制垂直方向图。但是在这里我将绘制一个水平的字母,单个大写字母代表特别有趣的提交,小写o
代表更无聊的提交。
出于我们的目的,我将省略任何已配置的上游(origin/master
和/或origin/feature
)。如果它们确实存在,您可能希望将它们添加到您自己的绘图中,然后注意当git rebase
复制提交时,它不会移动任何其他标签(包括这些)指向现有提交的远程跟踪分支:它只移动一个标签,即当前分支的标签。
... - A - o - o - o - F <-- master
\ \
B - C - D - E - G <-- HEAD -> feature
运气好的话,这与你的预先设定的设置相当接近,并准确地反映了你git merge
的结果。在进行合并之前和之后,提交A
是feature
与master
分离的原始基础;在B
上提交了E
到feature
的提交。在o
上提出了各种不太有趣的master
次提交;并且提交F
是主人的提示。您在分支feature
上(以便HEAD
命名为分支feature
,git status
表示“在分支功能上”)并且您运行了git merge master
并进行了合并并承诺。
此合并在feature
上创建了提示最多的提交,即提交G
,这是一个合并提交。
之后,您检查了分支master
(使HEAD
指向名称master
)并进行了一次新的提交,移动了master
的提示,所以让我们将其添加到我们的图表中:到目前为止:
... - A - o - o - o - F - H <-- HEAD -> master
\ \
B - C - D - E - G <-- feature
最后,您想要feature
({1}}上的master
重新定义git checkout feature
所以... - A - o - o - o - F - H <-- master
\ \
B - C - D - E - G <-- HEAD -> feature
:
git rebase master
现在运行命令rebase
。
feature
做的是复制提交。
首先,它必须找到要复制的提交。它应该复制的提交是那些可以从当前分支到达的提交 - 即,从名称master
- 但不是从您作为上游提供名称的分支,即git log <upstream>..HEAD
。
这是我们遇到一个相当大的问题。看看recent git rebase
documentation中的这个(相当密集的)段落:
当前分支中的提交所做的所有更改,但不在 &LT;上游&GT;被保存到临时区域。这是
git log 'fork_point'..HEAD
所显示的同一组提交;或--fork-point
,如果--fork-point
有效(请参阅下面git log HEAD
的说明);如果指定了--root
选项,则按git rebase master
。
fork point的东西本身有点复杂但我们现在可以忽略它,因为使用命令git log master..HEAD
意味着它被关闭了。因此,您可以看到要使用B
进行重新定位的提交。这是提交C
,D
,E
,G
和B
(除了rebase通常会抛出合并)。
您可能想知道为什么E
到master
包含在此处,因为feature
和G
的合并基础是提交{{ 1}}。问题是,虽然合并提交G
指向提交F
(可从主服务器获得),但提交F
不会(也不能)“指向”G
。因此,当我们从master
(新提交H
)的提示开始并向后工作时,我们得到H
,F
,所有无聊的o
, A
以及A
之前的所有内容:这些是提交排除。当我们从feature
(提交G
)的提示开始并向后工作时,我们会得到G
,E
,D
,C
,在我们点击第一个被排除的(B
)之前A
。因此,这些是变基的候选人。
如果你允许rebase继续,并解决所有冲突,你最终会得到:
B' - C' - D' - E' <-- HEAD -> feature
/
... - A - o - o - o - F - H <-- master
\ \
B - C - D - E - G [abandoned]
(假设所有要复制的提交都有实际的复制更改;不需要复制提交G
,因为这次不会有任何贡献。)