This warning appears when Git's reflog has fewer entries than expected, typically due to reflog expiration, a freshly cloned repository, or using time-based references beyond the available history.
When you use a time-based reference in Git like `@{2 days ago}` or `@{1.week.ago}`, Git looks up the commit that a reference (like HEAD or a branch name) pointed to at that time. This lookup uses the **reflog**, which is a local log of when references were updated. The warning "Log for 'HEAD' only has N entries" means the reflog doesn't have enough historical entries to satisfy your time-based query. Git will use the oldest available entry instead, which may not be what you intended. This is important to understand: **reflogs are local and temporary**. They are not part of the repository's shared history and are not transferred during clone, fetch, or push operations. By default, reflog entries older than 90 days are pruned during garbage collection, and unreachable entries (from rebases or amends) expire after just 30 days.
View your reflog to see available entries and their dates:
git reflog show HEADOr with dates:
git reflog show --date=relative HEADThis shows what history is actually available in your reflog.
Instead of time-based references that depend on reflog, use actual commit history:
# Find commits before a date using git log
git log --before="2024-01-15" --oneline -1
# Use git rev-list for scripting
git rev-list -1 --before="2 days ago" HEAD
# Then use the commit hash directly
git diff abc1234..HEADThis queries the actual commit timestamps, which are part of permanent history.
For comparing against historical states, use remote branches:
# Fetch latest remote state
git fetch origin
# Find commit from date on remote
git rev-list -1 --before="Apr 1 2024" origin/main
# Checkout historical state
git checkout $(git rev-list -1 --before="2 weeks ago" origin/main)This works because it queries commit timestamps, not reflog.
To prevent future reflog expiration, configure longer retention:
# Set for current repository
git config gc.reflogExpire "180 days"
git config gc.reflogExpireUnreachable "90 days"
# Or set globally
git config --global gc.reflogExpire "180 days"
git config --global gc.reflogExpireUnreachable "90 days"To keep reflogs indefinitely (not recommended for most cases):
git config gc.reflogExpire never
git config gc.reflogExpireUnreachable neverCheck your current reflog expiration settings:
git config --get gc.reflogExpire
git config --get gc.reflogExpireUnreachableIf these return nothing, default values are in use (90 days and 30 days respectively).
### Understanding Reflog vs Log
The reflog is fundamentally different from git log:
- git log: Shows the commit history (public, shared, permanent)
- git reflog: Shows when references changed locally (private, local-only, temporary)
When you clone a repository, your reflog is empty except for the clone operation. The commit history via git log goes back to the beginning of the project, but HEAD@{1 year ago} only works if you've had the repo for a year.
### Default Expiration Settings
| Setting | Default | Purpose |
|---------|---------|---------|
| gc.reflogExpire | 90 days | Reachable entries (current branch history) |
| gc.reflogExpireUnreachable | 30 days | Unreachable entries (rebased/amended commits) |
### Pattern-Based Configuration
You can set different expiration for specific refs:
# Never expire remote tracking branches
git config "gc.refs/remotes/*.reflogExpire" never
# Short expiration for stash
git config "gc.refs/stash.reflogExpireUnreachable" "7 days"### Security Considerations
Setting reflog expiration to "never" has implications:
- Repository size grows over time
- Deleted sensitive data remains recoverable locally
- Old commits from rebases are preserved indefinitely
For sensitive repositories, the default expiration helps ensure truly deleted content eventually gets garbage collected.
### CI/CD Environments
In CI/CD pipelines, fresh clones have minimal reflog history. For time-based comparisons, always use:
git rev-list -1 --before="date" origin/branchThis avoids reflog entirely and works reliably in fresh checkouts.
warning: refname 'feature' is ambiguous
How to fix 'warning: refname is ambiguous' in Git
error: The following untracked working tree files would be overwritten by checkout
Untracked working tree files would be overwritten by checkout
error: remote origin already exists
How to fix 'fatal: remote origin already exists' in Git
pathspec did not match any file(s) known to git
How to fix 'pathspec did not match any file(s) known to git' in Git
ssh: Could not resolve hostname github.com: Name or service not known
How to fix 'ssh: Could not resolve hostname github.com: Name or service not known' in Git