Expand Authors Top

If you have a few years of experience in the Java ecosystem and you’d like to share that with the community, have a look at our Contribution Guidelines.

Expanded Audience – Frontegg – Security (partner)
announcement - icon User management is very complex, when implemented properly. No surprise here.

Not having to roll all of that out manually, but instead integrating a mature, fully-fledged solution - yeah, that makes a lot of sense.
That's basically what Frontegg is - User Management for your application. It's focused on making your app scalable, secure and enjoyable for your users.
From signup to authentication, it supports simple scenarios all the way to complex and custom application logic.

Have a look:

>> Elegant User Management, Tailor-made for B2B SaaS

November Discount Launch 2022 – Top
We’re finally running a Black Friday launch. All Courses are 30% off until end-of-day today:

>> GET ACCESS NOW

November Discount Launch 2022 – TEMP TOP (NPI)
We’re finally running a Black Friday launch. All Courses are 30% off until end-of-day today:

>> GET ACCESS NOW

1. Overview

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.

In this tutorial, we'll explore a few techniques to undo a git rebase operation.

2. Setup

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:

repo setupNow, assuming that we've got the above versioning ready for the project, let's check out the feature2 branch:

$ git branch --show-current
feature2

Finally, let's see the code commit history for the feature1 and feature2 branches:

$ git log feature1
commit e5e9afbbd82e136fc20957d47d05e72a38d8d10d
Author: Tapan Avasthi <[email protected]>
Date:   Sun Jul 31 16:27:22 2022 +0530

    Add feature-1

commit 033306a06895a4034b681afa912683a81dd17fed
Author: Tapan Avasthi <[email protected]>
Date:   Sun Jul 31 16:27:22 2022 +0530

    Add .gitignore file

$ git log feature2
commit 9cec4652f34f346e293b19a52b258d9d9a49092e
Author: Tapan Avasthi <[email protected]>
Date:   Sun Jul 31 16:27:22 2022 +0530

    Add feature-2

commit 033306a06895a4034b681afa912683a81dd17fed
Author: Tapan Avasthi <[email protected]>
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.

3. Using ORIG_HEAD

Let's start by checking the current commits for the feature2 branch with a clean scenario:

$ git log HEAD
commit 728ceb3219cc5010eae5840c992072cac7a5da00 (HEAD -> feature2)
Author: Tapan Avasthi <[email protected]>
Date:   Sun Jul 31 16:46:56 2022 +0530

    Add feature-2

commit 6ed8a4d2a961fdfc4d5e4c7c00b221ed6f283bf4 (development)
Author: Tapan Avasthi <[email protected]>
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:

$ git rebase feature1

After doing the rebase operation, let's see the HEAD reference:

$ git log HEAD
commit 9d38b792d0c9a8d0cd8e517fcb2ca5260989cc4a
Author: Tapan Avasthi <[email protected]>
Date:   Sun Jul 31 16:46:56 2022 +0530

    Add feature-2

commit 1641870338662a016d5c8a17ef5cada0309f107e
Author: Tapan Avasthi <[email protected]>
Date:   Sun Jul 31 16:46:56 2022 +0530

    Add feature-1

commit 6ed8a4d2a961fdfc4d5e4c7c00b221ed6f283bf4
Author: Tapan Avasthi <[email protected]>
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:

$ git log ORIG_HEAD
commit 728ceb3219cc5010eae5840c992072cac7a5da00
Author: Tapan Avasthi <[email protected]>
Date:   Sun Jul 31 16:46:56 2022 +0530

    Add feature-2

commit 6ed8a4d2a961fdfc4d5e4c7c00b221ed6f283bf4
Author: Tapan Avasthi <[email protected]>
Date:   Sun Jul 31 16:46:56 2022 +0530

    Add .gitignore file

Finally, we do a reset using the ORIG_HEAD reference:

$ git reset --hard ORIG_HEAD
$ git log HEAD -1
commit 728ceb3219cc5010eae5840c992072cac7a5da00
Author: Tapan Avasthi <[email protected]>
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.

4. Using git reflog

Again, let's start with a fresh scenario setup:

$ git log HEAD
commit 07b98ef156732ba41e2cbeef7939b5bcc9c364bb
Author: Tapan Avasthi <[email protected]>
Date:   Sun Jul 31 17:53:35 2022 +0530

    Add feature-2

commit d6c52eb601e3ba11d65e7cb6e99ec6ac6018e272
Author: Tapan Avasthi <[email protected]>
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 <[email protected]>
Date:   Sun Jul 31 17:53:35 2022 +0530

    Add feature-2

commit d2cabe48747699758e2b14e76fb2ebebfc49acb1
Author: Tapan Avasthi <[email protected]>
Date:   Sun Jul 31 17:53:35 2022 +0530

    Add feature-1

commit d6c52eb601e3ba11d65e7cb6e99ec6ac6018e272
Author: Tapan Avasthi <[email protected]>
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
b6ea25b [email protected]{0}: rebase (continue) (finish): returning to refs/heads/feature2
b6ea25b [email protected]{1}: rebase (continue): Add feature-2
d2cabe4 [email protected]{2}: rebase (start): checkout feature1
07b98ef [email protected]{3}: commit: Add feature-2
d6c52eb [email protected]{4}: checkout: moving from feature1 to feature2
d2cabe4 [email protected]{5}: commit: Add feature-1
d6c52eb [email protected]{6}: checkout: moving from development to feature1
d6c52eb [email protected]{7}: Branch: renamed refs/heads/master to refs/heads/development
d6c52eb [email protected]{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 [email protected]{3} reference.

So, as a final step, let's restore the earlier state by doing a git reset:

$ git reset --hard [email protected]{3}
$ git log HEAD
commit 07b98ef156732ba41e2cbeef7939b5bcc9c364bb
Author: Tapan Avasthi <[email protected]>
Date:   Sun Jul 31 17:53:35 2022 +0530

    Add feature-2

commit d6c52eb601e3ba11d65e7cb6e99ec6ac6018e272
Author: Tapan Avasthi <[email protected]>
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.

5. Conclusion

In this article, we used a test scenario for a git repository and learned about two popular techniques to undo a git rebase operation.

November Discount Launch 2022 – Bottom
We’re finally running a Black Friday launch. All Courses are 30% off until end-of-day today:

>> GET ACCESS NOW

Generic footer banner
Comments are closed on this article!