【问题标题】:How can I move a commit across a merge commit?如何跨合并提交移动提交?
【发布时间】:2014-02-07 15:52:05
【问题描述】:

假设我有一个这样的存储库:

I --- C --- M    master
  \       /
   `- A -´       topic

其中M 是将topic 合并到master 中的合并提交。

后来我在C 中发现了一个错误,所以我在master 分支上的M 之上进行了修复:

I --- C --- M --- C1    master
  \       /
   `- A -´              topic

但理想情况下,我希望历史看起来像这样:

I --- C --- C1 --- M    master
  \              /
   `- A --------´       topic

如何重写历史记录,以便C1 出现在合并M 之前?

我可以删除M,应用C1 制作的补丁,然后再次将topic 合并到master,再次解决所有冲突,但我想避免这种努力,我会如果可能,更愿意保留原始提交信息(作者、日期等),这排除了再次执行 git commit 的可能性。我希望git rebase 可以,但我失败了,-p-i 中的一个或两个都失败了。

【问题讨论】:

    标签: git git-merge git-rebase revision-history


    【解决方案1】:

    这可以通过单个变基来移动提交(或任意数量的提交),然后从主题重做合并。

    # Create some branches just for readability
    git branch mergeCommit master^
    git branch beforeMerge master^^
    
    # Run the rebase
    git rebase --onto beforeMerge mergeCommit master
    # After the rebase master will have the replayed commits on top of C
    
    # Redo the merge
    git merge topic
    

    通过这个 rebase,您可以在合并之前移动多个提交。您可以阅读计划英语中的变基指令:

    获取从mergeCommitmaster 的提交并将它们重新设置在beforeMerge 之上。

    【讨论】:

    • 是的,我看到这些分支确实只是为了可读性;你可以用两个命令来做同样的事情:git rebase --onto master^^ master^ master,然后是git merge topic。 (不必删除临时分支是一个额外的好处。)
    【解决方案2】:

    第三张图中的提交 M 与第二张图中的 M 不同,因为它具有不同的祖先。因此,您必须在 M 之前将 master 重置回来,或者使用 rebase 来完成。

    首先提交您的修复,然后使用git rebase -i 将新提交移到 M 之前。

    为避免再次解决冲突,请确保您已设置 rerere.enabled 以让 git 记住解决方案。但是,您必须在第一次解决它之前执行此操作,以便记住它。 Rerere(重复使用记录的分辨率)是一个很棒的功能。

    【讨论】:

    • 谢谢。你能更详细地解释一下git rebase -i 命令吗?我试过git rebase -i C,合并丢失了;我尝试了git rebase -i -p C,但C1 提交丢失了,即使我在交互模式下“选择”了提交。
    【解决方案3】:

    我发现的最好方法是:

    git checkout -b tmp master^^
    # Now tmp is on top of C
    
    git cherry-pick master
    # Now tmp is on top of C1', a copy of C1
    
    git rebase -p tmp master
    # Now master is on top of a merge commit from C1' and A
    
    git branch -d tmp
    

    我不知道为什么 git rebase 不能在没有 git cherry-pick 的情况下一次完成所有这些操作,但至少我知道这是可行的。

    【讨论】:

    • git rebase -p 创建的合并提交是否正确创建?如,它的父母是否正确C1'A?我在重新合并合并时遇到了问题,因为合并更改被重播为正常提交而不是合并提交。
    • @LopSae:是的,合并提交是在 C1' 和 A 之上进行的。保留合并是 -p(又名 --preserve-merges)的重点,但使用 @987654329 有一个错误@和-i一起在git-rebase(1)中提到。
    猜你喜欢
    • 2011-09-05
    • 2016-04-19
    • 2011-03-28
    • 2011-09-04
    • 2021-03-26
    • 2018-06-01
    • 2012-11-08
    • 1970-01-01
    • 2015-08-29
    相关资源
    最近更新 更多