gitrebasegit-rebaseundo

Undoing a git rebase


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.


Solution

  • 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 HEAD@{2} in the ref log:

    git reset --hard HEAD@{2}
    

    In Windows, you may need to quote the reference:

    git reset --hard "HEAD@{2}"
    

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

    If you've not disabled per branch reflogs you should be able to simply do git reflog branchname@{1} as a rebase detaches the branch head before reattaching to the final head. I would double-check this behavior, though, as I haven't verified it recently.

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

    [core]
        logAllRefUpdates = true