首页 > 解决方案 > 撤消 git rebase 错误

问题描述

我从来没有遇到过 rebase 的麻烦,主要是因为我在提交代码量和范围时会更加小心。但是,在努力将一些遗留项目的更改与我的同行合并时,我们在使用 rebase-first 方法时遇到了一个主要问题(因为提交中有大量更改)。所以这让我开始思考如何解决在这种情况下似乎很常见的一些问题。

好的,请考虑我目前正在做一个 rebase,到目前为止我已经应用了一半的提交。我现在正在应用下一次提交并解决一些冲突。我有三个主要问题:

1)如何为这个错误合并的单个文件重做rebase?

2)如果我在合并/删除或添加文件时犯了更多错误,如何为我正在应用的这个提交中的所有文件重做rebase?

3)如果我意识到我在合并一个或两个已经应用了一些提交的文件时犯了一个错误,我该如何返回这个 rebase 中已经应用的提交?

PS.:我知道git reflogORIG_HEAD指针。我确实想让它工作,同时保留 git rebase 操作状态。我不知道是否有更简单的方法来解决这个问题。

标签: rebasegit-rebasegit

解决方案


这是 (a) 一个普遍的难题,并且 (b) 以个人喜好为基础,这使得很难有一个好的通用解决方案。

考虑解决它的方法是记住变基复制提交。我们需要一种方法来在多个提交副本之间建立某种用户友好的映射。

也就是说,假设我们有:

       O1--O2--O3   <-- branch@{1} (as originally developed with original commits)
      /
...--M1--M2--M3--M4   <-- mainline
               \   \
                \   S1--S2   <-- HEAD (in middle of second rebase)
                 \
                  R1--R2--R3   <-- branch (after first rebase)

这里的映射是 O1、R1 和 S1 在某种程度上都是“等价的”,即使它们的补丁 ID 不匹配和/或 R1 和/或 S1 中存在错误。同样,O2、R2 和 S2 是“等价的”,而 O3 和 R3 是“等价的”(没有 S3)。

Git 不提供返回 S1 的机制。您可以随心所欲地对 S2 大惊小怪,git commit --amend用于制作其父级为 S1 的 S2a,但您唯一的内置选项是继续运行或完全中止。如果继续下去,最终名字branch会从 R3 上剥离,粘贴到 S3 上,branch@{1}变成branch@{2},branch@{1}ORIG_HEAD记住 R3。

Git 也没有提供可靠的机制来将任何 O/R/S 提交标记为“等效”。你得到的最接近的是git patch-id. 当然,如果您在自动变基中使用了 squash 或 fixup 操作,那么您真正想要的东西更奇特,例如,“R2 相当于用 Oy 压扁的 Ox”或其他什么。

可以使用 reflogs,或设置分支或标记名称,以便能够恢复提交 S2 的哈希 ID,您可以从中找到 S1。这使您可以创建自己的类似 rebase 的命令,该命令通过挑选 S1 并停止修改,然后挑选 S2 并继续挑选 R3 来工作。但是您通常只会知道如何使用等价映射来做到这一点。

如何从这里开始取决于您:您将构建自己的工具。您可以使用它git rev-list来获取选定提交的哈希 ID。只要确保如果在要挑选的提交序列中存在分支和合并操作,那么您已经习惯--topo-order了获得一致的顺序。


推荐阅读