Black Friday 2025 – NPI EA (cat = Baeldung on Ops)
announcement - icon

Yes, we're now running our Black Friday Sale. All Access and Pro are 33% off until 2nd December, 2025:

>> EXPLORE ACCESS NOW

Partner – Orkes – NPI EA (cat=Kubernetes)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

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 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.

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

$ git reset --hard HEAD@{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.