git notes attaches extra information to a commit without rewriting it.
Notes let CI annotate commits (build IDs, review links) out of band, since they are stored separately under refs/notes.
What it does
git notes stores annotations in a separate refs/notes namespace and binds them to commits, so you can add metadata without altering the commit object or its SHA.
Common usage
Terminal
git notes add -m "build: 1234" <sha>
git notes show <sha>
git notes append -m "deployed" <sha>
git push origin refs/notes/commits # notes are not pushed by default
git fetch origin refs/notes/*:refs/notes/*
Options
Subcommand / flag
What it does
add -m <msg>
Attach a note to a commit
show
Display a commit’s note
append
Add to an existing note
remove
Delete a note
--ref <name>
Use a non-default notes ref
Common errors in CI
error: Cannot add notes. Found existing notes for object … Use '-f' to overwrite - a note already exists; pass -f or use append. Notes are not transferred by default, so remote tooling sees nothing until you push refs/notes/* explicitly.
Using this in CI
CI checkouts are shallow and detached by default, which changes the answer this command gives you. Commands that read history, branch names, or tags need the checkout configured for it.
.github/workflows/ci.yml
- uses:actions/checkout@v4with:fetch-depth:0 # history, tags, and git describe all need this- run:|git rev-parse --is-shallow-repository # expect falsegit rev-parse --abbrev-ref HEAD # prints HEAD when detached
Frequently asked questions
git notes: Usage, Options & Common CI Errors?
Notes let CI annotate commits (build IDs, review links) out of band, since they are stored separately under refs/notes.
What it does?
git notes stores annotations in a separate refs/notes namespace and binds them to commits, so you can add metadata without altering the commit object or its SHA.
Common errors in CI?
error: Cannot add notes. Found existing notes for object … Use '-f' to overwrite - a note already exists; pass -f or use append. Notes are not transferred by default, so remote tooling sees nothing until you push refs/notes/* explicitly.