1. 概述

Git Rebase 是一种推荐的最佳实践,用于维护清晰、线性的提交历史,尤其适用于多人协作的项目。然而,有时在执行 rebase 后,我们可能会意识到这是一个错误操作,需要撤销它。

在本文中,我们将介绍几种常用的回退 Git Rebase 操作的方法,适用于不同场景下的恢复需求。


2. 模拟环境搭建

为了演示,我们先模拟一个多人协作的 Git 项目结构。假设我们有一个主开发分支 development,并基于它创建了两个功能分支 feature1feature2

repo setup

我们当前在 feature2 分支上:

$ git branch --show-current
feature2

查看 feature1feature2 的提交历史如下:

$ git log feature1
commit e5e9afbbd82e136fc20957d47d05e72a38d8d10d
Author: Tapan Avasthi <tapan@example.com>
Date:   Sun Jul 31 16:27:22 2022 +0530

    Add feature-1

commit 033306a06895a4034b681afa912683a81dd17fed
Author: Tapan Avasthi <tapan@example.com>
Date:   Sun Jul 31 16:27:22 2022 +0530

    Add .gitignore file

$ git log feature2
commit 9cec4652f34f346e293b19a52b258d9d9a49092e
Author: Tapan Avasthi <tapan@example.com>
Date:   Sun Jul 31 16:27:22 2022 +0530

    Add feature-2

commit 033306a06895a4034b681afa912683a81dd17fed
Author: Tapan Avasthi <tapan@example.com>
Date:   Sun Jul 31 16:27:22 2022 +0530

    Add .gitignore file

接下来我们将使用这个环境来演示 rebase 操作以及如何撤销它。


3. 使用 ORIG_HEAD 回退

步骤说明

  1. 查看当前 feature2 的提交历史:
$ git log HEAD
commit 728ceb3219cc5010eae5840c992072cac7a5da00 (HEAD -> feature2)
Author: Tapan Avasthi <tapan@example.com>
Date:   Sun Jul 31 16:46:56 2022 +0530

    Add feature-2

commit 6ed8a4d2a961fdfc4d5e4c7c00b221ed6f283bf4 (development)
Author: Tapan Avasthi <tapan@example.com>
Date:   Sun Jul 31 16:46:56 2022 +0530

    Add .gitignore file
  1. 执行 rebase:
$ git rebase feature1
  1. 查看 HEADORIG_HEAD 的提交记录:
$ git log HEAD
commit 9d38b792d0c9a8d0cd8e517fcb2ca5260989cc4a
Author: Tapan Avasthi <tapan@example.com>
Date:   Sun Jul 31 16:46:56 2022 +0530

    Add feature-2

commit 1641870338662a016d5c8a17ef5cada0309f107e
Author: Tapan Avasthi <tapan@example.com>
Date:   Sun Jul 31 16:46:56 2022 +0530

    Add feature-1

commit 6ed8a4d2a961fdfc4d5e4c7c00b221ed6f283bf4
Author: Tapan Avasthi <tapan@example.com>
Date:   Sun Jul 31 16:46:56 2022 +0530

    Add .gitignore file

$ git log ORIG_HEAD
commit 728ceb3219cc5010eae5840c992072cac7a5da00
Author: Tapan Avasthi <tapan@example.com>
Date:   Sun Jul 31 16:46:56 2022 +0530

    Add feature-2

commit 6ed8a4d2a961fdfc4d5e4c7c00b221ed6f283bf4
Author: Tapan Avasthi <tapan@example.com>
Date:   Sun Jul 31 16:46:56 2022 +0530

    Add .gitignore file
  1. 使用 ORIG_HEAD 进行回退:
$ git reset --hard ORIG_HEAD
$ git log HEAD -1
commit 728ceb3219cc5010eae5840c992072cac7a5da00
Author: Tapan Avasthi <tapan@example.com>
Date:   Sun Jul 31 16:46:56 2022 +0530

    Add feature-2

✅ 成功回退!这个方法适用于刚执行完 rebase 且没有执行其他操作的情况。


4. 使用 git reflog 回退

步骤说明

  1. 初始状态:
$ git log HEAD
commit 07b98ef156732ba41e2cbeef7939b5bcc9c364bb
Author: Tapan Avasthi <tapan@example.com>
Date:   Sun Jul 31 17:53:35 2022 +0530

    Add feature-2

commit d6c52eb601e3ba11d65e7cb6e99ec6ac6018e272
Author: Tapan Avasthi <tapan@example.com>
Date:   Sun Jul 31 17:53:35 2022 +0530

    Add .gitignore file
  1. 执行 rebase:
$ git rebase feature1
$ git log HEAD
commit b6ea25bf83ade2caca5ed92f6c5e5e6a3cb2ca7b
Author: Tapan Avasthi <tapan@example.com>
Date:   Sun Jul 31 17:53:35 2022 +0530

    Add feature-2

commit d2cabe48747699758e2b14e76fb2ebebfc49acb1
Author: Tapan Avasthi <tapan@example.com>
Date:   Sun Jul 31 17:53:35 2022 +0530

    Add feature-1

commit d6c52eb601e3ba11d65e7cb6e99ec6ac6018e272
Author: Tapan Avasthi <tapan@example.com>
Date:   Sun Jul 31 17:53:35 2022 +0530

    Add .gitignore file
  1. 查看 reflog:
$ git reflog
b6ea25b HEAD@{0}: rebase (continue) (finish): returning to refs/heads/feature2
b6ea25b HEAD@{1}: rebase (continue): Add feature-2
d2cabe4 HEAD@{2}: rebase (start): checkout feature1
07b98ef HEAD@{3}: commit: Add feature-2
d6c52eb HEAD@{4}: checkout: moving from feature1 to feature2
d2cabe4 HEAD@{5}: commit: Add feature-1
d6c52eb HEAD@{6}: checkout: moving from development to feature1
d6c52eb HEAD@{7}: Branch: renamed refs/heads/master to refs/heads/development
d6c52eb HEAD@{9}: commit (initial): Add .gitignore file
  1. 回退到 rebase 之前的状态:
$ git reset --hard HEAD@{3}
$ git log HEAD
commit 07b98ef156732ba41e2cbeef7939b5bcc9c364bb
Author: Tapan Avasthi <tapan@example.com>
Date:   Sun Jul 31 17:53:35 2022 +0530

    Add feature-2

commit d6c52eb601e3ba11d65e7cb6e99ec6ac6018e272
Author: Tapan Avasthi <tapan@example.com>
Date:   Sun Jul 31 17:53:35 2022 +0530

    Add .gitignore file

✅ 成功恢复!这个方法适用于 ORIG_HEAD 不再有效或已被覆盖的情况,但⚠️ 由于涉及 Git 内部机制,建议由熟悉 Git 的用户使用。


5. 总结

在本文中,我们通过模拟多人协作的 Git 项目结构,演示了两种常见的回退 rebase 操作的方法:

方法 适用场景 是否推荐
ORIG_HEAD rebase 刚执行完,未执行其他操作 ✅ 推荐
git reflog rebase 已执行一段时间或 ORIG_HEAD 被覆盖 ⚠️ 高级用法,谨慎使用

📌 小贴士:

  • 使用 rebase 时建议先做备份,尤其是多人协作分支。
  • 如果你不确定是否要保留 rebase 后的结果,可以先创建临时分支。
  • Git 的 reflog 是你恢复误操作的“后悔药”,但它的生命周期有限(默认 90 天)。

掌握这些技巧后,你就能在面对 Git rebase 操作失误时从容应对了。


原始标题:Guide to Undo a git rebase