Home / Alt manpages / git-notes(1)

  • git-notes(1)
  • User command
  • linux

Annotate Git commits safely with git notes

You will attach review or test information to an existing Git object without rewriting that object. This guide uses the git notes command from Git 2.43.0, installed here through the git-man package version 1:2.43.0-1ubuntu7.3. Allow about ten minutes. You need a Git repository and permission to write its metadata. None of these examples needs elevated privileges.

A note is separate from the commit message. The default notes ref is refs/notes/commits, and Git creates it when the first note is stored. Notes are repository data, so decide how they will be shared before relying on them in a team workflow.

1. Choose the commit and add a note

Move into the repository and resolve the object you want to annotate. The example chooses the current commit, but an explicit object ID is safer when a script must never act on the wrong commit:

$ cd /path/to/repository
$ commit=$(git rev-parse HEAD)
$ git notes add -m 'Reviewed against the staging configuration' "$commit"

-m supplies the message without opening an editor. You can give -m more than once; Git joins the messages as separate paragraphs. Lines beginning with # and excess blank lines are stripped in this non-editor form. Use -F file when the note is in a file, or -F - to read it from standard input.

Checkpoint: show the note and its object mapping:

$ git notes show "$commit"
Reviewed against the staging configuration
$ git notes list "$commit"
<note-object-id> <commit-object-id>

The object ID printed by git notes list identifies the note blob first and the annotated object second. Adding a note does not alter the commit ID.

2. Check how Git displays the annotation

Commands in the git log family can display the default commit notes. A compact check is:

$ git show -s --format='%h %s%nNotes:%n%N' "$commit"
<short-id> <commit subject>
Notes:
Reviewed against the staging configuration

The exact commit subject and ID will differ. If a command is not showing the note, check the active ref with git notes get-ref and inspect that ref explicitly with git notes --ref=refs/notes/commits show "$commit". The --ref option accepts a full ref name, or a shorter name such as review, which Git expands below refs/notes/.

3. Append a second observation

Use append when the existing text should remain and a new paragraph should be added:

$ git notes append -m 'Retested after the dependency update' "$commit"
$ git notes show "$commit"
Reviewed against the staging configuration

Retested after the dependency update

This is different from add. A second add refuses to replace an existing note, which protects against accidentally losing review history. If you really intend to replace it, use -f explicitly:

$ git notes add -f -m 'Replacement text' "$commit"
Overwriting existing notes for object <commit-object-id>

Do not use -f in a general script unless replacement is the intended policy. Before a deliberate replacement, save the current text to a file you control:

$ git notes show "$commit" > /tmp/commit-note.txt
$ git notes add -f -F /tmp/commit-note.txt "$commit"

The first command is a recovery copy. Treat the temporary file as sensitive if the note contains private review information.

4. Keep separate note collections with a custom ref

The default ref is convenient for ordinary commit notes, but a separate ref can keep build results or release checks distinct:

$ git notes --ref=review add -m 'Approved for the test environment' "$commit"
$ git notes --ref=review show "$commit"
Approved for the test environment
$ git notes --ref=review get-ref
refs/notes/review

This command does not move or copy the default note. It creates or updates refs/notes/review. Use the same --ref on later show, list, append or remove commands. A script can use git notes get-ref rather than guessing which ref is active.

For a permanent default, core.notesRef can name an unabbreviated ref. The GIT_NOTES_REF environment variable overrides that setting, while --ref overrides both. Check these layers before diagnosing a note that appears to have disappeared:

$ git config --get core.notesRef
$ printf '%s\n' "${GIT_NOTES_REF-}"

5. Remove a note only after checking the target

Removal changes the notes ref, not the commit. It is still destructive to the annotation, so confirm the object and make a recovery copy first:

$ git notes show "$commit" > /tmp/commit-note-before-remove.txt
$ git notes remove "$commit"
Removing note for object <commit-object-id>

Restore the saved text with an explicit overwrite if you removed it by mistake:

$ git notes add -f -F /tmp/commit-note-before-remove.txt "$commit"
$ git notes show "$commit"

When removing a list of objects, use --stdin only with carefully reviewed input. Use --ignore-missing when an absent note is an expected condition rather than an error. For cleanup of notes attached to unreachable objects, git notes prune --dry-run reports what would be removed; omit the dry-run flag only after reviewing that output.

6. Understand sharing, rewrites and merges

Notes are refs with their own commits. Inspect their history with git log -p notes/commits or the relevant custom ref. A normal commit push does not automatically make notes available to another clone. Share the notes ref deliberately, and make sure consumers fetch the ref they need.

Amending or rebasing creates new commit objects. Notes do not follow those rewritten objects unless note rewriting is configured. To enable copying for the default notes ref, configure notes.rewriteRef as refs/notes/commits, then review the resulting notes on the new commit. The rewrite mode defaults to concatenating an existing target note; available modes include overwrite, concatenate, cat_sort_uniq and ignore.

When two notes refs need combining, git notes merge <notes-ref> can stop on conflicts. The default manual strategy uses .git/NOTES_MERGE_WORKTREE; resolve the files there, then run git notes merge --commit. If the merge should not continue, run git notes merge --abort. Automated strategies such as ours, theirs, union and cat_sort_uniq make a policy choice, so use them only when that choice is understood.

Done means

  • The note is attached to the intended object and git notes show prints the expected text.
  • The annotated commit ID is unchanged.
  • append is used for additions and -f only for deliberate replacement.
  • Custom refs are named explicitly and shared deliberately.
  • Before removal or pruning, the target and recovery path have been checked.
  • Any rewrite or notes merge has been inspected before it is treated as authoritative.