Does anybody know how to easily undo a git rebase?
The only way that comes to mind is to go at it manually:
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
”.
Let's say I rebase master to my feature branch and I get 30 new commits which break something. I've found that often it's easiest to just remove the bad commits.
git rebase -i HEAD~31
Interactive rebase for the last 31 commits (it doesn't hurt if you pick way too many).
Simply take the commits that you want to get rid of and mark them with "d" instead of "pick". Now the commits are deleted effectively undoing the rebase (if you remove only the commits you just got when rebasing).
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.
I actually put a backup tag on the branch before I do any nontrivial operation (most rebases are trivial, but I'd do that if it looks anywhere complex).
Then, restoring is as easy as git reset --hard BACKUP
.
If you mess something up within a git rebase, e.g. git rebase --abort
, while you have uncommitted files, they will be lost and git reflog
will not help. This happened to me and you will need to think outside the box here. If you are lucky like me and use IntelliJ Webstorm then you can right-click->local history
and can revert to a previous state of your file/folders no matter what mistakes you have done with versioning software. It is always good to have another failsafe running.
Resetting the branch to the dangling commit object of its old tip is of course the best solution, because it restores the previous state without expending any effort. But if you happen to have lost those commits (f.ex. because you garbage-collected your repository in the meantime, or this is a fresh clone), you can always rebase the branch again. The key to this is the --onto
switch.
Let’s say you had a topic branch imaginatively called topic
, that you branched off master
when the tip of master
was the 0deadbeef
commit. At some point while on the topic
branch, you did git rebase master
. Now you want to undo this. Here’s how:
git rebase --onto 0deadbeef master topic
This will take all commits on topic
that aren’t on master
and replay them on top of 0deadbeef
.
With --onto
, you can rearrange your history into pretty much any shape whatsoever.
Have fun. :-)