Introduction

You've accidentally lost commits through a destructive git operation like git reset --hard, git rebase, git branch -D, or git push --force. The commits seem gone, but git reflog tracks all HEAD movements and can help you recover the lost work.

Symptoms

After a hard reset:

bash
$ git log --oneline
def456 (HEAD -> main) Previous commit
# Your recent commits are gone!

After branch deletion:

bash
$ git branch -D feature-branch
Deleted branch feature-branch (was abc123).
# Branch and its commits are "gone"

After force push:

bash
$ git push --force origin main
+ ghi789...abc123 main -> main (forced update)
# Remote commits overwritten

After rebase gone wrong:

bash
$ git rebase --abort
# Commits from the rebase seem lost

Common Causes

Git preserves all commits for a period (default 90 days) even after they're no longer reachable from any branch. The reflog records every change to HEAD, creating a history of where you've been. This means "lost" commits still exist in the object database and can be recovered using reflog.

Step-by-Step Fix

Step 1: View the Reflog

See the complete history of HEAD movements:

bash
git reflog

Output shows all recent HEAD positions:

bash
abc123 (HEAD -> main) HEAD@{0}: reset: moving to abc123
def456 HEAD@{1}: reset: moving to def456
ghi789 HEAD@{2}: commit: Add new feature
jkl012 HEAD@{3}: commit: Fix bug in feature
mno345 HEAD@{4}: checkout: moving from feature to main
pqr678 (feature) HEAD@{5}: commit: Work on feature
stu901 HEAD@{6}: branch: Created from main

Step 2: Find the Lost Commit

Search reflog for specific actions:

```bash # Find commits git reflog show --grep="commit"

# Find resets git reflog show --grep="reset"

# Find branch operations git reflog show --grep="branch" ```

View reflog for a specific branch:

bash
git reflog show feature-branch

Step 3: Examine the Found Commit

Once you identify a likely commit, examine it:

bash
git show HEAD@{5}

Or by commit hash:

bash
git show abc123

Check what files changed:

bash
git show --stat HEAD@{5}

Step 4: Recover Using Reset

To restore your branch to a previous state:

bash
# Reset to the lost commit
git reset --hard HEAD@{5}

Or using the commit hash:

bash
git reset --hard abc123

For a softer recovery (keeping current changes):

bash
git reset --soft HEAD@{5}

Step 5: Recover a Deleted Branch

To recreate a deleted branch:

```bash # Find where the branch was git reflog show --grep="branch: Created"

# Recreate the branch at that commit git branch recovered-branch HEAD@{5} ```

Or:

bash
git branch recovered-branch abc123

Step 6: Cherry-Pick Lost Commits

If you only want specific commits:

```bash # Cherry-pick a single commit git cherry-pick abc123

# Cherry-pick a range git cherry-pick abc123..def456 ```

Step 7: Create a Recovery Branch

Instead of resetting, create a new branch:

bash
git branch recovery-branch HEAD@{5}
git checkout recovery-branch

This preserves your current state while recovering the lost work.

Step 8: Recover After Force Push

If you force-pushed and lost commits on the remote:

```bash # Local reflog still has the commits git reflog

# Reset to the commit before force push git reset --hard HEAD@{1}

# Force push back git push --force origin main ```

Step 9: Find All Dangling Commits

Search for all unreachable commits:

bash
git fsck --lost-found

Output shows:

bash
dangling commit abc123...
dangling blob def456...
dangling tree ghi789...

Examine dangling commits:

bash
git show abc123

Or check the lost-found directory:

bash
ls .git/lost-found/commit/

Step 10: Extend Reflog Retention

By default, reflog keeps entries for 90 days. To extend:

```bash # Set to 1 year git config --global gc.reflogExpire 365.days

# Keep unreachable objects for 1 year git config --global gc.reflogExpireUnreachable 365.days ```

Prevent garbage collection from cleaning up:

bash
# Disable auto GC temporarily
git config --global gc.auto 0

Step 11: Recovery from Remote Reflog

If someone else force-pushed to a shared branch:

```bash # Fetch all refs git fetch origin

# Check remote reflog (if enabled on server) git reflog show origin/main ```

If the commits were pushed and you have a clone, check your local reflog before updating:

bash
# Don't pull yet! Check reflog first
git reflog show origin/main

Verification

Confirm the recovery:

bash
git log --oneline -10

Your commits should be back:

bash
abc123 (HEAD -> main) Recovered commit
def456 Previous commit

Verify branch exists:

bash
git branch

Should show your recovered branch:

bash
main
* recovered-branch

Check file contents:

bash
git show HEAD:path/to/file.txt

To prevent future loss, consider:

```bash # Create a backup branch before risky operations git branch backup-branch

# Or tag important commits git tag important-milestone ```

  • [Technical troubleshooting: Fix Git Bisect Skip Marking Bad Commit Incorrectly](bisect-skip-marking-bad-incorrectly-git)
  • [Technical troubleshooting: Fix Cherry Pick Range Wrong Order Git Issue in Git](cherry-pick-range-wrong-order-git)
  • [Fix Credential Helper Not Storing Wsl2 Git Issue in Git](credential-helper-not-storing-wsl2-git)
  • [Fix Git Filter-Branch Rewrite Breaking GPG Commit Signatures](filter-branch-rewrite-breaking-signatures-git)
  • [Git Abort Rebase and Recover: Complete Guide](fix-git-abort-rebase)

<script type="application/ld+json"> { "@context": "https://schema.org", "@type": "TechArticle", "headline": "Git Reflog Recovery for Lost Commits", "description": "Learn how to use git reflog to recover lost commits, branches, and work after accidental deletion or destructive operations", "url": "https://www.fixwikihub.com/fix-git-reflog-recovery", "publisher": { "@type": "Organization", "name": "FixWikiHub", "url": "https://www.fixwikihub.com" }, "author": { "@type": "Person", "name": "FixWikiHub Editorial Team" }, "datePublished": "2025-11-18T14:57:31.999Z", "dateModified": "2025-11-18T14:57:31.999Z" } </script>