Git’s Reflog: Your Local Safety Net for Lost Work

Git’s Reflog is often described as a safety net, but it’s more accurate to think of it as Git’s personal diary. It records every movement of the HEAD pointer—each commit, merge, rebase, cherry-pick, and reset—so when something goes wrong, it’s the first place to look for answers.

This journal is a private, workspace-specific record. Unlike the repository itself, it is not replicated when you push or pull. The Reflog lives locally in .git/logs/refs/heads/ and tracks the history of each branch’s commits, making it a powerful tool for undoing mistakes.

Reflog vs. Git Log: Complementary Views

The git log command shows your commit history by traversing the ancestry of HEAD: it prints the current commit, then its parent, then the grandparent, and so on. This is a repository-level view that is shared with collaborators.

git reflog, on the other hand, doesn’t walk the ancestry chain. Instead, it lists every commit that HEAD has pointed to, in reverse chronological order. It’s an “undo history” in the same way a word processor tracks your edits—local to your machine alone.

By default, Git cleans up the Reflog after 90 days, but you can adjust that window. To set it to 180 days:

$ git config gc.reflogExpire 180.days.ago
Screenshot of a Terminal with a light yellow background and black text. The content shows the output from the git config gc.reflogExpire 180.days.ago command.
The repository’s configuration file (.git/config) now includes the variable reflogExpire with the value 180.days.ago

Alternatively, you can set it to never expire:

$ git config gc.reflogExpire never

When changing the expiration, remember that Git differentiates between the repository’s configuration (.git/config), the per-user configuration ($HOME/.gitconfig), and system-wide settings (/etc/gitconfig). Use the --global or --system flags to modify settings at those levels.

Recovering Lost Commits

Consider a common scenario: you run git reset to remove the last two commits from your branch, only to realize later that you needed those changes. Panic sets in—until you remember the Reflog.

Suppose your original history has a commit 2b504bee (“Change headlines for about and imprint”) that you want to be your new HEAD. You reset to it:

$ git reset --hard 2b504bee
Screenshot of the Tower application interface. The master branch is selected in the right navigation, the first commit is selected in the center panel, and the detail for that commit is displayed in the right panel. The commits in the center panel are clean and linear without any additional commits or branches.

The commits are gone from your log, but not from history. If you check git reflog, you’ll see the journal entries ordered from newest to oldest:

Screenshot of an open Terminal window with a light yellow background. The text is mainly black, but some words are highlighted in red, light blue and bright green. The top line is the git reset --hard 2b504bee command. The second line says the head is now at that commit ID. The third line is the git reflog command, which outputs the history.

The top entry should show your recent git reset action. To restore the state from before that reset, copy the hash of the previous commit—in this example, e5b19e4. You can then create a new branch from that point:

$ git branch happy-ending e5b19e4

The new branch, happy-ending, now contains the commits you thought were gone. Nothing is actually lost.

Bringing a Deleted Branch Back

The same technique works for entire branches. Imagine you delete a feature/login branch that contains a unique commit C3 not merged anywhere else:

Illustration showing the commit history flow of a feature/login branch with ID C2 being deleted from a C2 branch that is off the master branch. Beside the diagram is a list of the steps taken to deleted the branch, ending with step 4: you panic next to a screaming emoji.

First, you must switch off the branch—Git won’t let you delete the branch you’re currently on:

Screenshot of an open Terminal window with a light yellow background and mostly black text, though the branch and committer names are highlighted in bright green. The first command is git status, the second is git checkout master, the third is git branch -vv, the fourth is git branch -D feature/login, and the last command is git branch -vv.

Now, with the branch deleted, your team changes its mind. A quick look at the Reflog shows the last entry was the switch to master, with hash b1c249b:

$ git reflog
776f8ca (HEAD -> master) HEAD@{0}: checkout: moving from feature/login to master
b1c249b (feature/login) HEAD@{1}: checkout: moving from master to feature/login
[...]

Recreate the branch from that state:

$ git branch feature/login b1c249b
$ git branch -vv
  feature/login b1c249b Change Imprint page title
* master        776f8ca Change about title and delete error page

Your feature/login branch is back, complete with its valuable commit:

Screenshot of the Tower application interface. The feature/login branch is selected in the left panel, the commit history for the branch is in the center panel with the first commit selected, and the left panel displays more information ab out the commit, including the author, date, refs, hashes, and modified files.

Track Your History, Keep Your Work

The Reflog turns potential catastrophes into minor detours. The key step is identifying the correct hash in the journal—after that, restoring lost commits or branches is remarkably straightforward. Whether you’re working from the command line or a graphical client, knowing how to read the Reflog gives you a reliable way to recover from accidental resets and deletions.