Recover Lost Commits / Reflog

Accidentally deleted a branch? Lost commits after a hard reset? Git's reflog is your safety net. It records every movement of your branch pointers, allowing you to recover commits you thought were gone forever.

Git Reflog Commit Recovery Garbage Collection
What is the Git Reflog?

The reflog (reference log) is Git's safety net. It records every time your branch pointers move—commits, checkouts, merges, rebases, resets, and more. Unlike the commit history, which shows the tree of commits, the reflog shows the chronological history of where your HEAD has been. Think of it as a "browser history" for Git.

If you accidentally delete a branch, reset to the wrong commit, or lose work during a rebase, the reflog is your best friend. Git keeps reflog entries for about 90 days by default, giving you plenty of time to recover from mistakes. The reflog is local to your repository, so it's not shared when you push or pull.

The reflog only exists on your local machine. GitHub does not store reflog information. Always push important branches to remote to protect against local disk failures.
Viewing the Reflog

To view the reflog, run git reflog or git log -g. The output shows each movement of HEAD with a commit hash, an index number (like HEAD@{1}), and a description of what happened. The most recent entries appear first.

The index numbers are relative to the current position. HEAD@{0} is where you are now. HEAD@{1} is where you were before your last operation. HEAD@{2} is two operations ago, and so on. This makes it easy to navigate backward through your Git history.

# View the reflog
$ git reflog

# Example output:
a1b2c3d (HEAD -> main) HEAD@{0}: commit: Fix login bug
e4f5g6h HEAD@{1}: checkout: moving from feature to main
i7j8k9l HEAD@{2}: commit: Add new feature
m9n0o1p HEAD@{3}: reset: moving to HEAD~2
q2r3s4t HEAD@{4}: commit: Initial commit
Each entry has a unique commit hash. You can use these hashes with git show, git checkout, or git reset to recover lost commits.
Common Recovery Scenarios

Scenario 1: You did a hard reset and lost commits. This is the most common reason to use reflog. Run git reflog, find the commit hash from before the reset (look for "reset" in the description), and reset back to that commit.

Scenario 2: You deleted a branch that had unmerged work. The commits are still in the reflog. Find the last commit of the deleted branch in the reflog, then create a new branch at that commit using git branch .

Scenario 3: A rebase went wrong. During a rebase, Git creates many reflog entries. Find the commit from before the rebase started (look for "rebase" or "checkout") and reset to that point with git reset --hard.

# Scenario 1: Recover from bad hard reset
$ git reflog
a1b2c3d HEAD@{2}: reset: moving to HEAD~3
e4f5g6h HEAD@{3}: commit: Important work before reset

$ git reset --hard e4f5g6h

# Scenario 2: Recover a deleted branch
$ git reflog
i7j8k9l HEAD@{5}: commit: Last commit of deleted-feature

$ git branch recovered-feature i7j8k9l

# Scenario 3: Abort a failed rebase and restore
$ git reflog
m9n0o1p HEAD@{10}: checkout: before rebase
$ git reset --hard m9n0o1p
Recovering Specific Files from Lost Commits

Sometimes you don't need to restore the entire commit—just one file from a lost commit. You can use git checkout with the commit hash and file path to extract a single file from a lost commit.

First, find the commit hash in the reflog. Then run git show :path/to/file to preview the file's content. To restore it to your working directory, use git checkout -- path/to/file. This is useful when you want to recover a specific function or configuration without undoing other changes.

# Preview a file from a lost commit
$ git show e4f5g6h:src/app.js

# Restore a single file from a lost commit
$ git checkout e4f5g6h -- src/app.js
$ git status # File is now staged for commit

# Restore multiple files
$ git checkout e4f5g6h -- src/ config/
Reflog Expiration and Garbage Collection

Reflog entries expire after 90 days by default. After that, Git's garbage collection (git gc) may remove unreachable commits permanently. This means you have a 90-day window to recover lost work. After 90 days, recovery becomes much harder or impossible.

You can adjust the expiration time with configuration settings. For critical repositories, you might want to keep reflog entries longer. To manually expire old entries, use git reflog expire. To trigger garbage collection, use git gc.

# Set reflog expiration to 180 days
$ git config gc.reflogExpire "180.days.ago"
$ git config gc.reflogExpireUnreachable "90.days.ago"

# Manually expire old reflog entries
$ git reflog expire --expire=now --all

# Run garbage collection
$ git gc --prune=now

# Check reflog expiration settings
$ git config --get gc.reflogExpire
Running git gc --prune=now permanently deletes unreachable commits. Only do this if you're certain you don't need any lost commits.
What About Commits Already Pushed?

The reflog is local, so it won't help if your local hard drive fails. For important work, always push to GitHub regularly. If a commit was pushed and then force-pushed over, you can still recover it from GitHub's event timeline or by checking the reflog of a coworker who pulled before the force push.

On GitHub, you can view a repository's network graph to see all branches and commits. If a branch was deleted, you may still find its commits referenced in pull requests or issues. For force-pushed commits, GitHub's API can sometimes retrieve them if you act quickly.

# Check if a commit exists on GitHub
$ git ls-remote origin | grep

# Fetch all remote branches and tags
$ git fetch --all

# Check reflog of a remote branch
$ git reflog show origin/main
The best recovery strategy is prevention: push frequently, use branch protection, and consider GitHub's repository backups for critical code.
Visualizing Lost Commits

The reflog gives you commit hashes, but sometimes you need to see the commit tree to understand what was lost. Use git log --graph --oneline --all to see all reachable commits. For unreachable commits (those only in reflog), use git log --walk-reflogs.

You can also create a temporary branch at a reflog entry to explore it safely. Use git branch temp then git log temp to see what's there. Once you've confirmed it's the right commit, you can merge or cherry-pick as needed.

# See all commits including unreachable ones
$ git log --graph --oneline --all

# See reflog as a graphical timeline
$ git log --graph --oneline --walk-reflogs

# Create a temporary branch to explore a lost commit
$ git branch explore-lost e4f5g6h
$ git checkout explore-lost
$ git log --oneline -10

# After verification, cherry-pick the lost commit
$ git checkout main
$ git cherry-pick e4f5g6h
Prevention: Avoiding Data Loss

Push frequently. The safest commit is one that's on GitHub. Push after completing logical work, not just at the end of the day.

Use branches for experiments. Create a branch before trying risky operations like rebasing or resetting. If something goes wrong, your original branch is safe.

Review before resetting. Always run git status and git log before a hard reset. Consider using git reset --soft or git stash first.

Enable push protection. GitHub's branch protection can prevent force pushes to important branches, protecting shared work from accidental overwrites.

Back up your repositories. Regular backups of your local repositories (or using GitHub's repository backups) provide an additional safety net.

The reflog is a powerful recovery tool, but it's not a backup. Push to GitHub, use branches, and maintain regular backups for critical work.
Frequently Asked Questions
How long does Git keep reflog entries?
By default, reachable reflog entries expire after 90 days. Unreachable entries expire after 30 days. You can configure these values with git config gc.reflogExpire and gc.reflogExpireUnreachable.
Can I recover commits after running git gc?
Once git gc runs and removes unreachable commits, recovery becomes extremely difficult. Professional data recovery tools might help, but it's not guaranteed. Prevention is better than recovery.
Does GitHub store reflog information?
No. The reflog is local to each clone. GitHub does not store or expose reflog data. This is why pushing frequently is important for data safety.
How do I recover a commit that was force-pushed over?
Check if anyone on your team pulled before the force push. Their local reflog will have the commit. Ask them to push it to a new branch. On GitHub, the commit may still be visible in the network graph or pull request history.
Can I recover a commit if I've closed my terminal?
Yes! The reflog is stored in the .git directory. As long as you haven't run git gc or deleted the repository, your reflog is preserved across terminal sessions.
What's the difference between git reflog and git log?
git log shows the commit history (the tree of commits). git reflog shows the history of where your HEAD has been (including commits that are no longer in the tree). The reflog includes commits lost through reset or rebase.
How do I recover a stash that was dropped?
Use git reflog and look for entries with "stash". The stash reflog is stored separately. Use git stash list to see stashes, or git fsck --unreachable to find orphaned commits that were stashed.
Can I recover commits after deleting the .git folder?
No. The .git folder contains the entire repository history, including the reflog. Without it, recovery is impossible unless you have a remote backup or GitHub copy.
Previous: Resolve Merge Conflicts Next: Detached HEAD State

The reflog is Git's emergency recovery system. When you make a mistake, don't panic—check the reflog first. Most lost commits can be recovered with a few commands.