Git Reflog - Restoring commits not shown in git log


Git's reflog records the position of HEAD (the ref for the current state of the repository) every time that it is changed. Generally, every operation that might be destructive involves moving the HEAD pointer (since if anything is changed, including in the past, the tip commit's hash will change), so it is always possible to revert back to an older state, before a dangerous operation, by finding the right line in the reflog.

Objects that are not referenced by any ref are usually garbage collected in ~30 days, however, so the reflog may not always be able to help.

Recovering from a bad rebase

Suppose that you had started an interactive rebase:

git rebase --interactive HEAD~20

and by mistake, you squashed or dropped some commits that you didn't want to lose, but then completed the rebase. To recover, do git reflog, and you might see some output like this:

aaaaaaa [email protected]{0} rebase -i (finish): returning to refs/head/master
bbbbbbb [email protected]{1} rebase -i (squash): Fix parse error
ccccccc [email protected]{n} rebase -i (start): checkout HEAD~20
ddddddd [email protected]{n+1} ...

In this case, the last commit, ddddddd (or [email protected]{n+1}) is the tip of your pre-rebase branch. Thus, to recover that commit (and all parent commits, including those accidentally squashed or dropped), do:

$ git checkout [email protected]{n+1}

You can then create a new branch at that commit with git checkout -b [branch]. See Branching for more information.