1. Overview
1.概述
git rebase is a recommended best practice to write a clean code-commit history, especially for a multi-developer code repository. After doing this operation manually, we might later realize that we want to return to the original state.
git rebase是一种被推荐的最佳做法,用于编写干净的代码提交历史,特别是对于多开发者的代码库。在手动完成这一操作后,我们可能会在后来意识到我们想要返回到原始状态。
In this tutorial, we’ll explore a few techniques to undo a git rebase operation.
在本教程中,我们将探讨撤销git rebase操作的一些技巧。
2. Setup
2.设置
Let’s create a test bed to simulate a multi-developer code repository with multiple branches. We can assume that the development branch is the single source of truth for the project, which every developer uses to work on a specific feature using a feature-specific branch:
让我们创建一个测试平台来模拟一个有多个分支的多开发者代码库。我们可以假设development分支是项目的单一真理源,每个开发人员都使用特定功能的分支来处理特定的功能。
Now, assuming that we’ve got the above versioning ready for the project, let’s check out the feature2 branch:
现在,假设我们已经为项目准备好上述版本,让我们看看feature2分支。
$ git branch --show-current
feature2
Finally, let’s see the code commit history for the feature1 and feature2 branches:
最后,让我们看看feature1和feature2分支的代码提交历史。
$ git log feature1
commit e5e9afbbd82e136fc20957d47d05e72a38d8d10d
Author: Tapan Avasthi <tavasthi@Tapans-MacBook-Air.local>
Date: Sun Jul 31 16:27:22 2022 +0530
Add feature-1
commit 033306a06895a4034b681afa912683a81dd17fed
Author: Tapan Avasthi <tavasthi@Tapans-MacBook-Air.local>
Date: Sun Jul 31 16:27:22 2022 +0530
Add .gitignore file
$ git log feature2
commit 9cec4652f34f346e293b19a52b258d9d9a49092e
Author: Tapan Avasthi <tavasthi@Tapans-MacBook-Air.local>
Date: Sun Jul 31 16:27:22 2022 +0530
Add feature-2
commit 033306a06895a4034b681afa912683a81dd17fed
Author: Tapan Avasthi <tavasthi@Tapans-MacBook-Air.local>
Date: Sun Jul 31 16:27:22 2022 +0530
Add .gitignore file
In the subsequent sections, we’ll use this base scenario repeatedly to do a git rebase, followed by applying one approach at a time for undoing the rebase operation.
在随后的章节中,我们将重复使用这个基本方案来做git rebase,然后每次应用一种方法来撤销 rebase 操作。
3. Using ORIG_HEAD
3.使用ORIG_HEAD。
Let’s start by checking the current commits for the feature2 branch with a clean scenario:
让我们先检查一下feature2 分支的当前提交情况,以及一个干净的方案。
$ git log HEAD
commit 728ceb3219cc5010eae5840c992072cac7a5da00 (HEAD -> feature2)
Author: Tapan Avasthi <tavasthi@Tapans-MacBook-Air.local>
Date: Sun Jul 31 16:46:56 2022 +0530
Add feature-2
commit 6ed8a4d2a961fdfc4d5e4c7c00b221ed6f283bf4 (development)
Author: Tapan Avasthi <tavasthi@Tapans-MacBook-Air.local>
Date: Sun Jul 31 16:46:56 2022 +0530
Add .gitignore file
Now, let’s rebase the feature2 branch on top of the feature1 branch:
现在,让我们在feature1分支的基础上重新建立feature2分支。
$ git rebase feature1
After doing the rebase operation, let’s see the HEAD reference:
在做完重定位操作后,让我们看看HEAD参考。
$ git log HEAD
commit 9d38b792d0c9a8d0cd8e517fcb2ca5260989cc4a
Author: Tapan Avasthi <tavasthi@Tapans-MacBook-Air.local>
Date: Sun Jul 31 16:46:56 2022 +0530
Add feature-2
commit 1641870338662a016d5c8a17ef5cada0309f107e
Author: Tapan Avasthi <tavasthi@Tapans-MacBook-Air.local>
Date: Sun Jul 31 16:46:56 2022 +0530
Add feature-1
commit 6ed8a4d2a961fdfc4d5e4c7c00b221ed6f283bf4
Author: Tapan Avasthi <tavasthi@Tapans-MacBook-Air.local>
Date: Sun Jul 31 16:46:56 2022 +0530
Add .gitignore file
Further, we can verify that the ORIG_HEAD is still pointing to the 728ceb3219cc5010eae5840c992072cac7a5da00 commit:
此外,我们可以验证ORIG_HEAD仍然指向728ceb3219cc5010eae5840c992072cac7a5da00提交。
$ git log ORIG_HEAD
commit 728ceb3219cc5010eae5840c992072cac7a5da00
Author: Tapan Avasthi <tavasthi@Tapans-MacBook-Air.local>
Date: Sun Jul 31 16:46:56 2022 +0530
Add feature-2
commit 6ed8a4d2a961fdfc4d5e4c7c00b221ed6f283bf4
Author: Tapan Avasthi <tavasthi@Tapans-MacBook-Air.local>
Date: Sun Jul 31 16:46:56 2022 +0530
Add .gitignore file
Finally, we do a reset using the ORIG_HEAD reference:
最后,我们使用ORIG_HEAD引用进行复位。
$ git reset --hard ORIG_HEAD
$ git log HEAD -1
commit 728ceb3219cc5010eae5840c992072cac7a5da00
Author: Tapan Avasthi <tavasthi@Tapans-MacBook-Air.local>
Date: Sun Jul 31 16:46:56 2022 +0530
Add feature-2
That’s it! We’ve successfully reverted the rebase operation with the help of ORIG_HEAD.
这就是了!在ORIG_HEAD的帮助下,我们已经成功地恢复了重定位操作。
4. Using git reflog
4.使用git reflog。
Again, let’s start with a fresh scenario setup:
同样,让我们从一个新的场景设置开始。
$ git log HEAD
commit 07b98ef156732ba41e2cbeef7939b5bcc9c364bb
Author: Tapan Avasthi <tavasthi@Tapans-MacBook-Air.local>
Date: Sun Jul 31 17:53:35 2022 +0530
Add feature-2
commit d6c52eb601e3ba11d65e7cb6e99ec6ac6018e272
Author: Tapan Avasthi <tavasthi@Tapans-MacBook-Air.local>
Date: Sun Jul 31 17:53:35 2022 +0530
Add .gitignore file
Now, let’s do a rebase and check the commit history:
现在,让我们做一个重新定位并检查提交历史。
$ git rebase feature1
$ git log HEAD
commit b6ea25bf83ade2caca5ed92f6c5e5e6a3cb2ca7b
Author: Tapan Avasthi <tavasthi@Tapans-MacBook-Air.local>
Date: Sun Jul 31 17:53:35 2022 +0530
Add feature-2
commit d2cabe48747699758e2b14e76fb2ebebfc49acb1
Author: Tapan Avasthi <tavasthi@Tapans-MacBook-Air.local>
Date: Sun Jul 31 17:53:35 2022 +0530
Add feature-1
commit d6c52eb601e3ba11d65e7cb6e99ec6ac6018e272
Author: Tapan Avasthi <tavasthi@Tapans-MacBook-Air.local>
Date: Sun Jul 31 17:53:35 2022 +0530
Add .gitignore file
Next, let’s use the git reflog command to inspect the record of events at a granular level:
接下来,让我们使用git 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
We can notice that git internally maintains the references at a granular level wherein the position of HEAD before the rebase operation is represented by the HEAD@{3} reference.
我们可以注意到,git在内部对引用进行了细化维护,其中HEAD在rebase操作之前的位置由HEAD@{3}引用表示。
So, as a final step, let’s restore the earlier state by doing a git reset:
所以,作为最后一步,让我们通过做git reset来恢复早期状态。
$ git reset --hard HEAD@{3}
$ git log HEAD
commit 07b98ef156732ba41e2cbeef7939b5bcc9c364bb
Author: Tapan Avasthi <tavasthi@Tapans-MacBook-Air.local>
Date: Sun Jul 31 17:53:35 2022 +0530
Add feature-2
commit d6c52eb601e3ba11d65e7cb6e99ec6ac6018e272
Author: Tapan Avasthi <tavasthi@Tapans-MacBook-Air.local>
Date: Sun Jul 31 17:53:35 2022 +0530
Add .gitignore file
Great! We’ve successfully learned this approach too. However, this approach uses some low-level details of git, and only advanced git users should use it.
很好!我们也成功地学会了这种方法。然而,这种方法使用了git的一些低级细节,只有高级git用户才能使用它。
5. Conclusion
5.总结
In this article, we used a test scenario for a git repository and learned about two popular techniques to undo a git rebase operation.
在这篇文章中,我们使用了一个git仓库的测试场景,了解了两种流行的技术来撤销git rebase操作。