# The reflog

> Git’s record of everywhere HEAD and each branch has pointed — how you get back a commit you “lost”.

Concept · How Git works · https://levelcode.org/concepts/reflog

Whenever HEAD or a branch moves (commit, reset, rebase, merge, checkout, amend), Git appends a line to that ref's **reflog**. It's a local diary of where your refs have been:

```bash
$ git reflog
9f2c1e7 (HEAD -> main) HEAD@{0}: reset: moving to HEAD~3
c81d4a2 HEAD@{1}: commit: Add password reset email
5b0e9f1 HEAD@{2}: commit: Add password reset form
2a7c3d8 HEAD@{3}: rebase (finish): returning to refs/heads/main
```

Commits don't disappear when no branch points to them any more. They stay in the [object store](https://levelcode.org/concepts/git-object-model) until garbage collection removes unreachable objects, which by default happens only after their reflog entries expire (about 30 days for unreachable commits, 90 days otherwise). The reflog is how you find them again.

## Recovering

**Undo a bad `reset --hard`:**

```bash
git reflog                      # find the commit from before the reset: c81d4a2
git reset --hard c81d4a2        # move the branch back (or: git reset --hard HEAD@{1})
```

**Undo a rebase that went wrong:**

```bash
git reflog                      # find "rebase (start)" and take the entry just before it
git reset --hard HEAD@{5}
# or, immediately after the rebase:
git reset --hard ORIG_HEAD      # reset, rebase and merge save the previous position here
```

**Get back commits made on a detached HEAD**, or on a branch you deleted:

```bash
git reflog                      # find the last commit
git switch -c recovered 5b0e9f1
```

`git reflog show feature-x` shows one branch's own history, which helps after it has been reset or rebased several times.

## Limits

- **Local only.** The reflog isn't pushed or cloned. It knows what happened in *your* repository, not what a teammate did.
- **Only commits.** Changes that were never committed, such as edits wiped by `reset --hard` or `restore`, were never in the object store. `git stash` before risky operations protects them, and stashes are commits.
- **Entries expire.** Recover soon rather than months later.

The reflog makes most of Git's history-rewriting commands safe to try: [rebase](https://levelcode.org/concepts/merge-vs-rebase), amend and reset can all be undone. It doesn't help once you've force-pushed over someone *else's* commits, which is why the golden rule of rebasing still applies.
