Git Notes Storage
whogitit stores attribution data using git’s built-in notes feature. This page explains how notes work and how whogitit uses them.
What Are Git Notes?
Git notes are metadata attached to commits without modifying the commits themselves. They’re stored in a separate ref namespace and can be pushed/fetched independently.
Key characteristics:
- Non-invasive: Don’t modify commit SHAs
- Portable: Can be shared via push/fetch
- Flexible: Any data can be attached
- Native: Built into git, no external dependencies
whogitit’s Notes Ref
Attribution is stored under refs/notes/whogitit:
# View notes ref
git show-ref | grep whogitit
# abc123def456... refs/notes/whogitit
# List all notes
git notes --ref=whogitit list
# abc123... def456... (note hash, commit hash)
# ghi789... jkl012...
Viewing Notes
Raw Note Content
# View note for HEAD
git notes --ref=whogitit show HEAD
# View note for specific commit
git notes --ref=whogitit show abc123
# Pretty-print JSON
git notes --ref=whogitit show HEAD | jq .
Using whogitit
# Formatted view
whogitit show HEAD
# JSON output
whogitit show --format json HEAD
How Notes Are Created
Automatic (Post-Commit Hook)
The post-commit hook creates notes automatically:
# In .git/hooks/post-commit
whogitit post-commit
This:
- Reads the pending buffer
- Analyzes changes
- Creates the note
Manual (Advanced)
# Add a note manually
git notes --ref=whogitit add -m '{"schema_version":2,...}' abc123
# Edit existing note
git notes --ref=whogitit edit abc123
# Remove a note
git notes --ref=whogitit remove abc123
# Copy a note
git notes --ref=whogitit copy abc123 def456
Pushing Notes
Notes must be pushed separately from branches:
Automatic (Pre-Push Hook)
After whogitit init, notes are pushed automatically:
git push # Triggers pre-push hook
# Hook runs: git push origin refs/notes/whogitit
Manual
git push origin refs/notes/whogitit
Force Push (Caution)
If notes diverge:
git push origin refs/notes/whogitit --force
Fetching Notes
Automatic Configuration
whogitit init configures automatic fetching:
# Check configuration
git config --get-all remote.origin.fetch | grep notes
# +refs/notes/whogitit:refs/notes/whogitit
With this config, git fetch includes notes.
Manual
# Fetch notes explicitly
git fetch origin refs/notes/whogitit:refs/notes/whogitit
# Fetch all notes
git fetch origin 'refs/notes/*:refs/notes/*'
Notes and Rebasing
When rebasing, commits get new SHAs. The post-rewrite hook (installed by whogitit init) automatically preserves notes.
Automatic Preservation (Recommended)
Run whogitit init to install the post-rewrite hook:
whogitit init
After this, notes are automatically preserved during:
git rebasegit commit --amend
You’ll see a message like:
whogitit: Preserved attribution for 3 commit(s)
Manual Copy (Cherry-pick or Recovery)
For cherry-pick (not covered by post-rewrite hook) or manual recovery:
# Using whogitit command
whogitit copy-notes <old-sha> <new-sha>
# Or using git directly
git notes --ref=whogitit copy <old-sha> <new-sha>
Batch Recovery
If you rebased without the hook installed:
# Before rebase, save commits
git log --format='%H' main..HEAD > /tmp/old-commits
# After rebase
git log --format='%H' main..HEAD > /tmp/new-commits
# Copy notes
paste /tmp/old-commits /tmp/new-commits | while read old new; do
whogitit copy-notes "$old" "$new"
done
Notes and Merge/Squash
Merge Commits
Merge commits don’t automatically get notes. The individual commits retain their notes.
Squash Merging
Squash creates a new commit, losing individual notes. Options:
- Use regular merge to preserve notes
- Manually create a summary note for the squash
- Accept that the PR comment serves as record
Storage Details
Notes Tree Structure
refs/notes/whogitit/
├── ab/
│ ├── c123... → note for commit abc123...
│ └── d456... → note for commit abd456...
├── cd/
│ └── e789... → note for commit cde789...
...
Notes are stored as blobs in the git object database.
Note Size
Each note is a JSON blob. Typical sizes:
- Small commit (1 file, 20 lines): ~500 bytes
- Medium commit (5 files, 100 lines): ~2-5 KB
- Large commit (20 files, 500 lines): ~10-20 KB
Storage Efficiency
Git compresses notes like any other objects. Similar notes compress well together.
Garbage Collection
Notes are git objects and subject to garbage collection:
# Notes blobs without refs will be collected
git gc
# Prune unreferenced notes
git gc --prune=now
Notes attached to existing commits are protected.
Backup and Recovery
Backup Notes
# Clone just the notes
git clone --bare <repo> --single-branch --branch refs/notes/whogitit notes-backup
# Or export
whogitit export --full-prompts -o backup.json
Restore Notes
# Push notes from backup
cd notes-backup
git push <repo> refs/notes/whogitit:refs/notes/whogitit
Troubleshooting
Notes Not Showing
# Check if notes exist locally
git notes --ref=whogitit list
# If empty, fetch
git fetch origin refs/notes/whogitit:refs/notes/whogitit
# Check remote
git ls-remote origin refs/notes/whogitit
Notes Diverged
# See what's different
git log refs/notes/whogitit..origin/refs/notes/whogitit
# Pull remote (may need merge)
git fetch origin refs/notes/whogitit
git update-ref refs/notes/whogitit FETCH_HEAD
Corrupted Note
# Remove and recreate
git notes --ref=whogitit remove <commit>
# Pending buffer is gone, so attribution is lost for that commit
See Also
- Architecture - System design
- Data Formats - JSON schemas
- Troubleshooting - Common issues