Recovery

Recovering with reflog

Use reflog to locate previous references and recover from reset, rebase, or lost branch states.

Who This Is For
  • Anyone actively handling a Git mistake
  • Readers who want a conservative rescue habit before trouble happens
Prerequisites
  • Stop mutating the repo further
  • Be ready to inspect `git reflog`, `git status`, and `git log --graph`
Common Risks
  • Running more reset or rebase commands before preserving a checkpoint
  • Changing shared history before assessing blast radius

git reflog is often the most practical recovery tool in everyday Git accidents. After a bad reset, rebase, amend, or pull, what you usually lose first is not the commit object itself but the name and reference that used to point to it.

What reflog actually gives youIt records how references moved over time. Recovery usually starts by finding the old position, then deciding whether to reset, branch off, or cherry-pick from it.
Recent reference movement
HEAD@{3}HEAD@{2}HEAD@{1}Now
Safer first move
rescue/recover
Find the old position before choosing the fix

Reflog does not magically undo everything for you. It helps you answer a more important question first: where did this branch or HEAD point before things went sideways? Once you know that, the recovery strategy becomes much easier to choose safely.

When reflog is the right first stop

  • after a reset --hard you regret
  • after a rebase that rewrote history in the wrong way
  • after a pull that changed the branch differently than expected
  • after deleting a branch and suspecting the commits still exist
  • after commit --amend or interactive rebase when you want the previous state back

The real value is that you do not need to know the final recovery plan yet. You only need to relocate the trustworthy old state.

A conservative recovery flow

1. Inspect reflog before trying more mutations

git reflog --date=local

Look for entries that correspond to the operation right before the mistake. Useful clues often include:

  • reset: moving to ...
  • rebase (start) / rebase (finish)
  • checkout: moving from ... to ...
  • commit (amend): ...

2. Create a rescue branch before resetting anything

git switch -c rescue/recover HEAD@{1}

If HEAD@{1} is not the correct entry, use the SHA or another reflog position instead.
The goal here is not to finish the recovery immediately. It is to pin the old state somewhere safe so later experiments do not erase your best recovery target.

3. Choose the real restoration path afterward

  • want the current branch to return to that state: git reset --hard <target>
  • want to keep today’s state and recover in parallel: continue on the rescue/* branch
  • want only some commits back: git cherry-pick <sha>
  • want to compare both sides first: git log --oneline --graph --decorate --all

Why “branch first, reset later” is safer

Many people know reflog is useful, but still jump straight from “I found the old SHA” to “I will reset immediately.” The problem is that recovery commands are also reference-moving commands. If you guess wrong once, you can make the situation harder to reason about.

A safer rhythm is:

  1. run git reflog
  2. create rescue/...
  3. inspect content and history on that rescue branch
  4. only then decide whether the original branch should move

This costs a little more time, but incident response is usually better when it is calm and reversible.

Three common recovery situations

Recover after reset

Your job is to find the branch tip from before the reset, pin it on a rescue branch, and only then decide whether the original branch should be moved back.

Recover after rebase

Do not focus first on which SHAs changed. Focus on where the branch pointed before the rebase started. Reflog usually makes that visible quickly.

Recover after pull

First understand what the pull actually did:

  • fast-forward
  • merge
  • or rebase

Then use reflog to locate the pre-pull position. Do not hard-reset blindly before you know what changed.

Reflog is powerful, but it has limits

  • reflog is local, not a shared cross-machine audit log
  • entries are not kept forever
  • aggressive cleanup and time can shrink the recovery window
  • success still depends on whether the old objects remain available

That is why the best habit is to create a rescue branch as soon as you find a meaningful old position.

Do not treat reflog like unlimited undo history

Reflog is a recovery window, not a permanent backup strategy. When you find a useful old position, capture it early. A rescue branch is often the difference between a controlled recovery and a second accident during the first one.

Common mistakes

Resetting immediately after finding an old SHA

You may be right, but it is still the riskier sequence. Branch first if you want a reversible path.

Thinking reflog matters only after reset

Checkout, merge, rebase, amend, and pull can all leave useful reflog entries.

Assuming deleted branch means deleted commits

Sometimes only the name disappeared. The objects may still exist and be recoverable.

Practice: recover from a deliberate bad reset

Create a tiny repository, make a reversible mistake, and use reflog to recover it. This is one of the highest-value Git drills you can run.

Setup
mkdir reflog-lab && cd reflog-lab
git init
echo one > notes.txt
git add notes.txt
git commit -m "init"
echo two >> notes.txt
git commit -am "second"
echo three >> notes.txt
git commit -am "third"
Steps
  1. Run `git reset --hard HEAD~1`
  2. Inspect `git reflog --date=local` and find the pre-reset entry
  3. Create `git switch -c rescue/recover HEAD@{1}`
  4. Compare both branches with `git log --oneline --graph --decorate --all`
  5. Decide whether the original branch should move back or whether rescue work should continue separately
What you should observe
  • The old commit does not vanish immediately
  • A rescue branch safely captures the old position
  • The current branch and rescue branch become easier to reason about
  • Recovery becomes a choice, not a panic reaction
Common mistakes
  • Running another hard reset before creating a rescue branch
  • Forgetting which reflog entry was the pre-incident state
  • Treating `HEAD@{1}` as always correct without inspecting the reflog context

The habit worth remembering

When Git history looks wrong, start with this:

  1. git reflog
  2. create a rescue branch
  3. choose reset, cherry-pick, merge, or manual reconstruction only after the old position is safe