我如何清理 Git 被 Rebase 搞砸的提交

How do I cleanup Git Commits messed up by Rebase

下面是提交历史在我搞砸之前的样子:

A B C [master]
     \
      D E F G H I [refactor]

这是我当前的提交历史:

A --------------- E B C F D [master branch]
 \
  B C D E F G H I [refactor branch]

这是我想要的样子:

A B C D F G       [master branch]
           \
            E H I [refactor branch]

我没有完全理解 rebase 命令要做什么,所以我现在有点乱。这给我留下了两个问题:

  1. 有没有办法轻松撤销上一个rebase命令的效果 你运行? (因为我可能会再次搞砸。)

  2. 我应该使用什么系列的命令来到达我想去的地方 是?我怀疑我想使用 rebase 和 cherry_pick,但不想再把事情搞砸了。

感谢您的宝贵时间和帮助。

不需要任何挑选 - 您想要的结果是一个似乎已经存在的分支(重构)。编辑:我刚刚意识到它不完全一样。我会在最后添加注释。

请注意,您的第一个图表不可能真正存在:您不能在不同的分支中拥有完全相同的提交(您可能有不同的提交散列,其中包含相同的更改)。

另请注意,您正在做的事情将使 master 与您可能已经推送到的任何存储库不兼容——如果您已经与其他人共享 master,那么变基 master 通常不是您想要的。通常你会在 master 之上重新设置分支(然后将分支合并到 master 中)。

无论如何,假设 'refactor' 中的提交是正确的:

git branch old-master master # just so you don't lose anything...
git checkout refactor
git branch -d master
# git rebase --interactive D # commit D is the one in refactor branch
git branch master G # commit G is the one in refactor branch

我在中间添加了注释掉的 rebase 命令:如果你真的想重新排序 E、F 和 G,这将很有用,如图所示。在 rebase 编辑器中,您可以根据需要重新排序提交,git 会尝试这样做——但您可能需要在被问及时手动修复问题。

就 "undoing a rebase" 而言,这是可能的,但需要更深入地研究 git:参见例如this answergit reflog 输出。

很难知道 "undo" 你所做的最好的选择是什么。 你应该指出你的分支在你的 rebase 之后的样子以及你实际输入的命令。

假设您的初始状态是:

A --------------- E B C F D [master branch]
 \
  B C D E F G H I [refactor branch]

你想要

A E B C F D       [master branch]
           \
            B' C' D' F' E' H' I' [refactor branch]

请注意,B 变为 B',C 变为 C',依此类推

那么你应该这样做:

$ git rebase <upstream> <branch>

$ git rebase master refactor

如果你想将提交 B'、C' 等压缩到一个提交中,你可以使用 rebase 命令的 -i 选项来实现,这样你最终得到:

A E B C F D [主分支] \ B" [重构分支]

其中 B" 是来自 B、C 等的压缩提交结果 请看git rebase documentation