我如何清理 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 命令要做什么,所以我现在有点乱。这给我留下了两个问题:
有没有办法轻松撤销上一个rebase命令的效果
你运行? (因为我可能会再次搞砸。)
我应该使用什么系列的命令来到达我想去的地方
是?我怀疑我想使用 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 answer 和 git 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
下面是提交历史在我搞砸之前的样子:
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 命令要做什么,所以我现在有点乱。这给我留下了两个问题:
有没有办法轻松撤销上一个rebase命令的效果 你运行? (因为我可能会再次搞砸。)
我应该使用什么系列的命令来到达我想去的地方 是?我怀疑我想使用 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 answer 和 git 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