Hello, I'm Shrijith Venkatramana. I’m building LiveReview, a private AI code review tool that runs on your LLM key (OpenAI, Gemini, etc.) with highly competitive pricing -- built for small teams. Do check it out and give it a try!
Git notes let you attach metadata to commits or other Git objects without altering their history. Think of them as sticky notes for your repository—perfect for adding context like bug references or CI statuses while keeping the commit history untouched.
Key points:
- Notes live in a separate namespace (
refs/notes/
). - They don’t affect commit hashes.
- You can share them selectively via fetch/push.
This post dives into what Git notes are, their history, how they work, and practical examples to make them useful in your projects. All details align with the official Git notes documentation.
What Are Git Notes?
Git notes are annotations you can add to any Git object (usually commits) without modifying the object itself. Stored under refs/notes/commits
by default, they’re ideal for supplemental info like test results or review comments.
Core commands:
-
git notes add
: Attach a note. -
git notes show
: View a note. -
git notes remove
: Delete a note.
To try it out:
# Initialize a repo
git init notes-test
cd notes-test
echo "Hello" > file.txt
git add file.txt
git commit -m "First commit"
# Add a note
git notes add -m "Tested on CI"
git notes show
# Output: Tested on CI
This runs in any Git setup (version 1.6.6+).
The History Behind Git Notes
Git notes emerged to address the need for metadata without rewriting commits. Proposed in 2007 by Johan Herland, they drew inspiration from tools like StGit for patch management. The feature landed in Git 1.6.6 (2009) and gained namespaces in 1.7.0 for better organization.
Timeline:
- 2007: Concept proposed on Git mailing list.
- 2009: Added to Git core.
- 2010: Namespace support introduced.
This evolution reflects Git’s focus on flexibility without compromising history integrity.
How Notes Work Under the Hood
Notes are stored as blobs in the Git object database, referenced by a tree under refs/notes/
. Each note’s filename is the SHA-1 of the annotated object, ensuring a clear mapping.
When you add a note, Git creates a blob with your message and updates the notes ref with a new commit. Fetching uses a refspec like +refs/notes/*:refs/notes/*
.
Storage breakdown:
Component | Description | Example |
---|---|---|
Note Blob | Contains the note’s content. | SHA-1 of "My note". |
Notes Tree | Maps object SHA-1 to note blob. | Tree under refs/notes/commits . |
Notes Commit | Tracks changes to notes tree. | Updated per note change. |
Inspect it yourself:
# In the notes-test repo
commit_sha=$(git rev-parse HEAD)
git notes add -m "Internal note"
# Check notes ref
git show-ref refs/notes/commits
# Output: <sha> refs/notes/commits
# View note blob
note_sha=$(git notes list $commit_sha)
git cat-file -p $note_sha
# Output: Internal note
This code reveals the note’s storage and runs in your test repo.
Adding and Viewing Notes
Use git notes add <commit> -m "Your note"
to attach a note. Without <commit>
, it targets HEAD. Use -F <file>
for multiline notes or -c
to edit in an editor.
View with git notes show <commit>
or integrate into logs with git log --show-notes
.
Options:
-
-f
: Overwrite existing notes. -
-C <object>
: Reuse another note’s content.
Example:
# In notes-test repo
echo -e "Line 1\nLine 2" > note.txt
git notes add -F note.txt
# View in log
git log -1 --show-notes
# Output:
# commit <sha>
# Author: <you>
# Date: <date>
#
# First commit
#
# Notes:
# Line 1
# Line 2
This keeps notes visible and clean.
Editing and Deleting Notes
Modify notes with git notes edit <commit>
, which opens your editor. Append with git notes append -m "More text"
. Delete with git notes remove <commit>
.
Command options:
Command | Purpose | Notes |
---|---|---|
git notes edit |
Edit note in editor. | Requires commit. |
git notes append |
Add to existing note. | Preserves original. |
git notes remove |
Delete note. | No undo by default. |
Try it:
# Edit note
git notes edit
# (Change to "Updated note" in editor)
# Append
git notes append -m "Extra info"
# Show
git notes show
# Output: Updated note
# Extra info
# Remove
git notes remove
git notes show
# Output: fatal: No note found for object <sha>.
This sequence runs after previous examples.
Using Notes Namespaces
Namespaces organize notes, e.g., refs/notes/bugs
for bug tracking. Specify with --ref=<name>
. Fetch custom namespaces by updating .git/config
refspecs.
Common namespaces:
-
commits
: Default. -
ci
: Build statuses. -
reviews
: Code review notes.
Example:
# Add note in custom namespace
git notes --ref=bugs add -m "Bug #123 fixed"
# View it
git notes --ref=bugs show
# Output: Bug #123 fixed
# List all notes refs
git for-each-ref refs/notes
# Output: refs/notes/commits, refs/notes/bugs
This helps manage multiple note types.
Merging Notes Across Repos
Merge notes from another ref with git notes merge <notes-ref>
. Strategies include:
-
manual
: Resolve conflicts in.git/NOTES_MERGE_WORKTREE
. -
ours
/theirs
: Favor local/remote notes. -
union
: Concatenate notes.
Finalize with git notes merge --commit
or cancel with --abort
.
Example:
# Clone a repo with notes
git clone <remote-repo> repo2
cd repo2
git notes add -m "Local note"
# Merge remote notes
git notes merge origin/notes/commits
# (Resolve conflicts if any, then:)
git notes merge --commit
# View merged notes
git notes show
# Output: Combined notes (depends on merge strategy)
This ensures notes sync across teams.
Real-World Use Cases
CI pipelines: Add build status:
#!/bin/bash
# Save as ci-note.sh, chmod +x
echo "Running build..."
sleep 1
git notes --ref=ci add -f -m "Build passed: $(date)"
git notes --ref=ci show
# Output: Build passed: <date>
Tagging releases: Annotate tags:
git tag v1.0
git notes add v1.0 -m "Release v1.0: Stable build"
git notes show v1.0
# Output: Release v1.0: Stable build
Push notes with git push origin refs/notes/*
. These scripts work in any Git repo.
Best Practices and Tips
Use notes for non-critical data like CI results or temporary annotations. Avoid sensitive info, as notes are shareable. Set notes.displayRef
to show specific refs in logs. Clean up with git notes prune
for orphaned notes.
In teams, define namespace conventions. For automation, use hooks to prompt for notes post-commit.
Git notes offer a lightweight way to enrich your repository’s context. Test them in a small project to see how they fit your workflow. The official docs at git-scm.com have more details for advanced usage.
Top comments (0)