161

In Git, how do you rollback a rebase if you're not happy with it?

Git doesn't have dry-run for rebase. If I did a rebase and have not pushed it yet, how do I rollback to before, as if it never happened?

Robbie
  • 18,750
  • 4
  • 41
  • 45
user1615666
  • 3,151
  • 7
  • 26
  • 23

2 Answers2

319

You can use the reflog to find the first action before the rebase started and then reset --hard back to it. e.g.

$ git reflog

b710729 HEAD@{0}: rebase: some commit
5ad7c1c HEAD@{1}: rebase: another commit
deafcbf HEAD@{2}: checkout: moving from master to my-branch
...

$ git reset HEAD@{2} --hard

Now you should be back to before the rebase started.

To find the right place to reset to, you just pick the entry closest to the top that doesn't start with "rebase".

Update: As mentioned in comments and other answers, you can also use ORIG_HEAD as an easier way to find where to reset to: git reset ORIG_HEAD --hard

Alternative approach

If the rebase is the only thing you have done on the branch, i.e. you have no unpushed commits/changes - then you could just delete the local branch with git branch -D and then check it out again:

$ git checkout my-branch
$ git rebase master
// not happy with the result
$ git checkout master
$ git branch -D my-branch
$ git checkout my-branch

Or for the same effect, you could reset --hard to the origin branch:

$ git reset --hard origin/my-branch

If you did do this while you had other unpushed commits, then you will have lost them. In that case, just use the reflog approach above to jump back to the reflog entry where you made the commit(s).

Robbie
  • 18,750
  • 4
  • 41
  • 45
  • 13
    One other handy shortcut: rebase sets `ORIG_HEAD` to the original hash value of the branch being rebased. So rather than finding the number 2 for `HEAD@{2}`, you can just use `ORIG_HEAD` ... but *only* if `ORIG_HEAD` is still undisturbed. A bunch of Git commands set it (rebase, am, reset, and merge, under various circumstances). – torek Dec 09 '16 at 00:00
  • using the position instead of commit id is a great way to make sure you're getting the desired exact point in the reflog rather than the most recent commit id in the reflog. :) – Dan Nov 05 '20 at 19:37
  • Note: If you reset multiple branches don't leave "git reflog" open since the IDs in the reflog will change each time you checkout and reset. This bit me the first time – 137 Jan 05 '21 at 14:49
70

Rebase keeps a backup of the old state as ORIG_HEAD.
So you can revert the last rebase by running:

git reset --hard ORIG_HEAD
Meligy
  • 35,654
  • 11
  • 85
  • 109
  • 2
    Do you happen to know where that tag is documented? – Ben S Sep 23 '19 at 12:53
  • Is there some downside to this or is it a new feature? This seems so much easier than sifting through a reflog. – 1252748 Dec 11 '19 at 17:19
  • 1
    It's not new. But you'd usually use it right after the rebase, cannot go back retrospectively after several rebases etc. For these complex situations you'd hunt for the relog stuff, but for just "oops, what did I just do? How can I revert that now?" it works just fine. – Meligy Dec 14 '19 at 12:25
  • 1
    This has been the simplest effective immediate rollback method for me! – Jordan Oct 25 '22 at 00:21
  • 1
    This is the hands down simplest method so far! – Godwin Mathias Aug 02 '23 at 00:09