Git Reflog and Recovery: Your Safety Net for Destructive Operations

Master git reflog to recover lost commits, undo destructive operations, and understand Git's safety net. Learn recovery techniques for reset, rebase, and merge disasters.

published: reading time: 24 min read author: Geek Workbench updated: March 31, 2026

Git Reflog and Recovery: Your Safety Net for Destructive Operations

When to Use / When Not to Use

Use Git Reflog When

  • Accidental reset — You ran git reset --hard and lost commits
  • Dropped stash — You accidentally dropped a stash with important work
  • Failed rebase — A rebase went wrong and you need to go back
  • Force push recovery — You force pushed the wrong branch and need the old state
  • Orphaned commits — Commits exist but no branch points to them
  • Understanding history — You want to see what operations were performed locally

Do Not Use Git Reflog When

  • Shared history recovery — Reflog is local; it can’t recover commits never pushed
  • Long-term backup — Reflog entries expire (default 90 days); it’s not a backup system
  • Remote recovery — Reflog doesn’t exist on the remote; it’s a local-only feature
  • Deleted repository — If the .git directory is gone, reflog is gone too

Core Concepts

Git reflog tracks HEAD movements and branch updates:

Entry TypeTriggerExample
commitCreating a new commitcommit: feat: add user authentication
checkoutSwitching branchescheckout: moving from main to feature/login
resetRunning git resetreset: moving to HEAD~3
rebaseRunning git rebaserebase: picking abc1234
mergeRunning git mergemerge main: Fast-forward
stashStash operationsstash: WIP on feature: abc1234
cherry-pickRunning git cherry-pickcherry-pick: def5678

Each reflog entry has a reference: HEAD@{n} where n is how many operations ago. HEAD@{0} is the current state, HEAD@{1} is the previous state, and so on.

graph LR
    A["HEAD@{0}: Current State"] --> B["HEAD@{1}: Previous Operation"]
    B --> C["HEAD@{2}: Earlier Operation"]
    C --> D["HEAD@{3}: Even Earlier"]
    D --> E["HEAD@{n}: Oldest Tracked"]

Architecture and Flow Diagram

The reflog structure and recovery workflow:

graph TD
    A[Local Operations] --> B[HEAD Reflog]
    A --> C[Branch Reflog]
    B --> D["refs/heads/main@{n}"]
    B --> E["refs/heads/feature@{n}"]
    C --> F[".git/logs/HEAD"]
    C --> G[".git/logs/refs/heads/"]
    D --> H{Need Recovery?}
    E --> H
    H -->|Yes| I[git reflog show]
    I --> J[Find Target Commit]
    J --> K[git reset/checkout/branch]
    K --> L[Recovered State]

Step-by-Step Guide

Reference: 1. Viewing the Reflog

Reference: 4. Recovering a Dropped Stash

1. Viewing the Reflog

The basic reflog shows recent HEAD movements:


# Show HEAD reflog
git reflog

# Output example:
# abc1234 HEAD@{0}: commit: feat: add payment processing
# def5678 HEAD@{1}: commit: feat: add cart functionality
# ghi9012 HEAD@{2}: checkout: moving from main to feature/checkout
# jkl3456 HEAD@{3}: reset: moving to HEAD~2
# mno7890 HEAD@{4}: commit: feat: add product listing
# pqr1234 HEAD@{5}: clone: from https://github.com/org/project.git

# Show reflog for a specific branch
git reflog show main

# Show reflog with dates
git reflog --date=iso

# Show reflog with full commit hashes
git reflog --format='%H %gd %gs'

2. Essential Reflog Patterns

Key patterns for everyday reflog usage:


# Get only the last 10 entries
git reflog -10

# Show branch-specific reflog with relative times
git reflog show main --format='%gd %gs %cr' -10

# Find a specific operation by message
git reflog --format='%gd %gs' | grep -i "reset\|rebase"

# Show reflog for a specific time window
git reflog --since='2 days ago'

# Export reflog to JSON for scripting
git reflog --format='{"ref":"%gd","message":"%gs","time":"%cr"}' > reflog.json

3. Recovering from Accidental Reset

The most common disaster scenario:


# Scenario: You accidentally reset main back 5 commits
git reset --hard HEAD~5

# Oh no! Your work is gone... but not really
# Check the reflog
git reflog

# Find the commit you were at before the reset
# abc1234 HEAD@{1}: reset: moving to HEAD~5
# def5678 HEAD@{2}: commit: feat: add user profile

# Reset back to where you were
git reset --hard def5678

# Done! Your commits are back.

4. Recovering a Dropped Stash

Stashes are commits too, and they appear in the reflog:


# Scenario: You accidentally dropped an important stash
git stash drop stash@{0}

# Find the stash commit in the reflog
git reflog | grep stash
# Or search for the stash message
git reflog | grep "WIP on feature"

# The stash commit SHA appears in the reflog
# abc1234 HEAD@{15}: stash: WIP on feature/auth

# Recreate the stash from the commit
git stash apply abc1234

# Or create a branch from it
git branch recovered-stash abc1234

5. Recovering from a Failed Rebase

When a rebase goes wrong, reflog is your escape hatch:


# Scenario: Rebase created conflicts and messed up history
git rebase main
# Conflicts everywhere... you abort but things are still broken

# Check the reflog for the state before rebase
git reflog

# Find the pre-rebase state
# def5678 HEAD@{1}: rebase: picking abc1234
# ghi9012 HEAD@{2}: checkout: moving from feature to feature

# Reset to before the rebase started
git reset --hard ghi9012

# Start fresh with a better rebase strategy
git rebase -i main

6. Recovering Orphaned Commits

Commits that no branch points to can still be found:


# Find all unreachable commits
git fsck --lost-found --no-reflogs

# This creates .git/lost-found/commit/ with orphaned commits
ls .git/lost-found/commit/

# Examine each one
git show <commit-sha>

# Create a branch from the one you want
git branch recovered-feature <commit-sha>

7. Using Reflog with Dates

Time-based recovery when you don’t remember the commit:


# What did HEAD look like yesterday?
git reflog --date=iso | grep "yesterday"

# What was main pointing to 2 hours ago?
git reflog show main --date=relative | grep "2 hours ago"

# Checkout the state from a specific time
git checkout main@{2.hours.ago}

# Create a branch from that state
git branch recovery-point main@{2.hours.ago}

Production Failure Scenarios

ScenarioWhat HappensMitigation
Reflog expired — Entry is older than 90 daysThe commit may be garbage collectedRun recovery within 90 days; use git fsck for older commits
Garbage collection rangit gc pruned unreachable commitsReflog entries exist but commits are goneDisable aggressive gc; set gc.reflogExpireUnreachable to longer period
Remote force push — You force pushed and lost remote commitsLocal reflog can’t help if you never had the commitsRequire force push protection; use --force-with-lease instead of --force
Deleted .git directory — The entire repository is goneReflog lives in .git/logs/ — it’s gone tooRegular backups; never delete .git without archiving first
Reflog corruption — Reflog file is damagedEntries may be unrecoverableReflog is append-only; corruption is rare but possible
Wrong commit recovery — You recover the wrong commitYou’re back to a different wrong stateVerify the commit content with git show before resetting

Trade-off Analysis

AspectAdvantageDisadvantage
Safety netCatches almost all local mistakesLocal only; doesn’t help with remote issues
Time-basedCan recover by date/timeEntries expire (default 90/30 days)
ComprehensiveTracks all HEAD movementsCan be overwhelming with hundreds of entries
No setup requiredEnabled by defaultConsumes disk space for log files
Branch-specificEach branch has its own reflogOnly tracks branches you’ve checked out
Recovery flexibilityCan reset, checkout, or branch from any entryRequires understanding of reflog references

Implementation Snippets

Reflog Configuration


# ~/.gitconfig
[gc]
    # Don't aggressively garbage collect
    auto = 6000
    autopacklimit = 50

[core]
    # Keep reflog entries longer
    logAllRefUpdates = true

# Per-repository settings
git config gc.reflogExpire 180.days.ago
git config gc.reflogExpireUnreachable 90.days.ago

Recovery Script


#!/bin/bash
# scripts/recovery-assistant.sh
# Interactive reflog recovery assistant

echo "=== Git Reflog Recovery Assistant ==="
echo ""

# Show recent reflog
echo "Recent operations:"
git reflog --date=iso --format='%C(auto)%h %gd %C(reset)%gs %C(blue)%cr' | head -20

echo ""
echo "Options:"
echo "1) Reset HEAD to a specific reflog entry"
echo "2) Create a branch from a reflog entry"
echo "3) Show details of a specific entry"
echo "4) Search reflog by message"
echo "5) Find lost stashes"
read -r choice

case $choice in
  1)
    echo "Enter reflog reference (e.g., HEAD@{3} or commit SHA):"
    read -r ref
    echo "This will reset HEAD to: $ref"
    echo "Proceed? (y/n)"
    read -r confirm
    if [ "$confirm" = "y" ]; then
      git reset --hard "$ref"
      echo "Reset complete."
    fi
    ;;
  2)
    echo "Enter reflog reference:"
    read -r ref
    echo "Branch name:"
    read -r branch
    git branch "$branch" "$ref"
    echo "Branch '$branch' created from $ref"
    ;;
  3)
    echo "Enter reflog reference:"
    read -r ref
    git show "$ref"
    ;;
  4)
    echo "Search term:"
    read -r term
    git reflog --grep="$term"
    ;;
  5)
    echo "Lost stashes:"
    git reflog | grep "stash"
    ;;
  *)
    echo "Invalid option"
    ;;
esac

Pre-Destructive Hook


#!/bin/bash
# scripts/safe-reset.sh
# Wrapper for git reset that creates a safety branch first

TARGET=${1:?Usage: safe-reset.sh <target>}

# Create a safety branch pointing to current HEAD
SAFETY_BRANCH="safety/$(date +%Y%m%d-%H%M%S)"
git branch "$SAFETY_BRANCH" HEAD

echo "Safety branch created: $SAFETY_BRANCH"
echo "Current HEAD: $(git rev-parse HEAD)"
echo ""

# Perform the reset
echo "Resetting to: $TARGET"
git reset --hard "$TARGET"

echo ""
echo "Reset complete."
echo "If something went wrong, recover with:"
echo "  git reset --hard $SAFETY_BRANCH"

Reflog Diff Viewer


#!/bin/bash
# scripts/reflog-diff.sh
# Compare two reflog entries

ENTRY1=${1:?Usage: reflog-diff.sh <entry1> <entry2>}
ENTRY2=${2:?Second entry required}

echo "=== Comparing $ENTRY1 vs $ENTRY2 ==="
echo ""

git diff "${ENTRY1}...${ENTRY2}" --stat
echo ""
echo "Full diff:"
git diff "${ENTRY1}...${ENTRY2}"

Observability Checklist

  • Logs: Not typically applicable — reflog is local
  • Metrics: Track reflog size and entry count per repository
  • Alerts: Alert when reflog entries approach expiration or when disk usage from logs exceeds threshold
  • Dashboards: Display reflog health: entry count, oldest entry age, and disk space used
  • Recovery tracking: Log recovery operations for post-incident analysis

Security and Compliance Notes

  • Local only: Reflog never leaves your machine — it’s stored in .git/logs/
  • Sensitive data: Reflog may contain commit messages with sensitive information — audit reflog entries
  • No remote sync: Reflog is not pushed to remotes; each developer has their own reflog
  • Audit trail: Reflog provides a local audit trail of all operations, useful for forensic analysis
  • Compliance: For regulated environments, reflog can help reconstruct developer actions during an incident

Security & Compliance Considerations

  1. Assuming Reflog is Forever — Reflog entries expire. Default is 90 days for reachable commits, 30 days for unreachable ones. Don’t rely on it as a backup.
  2. Ignoring Unreachable Commits — After git gc --prune, unreachable commits are gone forever. Run recovery before garbage collection.
  3. Confusing Reflog with Loggit log shows commit history; git reflog shows local operations. They serve different purposes.
  4. Not Verifying Before Reset — Resetting to the wrong reflog entry compounds the problem. Always git show the target first.
  5. Force Push Without Lease — Using --force instead of --force-with-lease can overwrite others’ work without warning.
  6. Deleting .git/logs — Manually cleaning .git/logs/ destroys your safety net. Let Git manage reflog expiration.
  7. No Backup Strategy — Reflog is not a backup. Use remote branches, tags, or external backups for critical work.

Quick Recap Checklist

  • Reflog tracks all HEAD movements locally
  • Use git reflog to view recent operations
  • Use git reflog show <branch> for branch-specific history
  • Recover lost commits with git reset --hard <reflog-entry>
  • Recover dropped stashes by finding them in reflog
  • Use git fsck --lost-found for orphaned commits
  • Reflog entries expire (default 90/30 days)
  • Reflog is local-only; it doesn’t sync to remotes
  • Create safety branches before destructive operations
  • Never use reflog as a substitute for proper backups

Recovery Decision Tree

When you’ve lost work, follow this path:

flowchart TD
    A[Lost work detected] --> B{Reflog available?}
    B -->|Yes| C[Find target commit in reflog]
    C --> D[Reset or branch from entry]
    B -->|No| E{Refs still accessible?}
    E -->|Yes| F[Use git fsck --lost-found]
    E -->|No| G{Remote has commits?}
    G -->|Yes| H[Fetch from remote]
    G -->|No| I[Check backups]
    I --> J{Lost work recovered?}
    J -->|No| K[Accept loss, recreate]
    J -->|Yes| L[Document incident]
    D --> L
    F --> L
    H --> L
  1. Reflog available?git reflog — Find the commit SHA and reset/branch from it
  2. Reflog expired?git fsck --lost-found — Check .git/lost-found/commit/ for orphaned objects
  3. Remote has it?git fetch origin — Check if the remote still has the old branch state
  4. Backup exists? → Check your backup system, IDE local history, or time machine
  5. All else failed? → The work is gone. Accept the loss and recreate it.

Reflog Internals and Storage

Understanding how reflog works under the hood helps you reason about its behavior:

Reflog Storage Architecture

Where Reflog Data Lives

Reflog entries are stored as plain text files in the .git/logs/ directory:

  • HEAD reflog: .git/logs/HEAD
  • Branch reflogs: .git/logs/refs/heads/<branch>

Each line follows the format:

<old_sha> <new_sha> <author> <timestamp> <operation_message>

Example entry:

0000000 abc1234 Geek Workbench <email> 1742000000 +0000 commit: feat: add payment processing

Reflog Entry Format

FieldDescription
old_shaCommit before the operation
new_shaCommit after the operation
authorUser who performed the operation
timestampUnix timestamp of the operation
messageHuman-readable operation description

Reflog Size Management

Reflog files grow over time. Monitor and manage them:

# Check reflog file sizes
ls -lh .git/logs/

# See entry count per reflog
wc -l .git/logs/HEAD
git reflog | wc -l

# Compact reflog (remove expired entries)
git reflog expire --expire=30.days.ago --all

Reflog Lifecycle

Reflog and Garbage Collection

Git’s garbage collector (git gc) removes unreachable objects, including reflog entries past their expiration:

# Reflog entries expire based on reachability
git config gc.reflogExpire 90.days.ago        # Reachable commits
git config gc.reflogExpireUnreachable 30.days.ago  # Orphaned commits

# Check gc configuration
git config --get gc.reflogExpire
git config --get gc.reflogExpireUnreachable

# Run gc manually (usually automatic)
git gc --prune=now

Reflog Across Clones

When you clone a repository, reflog is not transferred. Each developer has their own local reflog tracking their own operations. This design choice means:

  • You cannot recover another developer’s dropped commits
  • Remote force pushes cannot be undone via local reflog
  • Each repository maintains independent reflog history

Extended Reflog Configuration

Expiration Configuration for Critical Repos

For repositories where recovery is critical, extend reflog retention:

# Extend to 180 days for reachable, 90 for unreachable
git config gc.reflogExpire 180.days.ago
git config gc.reflogExpireUnreachable 90.days.ago

# Or disable expiration for certain branches
git config gc.reflogExpireNever refs/heads/main

Reflog and Git Operations

Every Git operation that moves HEAD writes to reflog. The reflog acts as a chronological journal:

# Timeline of operations
git reflog --format="%h %gd %gs %cr"

# Find operation by time
git reflog --date=iso | grep "2026-03-31"

# Trace a specific commit through reflog
git reflog --all --format="%H %gd %gs" | grep <sha>

Understanding reflog internals helps you diagnose recovery failures and configure appropriate expiration policies for your workflow.

Recovery Checklist

  • Act quickly — Reflog entries expire; garbage collection makes recovery impossible
  • Don’t run git gc — Garbage collection permanently removes unreachable objects
  • Check reflog firstgit reflog is the fastest recovery path
  • Verify before resettinggit show <sha> to confirm it’s the right commit
  • Create safety branchgit branch recovery-attempt HEAD before any destructive operation
  • Check fsck — If reflog fails, git fsck --lost-found may find orphaned commits
  • Check remotegit fetch origin and check remote branches for the lost state
  • Extend reflog — For critical repos, set gc.reflogExpire to 180 days or more

Interview Questions

1. What is the difference between git log and git reflog?

git log shows the commit history of the current branch — the ancestry chain of commits reachable from HEAD. It's a view of the project's evolution.

git reflog shows the history of local operations — every time HEAD moved, regardless of whether the commit is still reachable. It includes resets, checkouts, rebases, and stashes that don't appear in git log.

Think of it this way: git log is the project's history; git reflog is your personal history with the repository.

2. How long does git reflog keep entries?

By default, reflog keeps entries for 90 days for commits reachable from any branch or tag, and 30 days for unreachable commits (orphaned commits not referenced by any branch).

These values are configurable via gc.reflogExpire and gc.reflogExpireUnreachable. You can extend them for critical repositories or shorten them to save disk space.

After expiration, entries are removed during garbage collection. Once garbage collected, the commits are truly gone unless you have a backup.

3. Can git reflog recover a force-pushed branch?

Only if you had the commits locally. Reflog is a local feature — it tracks operations on your machine. If you force pushed and lost commits that existed on the remote but you never had locally, reflog can't help.

If you did have the commits locally, check your reflog for the pre-force-push state and reset or create a branch from that entry. Then force push the recovered state.

To prevent this scenario, use --force-with-lease instead of --force. It checks that the remote hasn't changed since your last fetch, preventing accidental overwrites.

4. How do you find a commit that was lost during an interactive rebase?

Interactive rebase rewrites history, but the original commits remain in the reflog:

  1. Run git reflog to find the state before the rebase started
  2. Look for the entry just before the rebase: HEAD@{n}: rebase: picking ...
  3. The entry before that is your pre-rebase state
  4. Create a branch from it: git branch recovered HEAD@{n+1}
  5. Compare the recovered branch with your current state to identify dropped commits

Alternatively, use git fsck --lost-found to find all unreachable commits and examine each one.

5. Where does git store reflog data, and what is the file format?

Reflog data lives in .git/logs/ as plain text files:

  • .git/logs/HEAD — Global HEAD movements
  • .git/logs/refs/heads/<branch> — Per-branch reflogs

Each line follows the format: <old_sha> <new_sha> <author> <timestamp> <operation_message>

Because reflog is just text, you can read it with any editor, parse it with scripts, and even back it up manually.

6. What is the difference between git reset --hard, --mixed, and --soft?

The three reset modes differ in what they preserve:

  • --soft: Moves HEAD but keeps staging area and working directory unchanged. All changes remain staged and ready to commit.
  • --mixed (default): Moves HEAD and resets staging area but keeps working directory. Unstages changes but doesn't discard them.
  • --hard: Moves HEAD, resets staging, and discards all working directory changes. This is the dangerous one — data loss is permanent unless recovered via reflog.

All three modes are recorded in reflog, allowing recovery from any of them.

7. Why is git reflog considered local-only, and what implications does this have?

Reflog is stored in .git/logs/ which is not transferred during clone, fetch, or push. Each developer maintains their own independent reflog.

Implications:

  • You cannot recover another developer's dropped commits
  • Remote force-push losses cannot be undone via local reflog
  • Team members can't see your reflog history
  • Reflog must be present before data loss occurs — it's not a backup system

This is why teams use protected branches, force-push restrictions, and external backups for critical work.

8. How do you recover a dropped stash that no longer appears in git stash list?

Even after git stash drop <stash-ref>, the commit object remains until garbage collection:

  1. Find the stash commit in reflog: git reflog | grep stash
  2. Look for entries like HEAD@{n}: stash: WIP on feature/...
  3. Extract the commit SHA from the reflog entry
  4. Recover via git stash apply <sha> or create a branch: git branch recovered <sha>

If reflog expired, try git fsck --lost-found and examine commits in .git/lost-found/commit/.

9. What is git fsck --lost-found and when should you use it?

git fsck --lost-found finds commits that are reachable by no ref or branch — orphaned objects that would be garbage collected.

Usage:

  • After reflog fails (expired entries)
  • When you need to find commits that existed before a reset or rebase
  • Before running git gc --prune=now to rescue important work

Found commits are written to .git/lost-found/commit/ with short SHA filenames. Examine each with git show <sha> to identify the one you need.

10. How does --force-with-lease differ from --force when pushing?

--force overwrites the remote branch unconditionally, destroying any commits that teammates pushed since your last fetch.

--force-with-lease adds a safety check: it verifies that the remote ref still matches your local tracking ref. If another developer pushed since your last fetch, the push fails with a warning.

Think of it as a lease — you're saying "I know my fetch is current, let me push." If someone else pushed, the lease is broken and the push is rejected.

Best practice: alias git push to always use --force-with-lease to prevent accidental overwrites.

11. Can reflog help recover from a deleted branch? How?

Yes, branches are just pointers — deleting a branch doesn't destroy the commits:

  1. Check the branch reflog: git reflog show <deleted-branch>
  2. Find the last commit the branch pointed to
  3. Recreate the branch: git branch <deleted-branch> <commit-sha>

If the branch was never checked out, it won't have its own reflog. In that case, use git reflog (HEAD reflog) to find operations that referenced the branch, or search through git fsck --lost-found.

12. What is the relationship between reflog and garbage collection?

Reflog entries have expiration dates. Git's garbage collector removes:

  • Reflog entries older than gc.reflogExpire (default 90 days)
  • Reflog entries for unreachable commits older than gc.reflogExpireUnreachable (default 30 days)

When GC removes a reflog entry, the referenced commits become eligible for pruning. After GC runs, recovery may be impossible.

To protect important work, either recover before GC runs or configure longer expiration for critical repositories.

13. How do you use time-based reflog references like HEAD@{yesterday}?

Git supports symbolic reflog references with time units:

  • HEAD@{yesterday} — HEAD position yesterday
  • HEAD@{2.days.ago} — Two days ago
  • main@{last.week} — main branch from last week
  • HEAD@{3.months.ago} — Three months ago

Useful when you don't remember the commit SHA but know approximately when things were correct. Use with git checkout, git reset, or git branch.

List available time references: git reflog --date=iso

14. What are some common anti-patterns when using git reflog?

Several practices lead to problems:

  • Assuming reflog is permanent — Entries expire after 90/30 days; it's not a backup
  • Not verifying before resetting — Resetting to wrong entry compounds the problem
  • Relying on reflog for shared work — It's local-only; can't help with remote issues
  • Ignoring gc warnings — Garbage collection permanently removes unreachable objects
  • Manually editing .git/logs/ — Can corrupt reflog and make recovery impossible
  • Using reflog instead of proper workflow — Safer to create safety branches before destructive ops
15. How can you protect critical branches from accidental force-push losses?

Multiple layers of protection:

  1. Configure on remote: Disable force-push on main/develop or require PR reviews
  2. Use --force-with-lease: Configure as default in git config
  3. Create backup branches: Before risky operations, create safety branches
  4. Set longer reflog expiration: For critical repos, extend to 180+ days
  5. External backups: Regular pushes to mirrored repos for critical branches

On GitHub/GitLab: use branch protection rules to block force-push to protected branches.

16. What happens to reflog when you clone a repository?

Clone creates a fresh repository with no reflog history from the original. You get:

  • The current branch heads (at the clone point)
  • All commits reachable from those branches
  • No operational history — your reflog starts empty

This is by design: reflog tracks local operations. The clone operation itself becomes the first reflog entry.

If you need shared history, consider using shallow clones with --depth carefully — they can make certain recovery scenarios harder.

17. How do you audit reflog entries for security or compliance purposes?

Reflog provides a forensic record of repository operations:

  1. Export reflog: git reflog --format='%H %gd %gs %cr' --all
  2. Search for sensitive operations: Look for reset, rebase, branch deletion
  3. Correlate with commit content: git show <sha> to see what changed
  4. Track user activity: Parse the author field for team member operations

In regulated environments, reflog can help reconstruct developer actions during incident investigation. Store reflog exports periodically for long-term audit trails.

18. What is the safest way to perform a git reset on a shared branch?

For shared branches, follow this safety checklist:

  1. Communicate: Alert team members that you'll be rewriting history
  2. Create backup: git branch backup/<branch> HEAD
  3. Verify target: git show <target-commit> to confirm correct state
  4. Use --force-with-lease: When pushing recovered state, use --force-with-lease
  5. Confirm after push: Team members should fetch and reset their local tracking branches

Consider using git revert instead of reset for shared branches — it creates new commits that don't rewrite history.

19. Can reflog entries be manually created or modified?

Reflog entries are created automatically by Git operations — you cannot manually add entries for past operations.

You can:

  • Expire entries early: git reflog expire --expire=now HEAD
  • Delete reflog: Remove .git/logs/HEAD (dangerous!)

You cannot safely edit reflog entries — the format is append-only and modifications can corrupt the log. If you need to remove sensitive entries, remove the entire reflog file after the fact.

20. How do you set up automated monitoring for reflog health?

Monitor reflog to catch problems before data loss occurs:

# Check entry count and oldest entry
git reflog | wc -l
git reflog --date=iso | tail -5

Alert if oldest entry > 60 days (threshold configurable)

OLDEST=$(git reflog —format=‘%at’ | tail -1) NOW=$(date +%s) DAYS=$(( (NOW - OLDEST) / 86400 )) if [ $DAYS -gt 60 ]; then echo “Reflog oldest entry is $DAYS days old”; fi

Monitor disk usage of reflog files

du -sh .git/logs/

Set up alerts in your CI/CD or monitoring system to notify when reflog entries approach expiration or disk usage exceeds thresholds.

Further Reading

Conclusion

The reflog is Git’s insurance policy — it records every movement of HEAD, even after destructive operations. When a reset goes wrong or a rebase explodes, the reflog is your first and best recovery tool.

Category

Related Posts

Git Bisect for Bug Hunting: Binary Search Through Commit History

Master git bisect to find the exact commit that introduced a bug using binary search. Automate bug hunting with scripts and handle complex scenarios.

#git #version-control #debugging

Git Blame and Annotate: Line-by-Line Code Attribution

Master git blame for line-by-line code attribution, understanding code history, finding when code changed, and using blame effectively for code comprehension.

#git #version-control #git-blame

git log: Master Commit History Navigation and Filtering

Master git log formatting, filtering, searching history, and navigating commit history effectively for version control debugging and auditing.

#git #git-log #history