阿里云主机折上折
  • 微信号
Current Site:Index > Reference log recovery (git reflog)

Reference log recovery (git reflog)

Author:Chuan Chen 阅读数:33586人阅读 分类: 开发工具

Reference Log Recovery (git reflog)

Git's reference log (reflog) records the change history of all references (such as branches and HEAD) in the local repository. It acts like a "black box" for Git operations, allowing you to recover lost commits even if branches are accidentally deleted or incorrect resets are performed.

How reflog Works

Every time a HEAD or branch reference changes, Git records the following in the reference log:

  1. The SHA-1 value before the change
  2. The SHA-1 value after the change
  3. The type of operation (commit, checkout, reset, etc.)
  4. The operation timestamp
  5. The operator information

These records are stored in the .git/logs/ directory:

  • HEAD changes are recorded in .git/logs/HEAD
  • Branch changes are recorded in .git/logs/refs/heads/<branch-name>

Basic Usage

View the complete reference log:

git reflog
# Example output:
# 7a3b2c1 HEAD@{0}: commit: Update README
# 91d4f5a HEAD@{1}: checkout: moving from main to feature/login

View the reference log for a specific branch:

git reflog show feature/login

View with a time format:

git reflog --date=iso

Recovering from Mistakes

Scenario 1: Recovering a Deleted Branch

# 1. View records before deletion
git reflog
# Output includes:
# 91d4f5a HEAD@{3}: checkout: moving from deleted-branch to main

# 2. Recreate the branch based on the old reference
git branch recovered-branch 91d4f5a

Scenario 2: Undoing an Incorrect Reset

# Accidentally performed a hard reset
git reset --hard HEAD~3

# View the state before the reset
git reflog
# Example output:
# a1b2c3d HEAD@{1}: reset: moving to HEAD~3
# e4f5g6h HEAD@{2}: commit: Add user authentication

# Restore to the commit before the reset
git reset --hard e4f5g6h

Advanced Applications

Finding the Repository State at a Specific Time

# Find the HEAD state at 3 PM yesterday
git reflog --date=local | grep "May 10 15:"

Combining with git log

# View detailed information for a commit in the reference log
git show HEAD@{2}

Cleaning Up Expired Records

By default, reflog records are retained for 90 days. You can manually clean them up:

# Clean records older than 30 days
git reflog expire --expire=30.days.ago

Practical Example

Assume we encounter the following situation while developing a frontend project:

  1. Create a new feature branch:
git checkout -b feature/modal
  1. Make several commits:
// modal.js
export function showModal() {
  console.log('Modal opened');
}
git add modal.js
git commit -m "Add modal base function"
  1. Accidentally merge into the main branch:
git checkout main
git merge feature/modal
  1. Undo the merge:
git reflog
# Example output:
# 123abcd HEAD@{0}: merge feature/modal: Fast-forward
# 456efgh HEAD@{1}: checkout: moving from feature/modal to main

git reset --hard 456efgh

Differences Between Reference Log and Regular Log

Feature git reflog git log
Scope All reference changes in local repo Commit history
Storage .git/logs/ directory Object database
Retention Default 90 days Permanent
Order Reverse chronological by operation time Reverse chronological by commit time
Includes All reference changes Only commit operations

Reference Log Entry Breakdown

A typical reflog entry:

a1b2c3d HEAD@{5}: commit: Update package.json
  • a1b2c3d: New SHA-1 value after the operation
  • HEAD@{5}: Reference and relative position
  • commit: Operation type
  • Update package.json: Operation description

Reference Expression Syntax

Git supports various reference expressions:

  • HEAD@{n}: The nth previous state of HEAD
  • branch@{n}: The nth previous state of a branch
  • HEAD@{2.days.ago}: The state of HEAD two days ago
  • main@{yesterday}: The state of the main branch yesterday

Example:

# View code differences from this time yesterday
git diff HEAD@{1.day.ago}

Limitations of Reference Logs

  1. Local only: Reflog is not pushed to remote repositories
  2. Time-bound: Automatically cleaned up after 90 days by default
  3. Does not record workspace changes: Uncommitted modifications cannot be recovered via reflog
  4. Does not record stash operations: git stash operations have their own stash log

Integration with Other Commands

Using reflog to Check Merge Conflicts

git reflog show -p HEAD

Finding Lost Commits

# Search for commits containing specific information
git reflog | grep "fix login bug"

Restoring Historical Versions of Specific Files

# View file change history
git reflog -- path/to/file.js

# Restore a file to a specific version
git checkout HEAD@{5} -- path/to/file.js

Underlying Implementation of Reference Logs

Git automatically logs updates when references are changed via the git-update-ref command. The underlying data structure is a plain text file with the format:

<old-sha> <new-sha> <committer> <timestamp> <timezone> <operation> <message>

Example log entry:

0000000000000000000000000000000000000000 a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6 John Doe <john@example.com> 1625097600 +0800 commit (initial): Initial commit

Best Practices for Reference Logs

  1. Regular checks: Review reflog after important operations to confirm records
  2. Prompt recovery: Use reflog to recover from mistakes as soon as possible
  3. Backup important states: For critical points, creating tags is more reliable than relying on reflog
  4. Team collaboration note: Do not depend on others' reflogs, as they are local records

Alternatives to Reference Logs

When reflog is unavailable, consider:

  1. git fsck --lost-found: Find dangling objects
  2. Remote repository backup: Reclone from the remote repository
  3. File recovery tools: For uncommitted changes

Configuration Options for Reference Logs

You can adjust reflog behavior via Git configuration:

# Modify the default expiration time (days)
git config gc.reflogExpire 180

# Set to never delete reference logs
git config gc.reflogExpire never

Graphical View of Reference Logs

Many Git GUI tools support visualizing reflog:

# View with gitk
gitk --reflog

# View with tig
tig reflog

Scripting with Reference Logs

You can automate reflog processing with scripts:

// Example: Node.js script to parse git reflog output
const { execSync } = require('child_process');

function parseReflog() {
  const output = execSync('git reflog --date=iso').toString();
  return output.split('\n')
    .filter(line => line.trim())
    .map(line => {
      const [hash, ref, action, ...message] = line.split(/\s+/);
      return {
        hash,
        ref,
        action: action.replace(':', ''),
        message: message.join(' ')
      };
    });
}

console.log(parseReflog());

本站部分内容来自互联网,一切版权均归源网站或源作者所有。

如果侵犯了你的权益请来信告知我们删除。邮箱:cc@cccx.cn

Front End Chuan

Front End Chuan, Chen Chuan's Code Teahouse 🍵, specializing in exorcising all kinds of stubborn bugs 💻. Daily serving baldness-warning-level development insights 🛠️, with a bonus of one-liners that'll make you laugh for ten years 🐟. Occasionally drops pixel-perfect romance brewed in a coffee cup ☕.