【问题标题】:Git rebase conflicts after successful merge?成功合并后Git rebase冲突?
【发布时间】:2015-10-19 23:39:43
【问题描述】:

我有两个分支:我们称它们为masterfeature。我现在正在尝试将最近的更改从 master 合并到 feature。我通常更喜欢变基而不是合并,但是这两个分支有很大的不同,所以我决定做一个合并来记录所有的冲突解决。我完成了合并,并在功能上提交了它,并认为我已经完成了。一切看起来都不错。

现在,我对 master 做了一个小改动,只想将其重新设置为功能,但 git rebase master 现在让我与我上次合并中已经处理的旧提交发生冲突。奇怪的是,git merge master 没有像预期的那样给出冲突。什么给了?

【问题讨论】:

    标签: git merge


    【解决方案1】:

    这种行为正在发生,因为当您 merge 主控时,更改会发生在 featuretop/end

    当您变基时,来自master 的更改存在于feature开始

    这就是为什么当你在顶部合并时,你解决了所有的冲突,你再次合并,然后那些冲突已经解决了。但是,当您变基时,您必须再次合并冲突,因为您解决所有问题的先前提交位于分支的末尾。

    听起来你最好选择合并或变基,并在 feature 的一生中坚持下去。

    【讨论】:

    • 真的吗?当有很多冲突和变基时,没有合理的方法只使用合并?从现在开始,我对每一个简单的合并都有一个额外的提交似乎很糟糕。有没有其他方法可以处理这个问题?我愿意接受改变工作流程的建议。
    • 是的 - 问题是 Git 在您重新设置基准时不知道您的合并冲突提交,因为它从您的提交历史的开头开始。老实说,我认为你最好现在变基并摆脱之前的合并冲突解决提交。
    • 如果重新出现冲突是一个常见问题,git rerere 命令可能会有所帮助。
    【解决方案2】:

    你的措辞(“rebase [a small change made to master] into feature”)对我来说似乎有点奇怪,因为通常你会将 feature 重新设置为 master。 (“进入”这个词并不适用。)除此之外,我认为绘制提交图总是有帮助的。您可以使用gitk 或类似的查看器来绘制它,或者git log --graph,也许还可以使用--oneline 来绘制一个垂直方向的图形。但这里我会画一个水平的,单个大写字母代表特别有趣的提交,小写的os 代表更无聊的提交。

    出于我们的目的,我将省略任何已配置的上游(origin/master 和/或origin/feature)。如果它们确实存在,您可能希望将它们添加到您自己的绘图中,然后注意当git rebase 复制提交时,它不会移动任何 other 标签(包括这些远程-跟踪分支)指向现有提交:它只移动一个标签,即当前分支的标签。

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

    幸运的是,这与您的预变基设置相当接近,并且准确地反映了您的 git merge 的结果。在您进行合并之前和之后,提交Afeaturemaster 分离的原始基数;提交BE 是在feature 上进行的;各种不太有趣的o 提交是在master 上进行的;并提交F 是大师的提示。您在分支 feature 上(因此 HEAD 命名为分支 feature,而 git status 表示“在分支功能上”)并且您运行 git merge master 并进行了合并并提交。

    此合并在feature 上创建了最尖端的提交,即提交G,这是一个合并提交。

    之后,您检查了分支master(使HEAD 指向名称master)并进行了移动master 尖端的新提交,所以让我们将其添加到我们的图表中-so-远:

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

    最后,你想在master 的(新提示)上重新设置feature,所以你做了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 &lt;upstream&gt;..HEAD 显示的提交集相同;或git log 'fork_point'..HEAD,如果--fork-point 处于活动状态(请参阅下面--fork-point 的说明);或git log HEAD,如果指定了--root 选项。

    分叉点本身有点复杂,但我们现在可以忽略它,因为使用命令git rebase master 意味着它已关闭。因此,您可以看到要使用 git log master..HEAD 重新设置的提交。这是提交 BCDEG(除了变基通常会抛出合并)。

    鉴于masterfeature合并基数 是提交G,您可能想知道为什么在这里包含BE。问题是,虽然合并提交G 指向提交F(可从主控访问),但提交F 不会(也不能)“指向”G。因此,当我们从master(新提交H)的尖端开始并向后工作时,我们得到HF、所有无聊的os、A,以及A之前的所有内容:这些是提交排除。当我们从feature 的尖端开始(提交G)并向后工作时,我们得到GEDCB,然后再点击第一个排除的( A)。因此,这些是变基的候选者。

    如果您允许 rebase 继续进行并解决所有冲突,您将得到:

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

    (假设所有要复制的提交都有要复制的实际更改;提交G 不需要复制,因为这次它不会贡献任何东西)。

    【讨论】:

      猜你喜欢
      • 2011-12-16
      • 1970-01-01
      • 1970-01-01
      • 2017-12-25
      • 1970-01-01
      • 1970-01-01
      • 2021-11-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多