Recover Lost Commits with git reflog

Recover lost commits with git reflog — hands-on Git Tutorial lesson.

Focus: recover lost commits with git reflog

Sponsored

You've just run git reset --hard on the wrong branch, or maybe you deleted a branch that contained weeks of work. Your heart sinks as you realize the commits are gone. But here's the secret: in Git, almost nothing is truly lost. The reflog—Git's safety net—records every movement of your HEAD and branch references, and with it you can recover lost commits, branches, and even entire states of your repository. This lesson shows you exactly how to use git reflog to turn panic into a five-minute recovery.

The problem this lesson solves

Imagine you're working on a feature branch, and you accidentally run git reset --hard HEAD~3 on the wrong branch, or you delete a branch that contains unmerged work. You think your commits are gone forever, and you start regretting not pushing more often. This is a common nightmare for developers, and it happens more often than you'd think. The good news: Git keeps a detailed log of every reference update—called the reflog—so you can rewind time and bring those "lost" commits back.

Without the reflog, you'd be stuck with git fsck and manual commit hunting, which is slow and error-prone. With it, recovery is often a single command away. This lesson gives you the exact mental model and commands to recover lost commits with git reflog, whether you've reset, rebased, or deleted a branch.

Core concept / mental model

Think of Git as a time machine. The commit graph is the visible timeline—the branches and tags you normally see. The reflog is your black box recorder that logs every time the tip of a branch or HEAD changes. It records the old and new commit hashes, the command that caused the change, and a timestamp. So even if a commit becomes unreachable (no branch points to it), its hash remains in the reflog, and you can jump back to it.

  • HEAD reflog (git reflog): shows all actions that moved HEAD, including checkouts, resets, commits, merges, rebases, and amends.
  • Branch reflogs (e.g., git reflog show feature-branch or git reflog feature-branch): shows all updates to that specific branch, even if the branch was later deleted.

A key distinction: git log shows the commit graph (what's reachable from current refs), while git reflog shows the history of reference movements (what happened in your repository). The reflog is local—it's not shared with remote—so it only records activity on your machine.

How it works step by step

Here's the step-by-step process to recover lost commits with git reflog:

  1. Stop panicking — do not run any more Git commands that move refs (like git gc or git checkout -B), as they could overwrite reflog entries.
  2. Find the lost commit — run git reflog to see a list of all recent HEAD movements. Each line shows a short hash, the action (e.g., reset, commit, checkout), and a description.
  3. Identify the commit — look for the commit you want to restore. It might be the one that was the tip of a deleted branch, or the commit just before an unwanted reset.
  4. Recover the commit — create a branch at that commit using git branch <new-branch-name> <commit-hash>, or checkout the commit directly with git checkout <hash> (detached HEAD) and then create a branch.
  5. Verify — run git log --oneline on the new branch to confirm your work is back.

The same process works for deleted branches: the branch's reflog entry will appear in git reflog, and you can recreate the branch at the recorded hash.

Hands-on walkthrough

Let's practice. Create a temporary repository and lose a commit on purpose.

# Set up a test repo
mkdir reflog-demo && cd reflog-demo
git init
git config user.email "you@example.com"
git config user.name "Your Name"

# Create some commits
echo "first" > file.txt
git add file.txt && git commit -m "first commit"
echo "second" >> file.txt && git commit -am "second commit"
echo "third" >> file.txt && git commit -am "third commit"

# Oops! We reset too far back
git reset --hard HEAD~2

Now your working directory is at the first commit, and the second and third commits are "lost". Let's recover them with the reflog.

# View the reflog
git reflog

Output (your hashes will differ):

abc1234 HEAD@{0}: reset: moving to HEAD~2
def5678 HEAD@{1}: commit: third commit
fedcba9 HEAD@{2}: commit: second commit
1234567 HEAD@{3}: commit: first commit

The commit def5678 is the one we want (the third commit). To restore it, create a branch at that commit:

git branch recovered def5678
# Switch to it (or checkout the branch when you're ready)
git checkout recovered

Now git log --oneline shows:

def5678 third commit
fedcba9 second commit
1234567 first commit

Your work is back! You can now merge this branch into wherever you need it.

For a deleted branch, the process is identical. If you delete a branch called feature that pointed to def5678, the reflog will show its last position, and you can recreate it with git branch feature def5678.

Compare options / when to choose what

The reflog is not the only way to recover lost commits. Here's a comparison with other methods:

Method Purpose When to use Pros Cons
git reflog Find lost commits from local ref movements After reset, rebase, or branch deletion Fast, precise, simple Only local, entries expire (default 90 days)
git fsck --lost-found Find dangling commits and blobs When reflog is missing or the commit is old Finds any unreachable object No context, manual identification, slower
git cherry-pick Apply specific commits (hash known) When you know the hash and want a copy Copies changes without moving refs Requires hash from somewhere (e.g., reflog)
git revert Undo changes with a new commit When you want to keep history Safe for shared histories Doesn't bring back deleted branches

When to use what:

  • For most recovery scenarios, reflog is your first stop — it gives you the exact commit hashes with context.
  • If the reflog has expired (more than 90 days old) or was cleared, git fsck --lost-found can still find dangling objects.
  • For applying a specific lost commit onto a new base, git cherry-pick is useful after you've identified the hash.
  • For undoing a change without losing the commit history, git revert creates a new commit that reverses the changes — good for shared branches.

Pro tip: Always push critical branches to a remote to avoid relying solely on local reflogs, but remember that the reflog is your best friend for local accidents.

Troubleshooting & edge cases

  • Reflog doesn't show the lost commit: This can happen if the reflog has expired (entries older than 90 days are pruned by default) or if Git garbage collection cleaned up unreachable objects. In that case, run git fsck --full --no-reflogs --unreachable to list all unreachable commits, and inspect them with git show.
  • Reflog shows a commit but the commit message is empty or weird: If you see commit: (amend) or rebase (start), the reflog entry may be from an amend or rebase. Find the commit hash you need and test it with git show before creating a branch.
  • git checkout <hash> leaves you in detached HEAD: That's expected. After verifying the commit, immediately create a branch to avoid losing track: git branch saved-commit <hash> && git checkout saved-commit.
  • Reflog entries are not shared: If you cloned a repository, the reflog only contains your local actions. If you think a commit was pushed to a remote, use git fetch --all to retrieve it, then search git log --all.
  • After recovery, the reflog continues to fill up: Don't worry — it's normal. You can clean old entries with git reflog expire --expire=now --all, but only do that when you're certain you don't need them.

What you learned & what's next

You've learned that the reflog is a powerful recovery tool for lost commits. We covered:

  • What the reflog is and how it tracks reference movements.
  • How to use git reflog to find lost commit hashes.
  • How to recover lost commits and deleted branches by creating branches from those hashes.
  • When to use reflog versus git fsck, cherry-pick, or revert.
  • How to handle common edge cases like expired reflogs and detached HEADs.

You can now confidently recover lost commits with git reflog in your daily work. Next in the Git Tutorial, you'll learn about git bisect — a systematic way to find which commit introduced a bug, which pairs perfectly with the reflog for debugging and recovery workflows. Keep practicing, and remember: Git is forgiving, but the reflog is your best insurance.

Practice recap

Create a new test repository, add three commits, then run git reset --hard HEAD~2. Practice using git reflog to find the lost commit hash and recover it with git branch. Next, simulate a deleted branch by deleting a branch and recreating it from the reflog. This will cement the recovery workflow!

Common mistakes

  • Panicking and running git gc or git checkout -B before checking the reflog — this can overwrite or prune the very entries you need.
  • Forgetting that reflog entries are local and expire after 90 days — if you wait too long, you may need git fsck --lost-found instead.
  • Using git checkout <hash> and then making new commits without creating a branch — you end up in detached HEAD and risk losing work again.
  • Assuming the reflog shows all commits ever made — it only shows actions that moved refs (HEAD and branches), so an old unreachable commit might not appear.

Variations

  1. Instead of git reflog, use git reflog show <branch> to see the history of a specific branch even if it was deleted.
  2. For deeper recovery, use git fsck --full --no-reflogs --unreachable to list dangling commits when the reflog is unavailable.
  3. If you know the lost commit hash, you can merge it directly with git merge <hash> or apply its changes with git cherry-pick <hash>.

Real-world use cases

  • You accidentally run git reset --hard on your feature branch, losing several commits; the reflog lets you restore the branch tip in seconds.
  • A teammate deletes a shared branch before merging, and you need to recreate it locally from its reflog entry to recover the work.
  • After a failed interactive rebase, you abort and lose your original commits; the reflog shows the pre-rebase tips so you can branch back.

Key takeaways

  • The reflog records every movement of HEAD and branches, allowing you to recover lost commits with git reflog.
  • Use git reflog to find lost commit hashes, then create a new branch at that hash to recover the work.
  • Recovering a deleted branch is the same as recovering a reset commit — find its last reflog entry and recreate the branch.
  • If the reflog is unavailable, git fsck --lost-found can still find dangling commits.
  • Always push critical work to a remote to avoid relying solely on local reflogs.
  • After recovery, immediately create a branch from the recovered commit to avoid detached HEAD issues.

Sponsored

Sponsored

Discussion

Questions, corrections, and tips help everyone reading this page.

0 comments

Add a comment

Shown publicly with your comment.

Be constructive · max 4,000 characters

No comments yet — start the thread.

Related tutorials, quizzes, and articles for this topic.