Git Reflog

The git reflog (Reference Log) is a record of every position that HEAD has pointed to — every branch switch, every commit, every reset, every rebase, every pull. It is essentially a local diary of all movements through the repository's history.

Reflog is stored locally and is NOT pushed to GitHub. It is a personal safety net that allows recovery of commits or changes that appear to be "lost."

Real-life analogy: Think of the reflog as CCTV footage of every action taken in the repository. Even if a file is accidentally deleted from a shelf (via reset, rebase, or amend), the CCTV footage shows the exact moment it was last seen — making it possible to recover it.

When Does Reflog Save the Day?

  • After an accidental git reset --hard that wiped commits
  • After a branch was deleted before merging
  • After a rebase went wrong
  • When looking for an old commit that no longer appears in git log

Viewing the Reflog

git reflog

Sample output:

a3f92b1 (HEAD -> main) HEAD@{0}: commit: Add login page
b7c3d45 HEAD@{1}: commit: Update homepage
c1a2b3c HEAD@{2}: checkout: moving from feature to main
d4e5f6g HEAD@{3}: commit: Start feature work
e7f8g9h HEAD@{4}: reset: moving to HEAD~2

Each entry shows:

  • The short commit hash
  • HEAD@{N} — the N-th position back in the reflog
  • The action that moved HEAD to this position
  • A description of the action

Reflog for a Specific Branch

git reflog main

The Most Important Use: Recovery After git reset --hard

# Scenario: Accidentally reset 3 commits
git reset --hard HEAD~3
# Oh no! Three commits were wiped.

# Step 1: Open reflog to find the lost commits
git reflog
# Output:
# a3f92b1 HEAD@{0}: reset: moving to HEAD~3
# d4e5f6g HEAD@{1}: commit: Third commit
# e7f8g9h HEAD@{2}: commit: Second commit
# f1g2h3i HEAD@{3}: commit: First commit   ← This was before the reset

# Step 2: Recover by resetting back to the lost commit
git reset --hard f1g2h3i
# Or use the reflog reference:
git reset --hard HEAD@{3}

# Three commits are fully restored!

Recovering a Deleted Branch

# Scenario: A branch was deleted before merging
git branch -D feature-login
# "Oh no! I haven't merged this yet!"

# Step 1: Find the last commit of the deleted branch in reflog
git reflog
# Output includes:
# b7c3d45 HEAD@{5}: commit: Add login validation
# ...

# Step 2: Create a new branch pointing to the recovered commit
git switch -c feature-login b7c3d45

# The branch is fully restored with all its commits!

Recovering After a Bad Rebase

# Scenario: A rebase went very wrong
git rebase main
# Something went terribly wrong...

# Find the state before the rebase
git reflog
# Output:
# a1b2c3d HEAD@{0}: rebase (finish): returning to refs/heads/feature
# b1c2d3e HEAD@{1}: rebase (start): checkout main
# c1d2e3f HEAD@{2}: commit: My feature work   ← Before the rebase

# Recover the pre-rebase state
git reset --hard c1d2e3f

Show Reflog with Dates

git reflog --date=relative

Output:

a3f92b1 HEAD@{2 minutes ago}: commit: Add login page
b7c3d45 HEAD@{1 hour ago}: commit: Update homepage

How Long Does Reflog Keep History?

By default, reflog entries are kept for 90 days (30 days for unreachable commits). After that, Git may garbage-collect them. The expiry time can be configured:

# Keep reflog entries for 180 days
git config gc.reflogExpire 180.days

# Keep unreachable entries for 90 days
git config gc.reflogExpireUnreachable 90.days

Reflog is Local Only

The reflog is stored in .git/logs/ and is never pushed to GitHub. It is unique to each developer's machine. This means if a repository is cloned fresh, the reflog history from the original machine is not available.

Summary

The git reflog is the ultimate safety net in Git. It records every movement of HEAD, allowing recovery of lost commits, deleted branches, and botched rebases that would otherwise be permanently gone. The key recovery pattern is: find the hash in reflog → git reset --hard <hash> or git switch -c branch-name <hash>. The reflog is kept for 90 days by default and is stored locally only.

Leave a Comment

Your email address will not be published. Required fields are marked *