git.tools / guides

How to undo a git rebase

Rebased onto the wrong base, mangled an interactive rebase, or pushed a rebase you regret? The reflog remembers where your branch was — here's how to go back.

Last updated September 18, 2026 · 7 min read

A rebase feels irreversible because it rewrites your commits — new SHAs, new parents, new order. But here's the thing: the old commits are untouched. Rebase creates copies and moves your branch pointer; the originals sit in the object database exactly as they were. Undoing a rebase means finding that old pointer and putting your branch back on it.

TL;DR:

# Still mid-rebase, conflicts open?
git rebase --abort

# Rebase already finished?
git reflog                    # find the tip from before "rebase (start)"
git reset --hard <sha>        # often simply: git reset --hard ORIG_HEAD

Case 1: you're still inside the rebase

Conflicts on screen, (branch|REBASE 2/5) in your prompt, regret setting in. One command exits the whole operation:

git rebase --abort

Your branch returns to exactly the state it was in before you typed git rebase. Not "mostly" — exactly. This is the cleanest exit in git, and the one people forget exists while they're three conflicts deep.

Case 2: the rebase finished, but you haven't pushed

The shortcut: rebase records where your branch pointed before it started in ORIG_HEAD, so:

git reset --hard ORIG_HEAD

The catch: ORIG_HEAD gets overwritten by the next merge, rebase, or reset you run. If you've done anything since the rebase, don't gamble — use the reflog instead:

git reflog

You're looking for the line where the rebase began. The output reads newest-first and looks like:

a1b2c3d HEAD@{0}: rebase (finish): returning to refs/heads/feature
e4f5g6h HEAD@{1}: rebase (pick): add retry logic
...
7i8j9k0 HEAD@{8}: rebase (start): checkout main
2b3c4d5 HEAD@{9}: commit: last commit before the rebase

The entry directly below rebase (start) — 2b3c4d5 — is your pre-rebase tip. Put the branch back on it:

git reset --hard 2b3c4d5
git log --oneline -5

Verify the log looks like your old history, SHAs and all. It will — because those are your original commits, not reconstructions. Undoing an unpushed rebase is exact.

Undo only part of a rebase

Full undo is for full regret. If the rebase was ninety percent right and one pick was wrong, don't nuke the whole thing:

The reflog full-reset is the big hammer. Reach for it when the rebase itself was the mistake — wrong base, wrong branch, "why is my history suddenly unrecognizable" — not when a single commit is.

Case 3: you already pushed the rebase

Now the remote carries the rebased history. Restore locally as above, then overwrite the remote — carefully:

git push --force-with-lease

Always --force-with-lease over plain --force: it refuses to push if the remote moved since your last fetch, so you can't silently clobber a teammate's commit you haven't seen.

But understand what the flag does not protect: anyone who already pulled the rebased branch. Their clones now contain history you're about to delete from the remote, and their next pull becomes a diverged mess they have to reset --hard out of — or they accidentally merge the rebased commits back in, resurrecting the very thing you undid. So before force-pushing the undo:

Rebased onto the wrong base entirely?

If the branch itself is fine but sitting on the wrong foundation — say you rebased onto develop when you meant main — you don't need to undo first. Transplant directly with --onto:

git rebase --onto main develop feature-x

That reads as "take the commits on feature-x that came after develop, and replay them onto main." One command, no detour through the old state. The reflog still covers you if even this goes sideways.

Dropped a commit during an interactive rebase?

Same recovery, smaller blast radius. That drop line in your rebase -i didn't delete anything — the commit still exists in the object store. Find it in the reflog (it's the commit right before the one you rebased onto it, or search your shell history for its SHA) and either cherry-pick it back onto your branch, or reset the whole branch to the pre-rebase tip as above.

Make the next rebase boring

Rebases will keep happening; panics don't have to. Drop a thirty-second backup branch before any rebase more complicated than a fast-forward, and recovery becomes git reset --hard backup/before-rebase instead of reflog archaeology. If you work with a dirty tree, git config --global rebase.autoStash true stops "cannot rebase: you have unstaged changes" from tempting you into a hasty git stash you'll forget about. And when the branch is shared, default to --force-with-lease for every force push so the worst case is a rejected push, not a clobbered teammate.

The git.tools way

Restore the pre-rebase state with Time Travel

Point at the commit your branch sat on before the rebase. git.tools opens a pull request that puts it back in exactly that state — reviewed by your team, no force push, no reflog spelunking.

Open Time Travel →

Common questions

Does undoing a rebase restore the original SHAs?

Yes, exactly. The pre-rebase commits were never modified — rebase only made copies. Resetting to the pre-rebase tip brings back the identical commits, hashes included.

I've committed new work on top of the rebased branch. Can I still undo?

Yes, but a plain reset --hard to the pre-rebase tip would orphan your new commits too. Instead: note the SHAs of the new commits, reset to the pre-rebase tip, then git cherry-pick the new commits back on. The reflog keeps the full trail if you lose track.

A teammate already pulled my rebased branch. Now what?

Coordinate before you force-push the undo. They'll need to git fetch and git reset --hard origin/<branch> to realign, and any local work they based on the rebased commits needs to be rebased or cherry-picked onto the restored branch. If that sounds expensive, weigh fixing forward instead.

What's the difference between rebase --abort and the reflog method?

--abort only works while a rebase is still in progress. The moment it finishes (or you --continue past the last conflict), --abort is off the table and the reflog/ORIG_HEAD reset is your path. Same destination, different door.

Does git pull --rebase count as a rebase I can undo?

Yes — it's a fetch plus a rebase, and the rebase half sets ORIG_HEAD and writes reflog entries like any other. If a pull --rebase just rewound and replayed your local commits in a way you hate, the same git reset --hard ORIG_HEAD (or the reflog) puts you back.

Is there any case where a rebase truly can't be undone?

Locally, practically never — not until garbage collection prunes the old commits weeks later, and not if you act now. The genuinely hard case is when the rebase was pushed long ago, others built on it, and "undo" would mean rewriting history a whole team depends on. That's not a git problem anymore; that's a negotiation.