Skip to main content

Undo git rebase

· 8 min read
Serhii Hrekov
software engineer, creator, artist, programmer, projects founder

How to Undo a Git Rebase

Undoing a git rebase is a common task, especially if you've made a mistake or the rebase process introduced unexpected issues. The method you use depends on the state of your repository and whether you've pushed the changes to a remote repository.


Method 1: Aborting a Rebase in Progress

If you are in the middle of a rebase and encounter conflicts or realize you made a mistake, the easiest solution is to abort the process. This will return your branch to the state it was in before the rebase started.

To abort, simply run:

git rebase --abort

This command is safe and will restore your repository to its original state, discarding any changes from the rebase attempt.


Method 2: Undoing a Completed Rebase (Local Changes Only)

If you have successfully completed a rebase but haven't pushed the changes to a remote repository, you can use git reflog and git reset to go back in time. The reflog is a powerful tool that records every action that moves the HEAD pointer, including rebases and resets.

Step 1: Find the Pre-Rebase Commit

First, use git reflog to see a log of your branch's history.

git reflog

The output will look something like this:

a1b2c3d HEAD@{0}: rebase (finish): returning to refs/heads/my-feature-branch
e4f5g6h HEAD@{1}: rebase (start): checkout origin/main
i7j8k9l HEAD@{2}: commit: Fix a bug
...

You need to identify the commit before the rebase started. In the example above, HEAD@{2} is the last commit on the branch before the rebase operation began. The rebase (start) entry marks the beginning of the rebase.

Step 2: Reset Your Branch

Once you have identified the correct commit, you can use git reset --hard to move your branch's HEAD pointer back to that specific commit.

git reset --hard HEAD@{2}

Replace HEAD@{2} with the correct reference from your reflog output. The --hard flag discards all changes in the working directory and staging area, effectively resetting the branch to the exact state it was in at that commit.

Alternative: Using ORIG_HEAD

Git also saves the state of your HEAD before a "dangerous" operation (like rebase or reset) into a special reference called ORIG_HEAD. If you haven't run any other such commands since the rebase, you can use it as a shortcut.

git reset --hard ORIG_HEAD

Be careful with this, as ORIG_HEAD gets overwritten by subsequent rebase, reset, or merge commands. Using reflog is the more reliable and explicit method.


Method 3: Reverting a Pushed Rebase

If you've already pushed your rebased branch to a remote repository and other developers may have based their work on it, using git reset --hard can cause problems. Rewriting shared history can lead to conflicts and confusion for your team [1, 2]. In this case, the best approach is to use git revert to create new commits that undo the changes introduced by the rebase [1].

This method preserves the history of the branch, which is a key best practice for shared branches.

Step 1: Identify the Commits to Revert

First, you need to identify the commits that were introduced by the rebase. The easiest way to do this is to find the commit where your branch was originally forked from the main branch. Let's say your branch was originally branched from main at commit xcommit. After the rebase, your branch now contains new commits from main that you want to undo.

You can use git log to see the new commits:

git log main..my-feature-branch

This will show you the commits that are in my-feature-branch but not in main.

Step 2: Revert the Commits

Once you have the list of commits, you can revert them. git revert creates a new commit that applies the inverse changes of the specified commit. You can revert a range of commits at once.

git revert <commit-1> <commit-2> ...

For example, if your new commits are a1b2c3d and e4f5g6h, you would run:

git revert a1b2c3d e4f5g6h

Git will create a new commit for each reverted commit. After this, you can push the changes to the remote.

git push

This is a safer approach because it doesn't rewrite the shared history. Instead, it adds new commits to explicitly undo the changes, which is a transparent and collaborative way to handle mistakes on a shared branch [2].


Summary of Best Practices

  • Before you rebase, always create a backup branch.

    git checkout -b my-feature-branch-backup

    This gives you a safety net to fall back on if things go wrong [3].

  • If a rebase is in progress, use git rebase --abort.

  • If a rebase is complete and local, use git reflog and git reset --hard to undo it.

  • If a rebase is complete and pushed to a shared remote, use git revert to preserve history and avoid conflicts for your team.


Sources

  1. Warp. "How To Undo a Git Rebase". https://www.warp.dev/terminus/undo-a-git-rebase
  2. Graphite. "Git undo rebase". https://graphite.dev/guides/git-undo-rebase
  3. GeeksforGeeks. "How to Undo a Git Rebase?". https://www.geeksforgeeks.org/git/how-to-undo-a-git-rebase/