【问题标题】:How to revert a merge which used strategy=ours?如何恢复使用策略=我们的合并?
【发布时间】:2012-12-22 22:42:16
【问题描述】:

我正在使用几周前执行合并的存储库,我们刚刚发现它使用了 --strategy=ours 标志(它应该使用 --strategy-option=ours 标志),因此没有对头。但是,我们需要应用更改。 Git 已经将分支识别为被合并,并且分支历史中的提交。

这种合并不能使用git revert -m ...恢复

恢复和/或重新应用合并以更改文件的正确方法是什么?

master  A - B - E - F - G ---> L - M - N
             \     /
topic         C - D

合并提交 (F) 将是这种情况下的罪魁祸首。

【问题讨论】:

  • 是否可以肯定地说您不想重写历史记录,只需在合并文件的分支尖端生成一个新提交?
  • 实际上,重写历史是一个不错的选择。对于这种情况,只要实际应用更改就没有关系。需要注意的一点:我们正在尝试纠正合并到分支“master”,master 已经分支了几十次,所以历史必须能够在合并中传播到其他分支。

标签: git git-merge git-revert


【解决方案1】:

我已经找到了解决这个问题的方法。这全都在 Linus 写的关于恢复错误合并的信中:How to revert a faulty merge。 在我们的例子中,git merge --strategy=ours topic 不是有意的。即使它是错误的合并,也无法恢复,并且长期被推送,具有恢复合并提交但无法恢复恢复提交的相同效果。

解决方案是检查主题分支,从第一次提交运行rebase --no-ff,然后将该分支合并回主分支。

git checkout topic
git rebase -i --no-ff <C>
git checkout master
git merge topic

这产生了让步的效果:

fixed–topic   C'–––D'––––––––––––––––––––-
             /                            \
master  A–––B–––E–––F–––G –––> L–––M–––N–––F2
             \     /
topic         C–––D

要真正深入了解这一点,请阅读How to Revert a Faulty Merge 信的最后一部分,使用--no-ff rebase 选项重新创建分支。

【讨论】:

    【解决方案2】:

    @Highway of Life 有一个很好的答案。一件事是重新定位的提交现在看起来像新的不同提交,这在许多情况下可能是不可取的。我想再次合并相同的提交,但git-merge 阻止了这一点。但是,我一次又一次地发现,总是可以让 git 做你想做的事。

    1. 遵循生命之路的指示,但不要直接合并到主人:

      git checkout -b fixed-topic <D>
      git rebase -i --no-ff <B>
      git checkout -b re-merged master
      git merge fixed-topic
      

      这会导致:

      re-merged               ––––––––––––––––––––------R
                             /                         /
      fixed–topic      C'–––D'                        /
                      /                              /
      master     A–––B–––E–––F–––G –––> L–––M–––N–––F2
                      \     /
      topic            C–––D
      
    2. 现在,树已完全按照您的需要设置——所有文件都准确显示了您想要的内容。一个问题是您的合并提交的父母是原始提交的重新基础副本,而不是实际上是原始提交本身。使用git-reparent 很容易解决这个问题:

      git reparent -p master -p <D>
      

      最后是:

      master     A–––B–––E–––F–––G –––> L–––M–––N–––F2
                      \     /                        \
      topic            C–––D                          \
                            \                          \
      re-merged              ---------------------------R
      

      需要注意的重要一点是,自上一步以来,R 的内容没有改变——只有父母。

    3. 快进 master 到新的合并提交:

      git checkout master
      git merge re-merged
      
    4. 终于可以清理了

      git branch -d fixed-topic re-master
      

    完成!现在你的历史看起来像这样,一个分支合并了两次:

    master  A–––B–––E–––F–––G –––> L–––M–––N–––F2---R
                 \     /                           /
    topic         C–––D----------------------------
    

    【讨论】:

    • 我不知道reparent 选项是第三方功能。接缝是一个非常好的解决方案,但我正在寻找更简单的解决方案。
    【解决方案3】:

    从本质上说“无论你要合并什么,都保留你所拥有的”的合并策略是不可逆转的。在新分支中签出合并的第一个父级,然后再次进行合并。 Rebase --onto 你在原始合并之上的其余提交。

    更新:

    在你的情况下,如果你不关心过去,你可以将 G-N 重新定位到 E 上,然后将 D 合并到这个新的 master 上。 rebase 将是微不足道的,因为 F 是 --ours 合并。

    【讨论】:

    • 顺便说一句,我已经编辑了我的问题,使其更加清晰。 -- 自执行此合并以来,已对 master 分支进行了 69 次提交。我担心在这种情况下重写历史可能会导致团队成员的存储库发生潜在的灾难性故障,并且将他们的 rebase 合并合并回我的存储库可能会变得有趣。也许如果没有合适的选择,走补丁路线可能是最安全的方式?
    • rebase 和 patch 到底是一回事。不过,rebase 更加自动化。请记住打开您的 rerere,以防您必须重新启动并且您不想再次执行相同的冲突解决方案。
    猜你喜欢
    • 1970-01-01
    • 2018-01-06
    • 2022-01-08
    • 1970-01-01
    • 2018-09-08
    • 2012-12-15
    • 1970-01-01
    • 2019-05-03
    • 1970-01-01
    相关资源
    最近更新 更多