Git Internals
You are entering the core navigation systems of Git. Understanding references and reflog is essential for advanced repository management and emergency recovery operations.
Commander, every spacecraft needs a sophisticated navigation system to track its position, trajectory, and maintain logs of all movements for emergency recovery. In Git, this navigation system consists of references (refs) and the reference log (reflog) - the internal mechanisms that track every commit, branch, and state change in your repository.
While cadets use Git through simple commands, commanders understand the underlying reference system. This knowledge enables advanced operations like recovering "lost" commits, understanding Git's internal structure, and performing sophisticated repository maintenance that would be impossible without deep systems knowledge.
In the spacecraft analogy, references are like navigation beacons that point to specific coordinates (commits) in your mission history. Every branch name, tag, and HEAD pointer is a reference stored as a simple file containing a SHA-1 hash.
# View all references
git show-ref
# Branch references (refs/heads/)
git show-ref --heads
# Tag references (refs/tags/)
git show-ref --tags
# Remote references (refs/remotes/)
git show-ref | grep remotes
References are stored in .git/refs/ as plain text files. Each file contains a single SHA-1 hash pointing to a commit object. This simple system enables Git's powerful branching and history management.
Scenario: Investigate your repository's reference structure
# Look at branch reference
cat .git/refs/heads/main
# Check HEAD reference
cat .git/HEAD
# List all reference directories
ls -la .git/refs/
# Should match the file content
git rev-parse HEAD
git rev-parse main
# Show what HEAD points to
git symbolic-ref HEAD
HEAD is Git's most important reference - it's your current position in the repository timeline. Think of it as your spacecraft's current coordinates that determine what you see in your working directory.
| HEAD State | Points To | Meaning | Working Directory |
|---|---|---|---|
| Normal | refs/heads/branch-name | On a branch | Latest commit of branch |
| Detached | commit SHA-1 | Not on any branch | Specific commit content |
# Check current HEAD status
git status
git log --oneline -1
# Create detached HEAD state
git checkout [commit-hash]
# Return to branch
git checkout main
# Move HEAD without changing working directory
git reset --soft HEAD~1
# Move HEAD and update working directory
git reset --hard HEAD~1
Scenario: Practice navigating different HEAD states
git status
cat .git/HEAD
git log --oneline -5
git checkout HEAD~2
git status
cat .git/HEAD # Should be a SHA-1 now
git branch # Shows detached state
git checkout main
cat .git/HEAD # Should be ref: refs/heads/main
The reflog (reference log) is Git's flight recorder - it tracks every movement of references, especially HEAD. Unlike the commit history which can be rewritten, reflog maintains a complete log of where your references have pointed, making it invaluable for recovery operations.
Reflog is local only - it doesn't get pushed or pulled. It's your personal navigation history, typically kept for 90 days by default.
# View HEAD reflog
git reflog
# View reflog for specific branch
git reflog show branch-name
# View reflog with timestamps
git reflog --date=iso
# Find commits from specific time
git reflog --since="2 days ago"
# Show reflog entries as patches
git log -g -p
abc123f HEAD@{0}: commit: Add new feature
def456a HEAD@{1}: checkout: moving from feature-branch to main
ghi789b HEAD@{2}: commit: Fix bug in authentication
def456a HEAD@{3}: checkout: moving from main to feature-branch
jkl012c HEAD@{4}: reset: moving to HEAD~1
Scenario: Recover a "lost" commit using reflog
# Make a test commit
echo "test file" > recovery-test.txt
git add recovery-test.txt
git commit -m "Test commit for recovery"
# Note the commit hash
git log --oneline -1
# "Lose" the commit with hard reset
git reset --hard HEAD~1
git log --oneline # Commit not visible
ls # File is gone
git reflog # Find the lost commit
git show HEAD@{1} # Should show your test commit
git reset --hard HEAD@{1} # Recover it
ls # File should be back
git log --oneline # Commit visible again
Understanding Git's internal structure is like knowing your spacecraft's engineering systems. The .git directory contains all the repository data, and refs are just one part of this sophisticated system.
.git/
├── HEAD # Current branch reference
├── config # Repository configuration
├── description # Repository description
├── hooks/ # Git hook scripts
├── info/ # Additional repository info
├── objects/ # Git object database
│ ├── [0-9a-f][0-9a-f]/ # Object storage (by hash)
│ ├── info/ # Object database info
│ └── pack/ # Packed objects
└── refs/ # Reference storage
├── heads/ # Branch references
├── tags/ # Tag references
└── remotes/ # Remote references
# See all objects
find .git/objects -type f
# Examine object type and content
git cat-file -t [hash] # Show object type
git cat-file -p [hash] # Show object content
# Show object size
git cat-file -s [hash]
# List all references with their objects
git for-each-ref
Scenario: Explore the relationship between refs and objects
git rev-parse HEAD
git cat-file -t HEAD # Should be "commit"
git cat-file -p HEAD # Show commit details
# Get tree hash from commit
git cat-file -p HEAD | grep tree
git cat-file -p [tree-hash] # Show directory contents
# Create a tag pointing to HEAD
git tag test-tag HEAD
cat .git/refs/tags/test-tag
# Create a branch reference manually
echo $(git rev-parse HEAD) > .git/refs/heads/manual-branch
git branch # Should show manual-branch
Advanced Git operations often require direct reference manipulation for repository maintenance, migration, and custom workflows.
# Update reference safely
git update-ref refs/heads/branch-name [commit-hash]
# Delete a reference
git update-ref -d refs/heads/old-branch
# Create symbolic reference
git symbolic-ref HEAD refs/heads/main
# Expire reflog entries
git reflog expire --expire=30.days --all
# Prune unreachable reflog entries
git reflog expire --expire-unreachable=7.days --all
# Force reflog expiration
git gc --prune=now
git update-ref instead of direct file manipulationgit gc maintains optimal repository performanceScenario: Perform repository maintenance using reference tools
git reflog | wc -l
git reflog --date=iso | head -5
git reflog expire --expire=1.day --all
git reflog | wc -l # Should be fewer entries
git fsck --full
git gc --aggressive
Mastered Git's reference system including branches, tags, and HEAD management
Can recover lost commits and navigate repository history using reflog
Understands .git directory structure and object database relationships
Can perform advanced repository maintenance and reference operations