Categories
git git-rebase rebase undo

Undoing a git rebase

3900

How do I easily undo a git rebase? A lengthy manual method is:

  1. checkout the commit parent to both of the branches
  2. create and checkout a temporary branch
  3. cherry-pick all commits by hand
  4. reset the faulty rebased branch to point to the temporary branch

In my current situation, this works because I can easily spot commits from both branches (one was my stuff, the other was my colleague’s stuff). However, my approach strikes me as suboptimal and error-prone (let’s say I had just rebased with two of my own branches).

Clarification: I am talking about a rebase during which multiple commits were replayed, not only one.

0

    5362

    The easiest way would be to find the head commit of the branch as it was immediately before the rebase started in the reflog

    git reflog
    

    and to reset the current branch to it (with the usual caveats about being absolutely sure before reseting with the --hard option).

    Suppose the old commit was [email protected]{2} in the ref log:

    git reset --hard [email protected]{2}
    

    In Windows, you may need to quote the reference:

    git reset --hard "[email protected]{2}"
    

    You can check the history of the candidate old head by just doing a git log [email protected]{2} (Windows: git log "[email protected]{2}").

    If you’ve not disabled per branch reflogs you should be able to simply do git reflog [email protected]{1} as a rebase detaches the branch head before reattaching to the final head. I would double check this, though as I haven’t verified this recently.

    Per default, all reflogs are activated for non-bare repositories:

    [core]
        logAllRefUpdates = true
    

    5

    • 176

      Git reflog is awesome, just remember you can get better formatted output with git log -g (tip from Scott Chacon’s progit.org/book).

      – karmi

      Jul 23, 2010 at 10:14

    • 2

      Per Allan’s answer below a git rebase -i --abort is needed as well. The above alone is not enough.

      – Hazok

      Jun 14, 2011 at 22:36


    • 78

      @Zach: git rebase --abort (-i makes no sense with --abort) is for abandoning a rebase that hasn’t been completed – either because there were conflicts or because it was interactive or both; it’s not about undoing a successful rebase which is what the question is about. You would either use rebase --abort or reset --hard depending on which situation you were in. You shouldn’t need to do both.

      – CB Bailey

      Jun 15, 2011 at 20:40

    • 403

      Just in case, make a backup first: git tag BACKUP. You can return to it if something goes wrong: git reset --hard BACKUP

      – kolypto

      Nov 5, 2012 at 14:00

    • 27

      If you’ve made a lot of commits the [email protected]{#} you’re looking for will be prefaced with commit: as opposed to rebase:. Sounds obvious but it confused me for a bit.

      – Warpling

      Aug 26, 2013 at 20:43


    1810

    Actually, rebase saves your starting point to ORIG_HEAD so this is usually as simple as:

    git reset --hard ORIG_HEAD
    

    However, the reset, rebase and merge all save your original HEAD pointer into ORIG_HEAD so, if you’ve done any of those commands since the rebase you’re trying to undo then you’ll have to use the reflog.

    6

    • 45

      In case ORIG_HEAD is no longer useful, you can also use the [email protected]{n} syntax, where n is the nth prior position of the branch pointer. So for example, if you rebase featureA branch onto your master branch, but you don’t like the result of the rebase, then you can simply do git reset --hard [email protected]{1} to reset the branch back to exactly where it was before you did the rebase. You can read more about the [email protected]{n} syntax at the official Git docs for revisions.

      – user456814

      May 24, 2013 at 5:17

    • 19

      This is the easiest. Follow it up with a git rebase --abort though.

      – Seph

      Sep 16, 2015 at 19:24

    • 12

      @Seph Can you explain why you suggest following up with git rebase --abort?

      Jan 28, 2019 at 8:50

    • @Seph I agree with UpTheCreek as in my case it was not necessary. Maybe it is needed when things get odd during an interactive rebase? I would suggest anyone to try a git status to see if it mentions about the rebase or not first. Anyway doing a git rebase --abort should be harmless. If there is no ongoing rebase it will just fail complaining “fatal: No rebase in progress?“.

      Aug 20, 2021 at 14:44


    • 1

      Is it possible to check what the commit of ORIG_HEAD is first?

      – Simon

      May 9 at 12:13

    473

    Charles’s answer works, but you may want to do this:

    git rebase --abort
    

    to clean up after the reset.

    Otherwise, you may get the message “Interactive rebase already started”.

    1

    • 143

      That was not the question. The question asks how to undo a finished rebase.

      Apr 4, 2017 at 18:29