Recording backports with cherry-pick -x Jump to heading

A cherry-picked commit is a new commit with a new hash. Without a record, nothing connects it to the original: a search for the fix’s hash on the release branch finds nothing, a reviewer cannot tell whether the backport was adapted, and a security team asking β€œwhich releases contain the fix for this advisory?” gets a manual investigation. The -x option solves the first part by appending a line naming the source commit. Trailers and a couple of conventions cover the rest. This page sets those conventions up and shows the queries they make possible, as part of cherry-pick and backporting.

When to use this approach Jump to heading

  • Fixes are cherry-picked from main onto release branches or between long-lived branches.
  • You need to answer which releases contain a given fix, for customers or security advisories.
  • Backports are sometimes adapted, and reviewers need to know when the code differs from the original.
  • You automate backports, as in automating backport pull requests with labels, and want the bot’s commits to be traceable.

Step 1 β€” Always cherry-pick with -x Jump to heading

The -x option appends a line to the commit message:

git cherry-pick -x 4e7a91c
git log -1 --format=%B
# Fix double discount on credit notes
#
# (cherry picked from commit 4e7a91c2d9b8f0a1e3c5d7f9b1a3c5e7d9f1b3a5)

Git has no configuration option to make -x the default, so make it a habit through an alias that everyone uses for backports.

git config --global alias.backport 'cherry-pick -x'
git backport 4e7a91c

Do not use -x when cherry-picking from a private branch whose commits will never be published β€” the reference would point at a commit nobody else can see. For backports from main, the source is always public.

A backport with and without a recordWithout -x the backport is an unrelated commit with a new hash, and finding it from the original fix requires guessing by message. With -x the backport names its source, so either commit can be found from the other with a single search.cherry-pickcherry-pick -xlink to originalnonefull hash in messagefind from the fixsearch by subjectgrep the hashadvisory querymanualone commandprivate source branchfineavoidone flag turns every later question about the backport into a grep

Step 2 β€” Add trailers for what -x does not say Jump to heading

The -x line says where the change came from, but not whether it was changed on the way. Add trailers that capture the facts reviewers and auditors ask about.

git cherry-pick -x --edit 4e7a91c
# In the editor, add trailers below the -x line:
#
# (cherry picked from commit 4e7a91c…)
# Backport-Of: #812
# Backport-Adapted: yes β€” release branch inlines discount logic
# Fixes: SEC-2026-014

Trailers are key-value lines at the end of the message that Git can parse. git interpret-trailers adds them non-interactively, which is useful in automation.

git commit --amend --no-edit --trailer "Backport-Of: #812" --trailer "Fixes: SEC-2026-014"
git log -1 --format='%(trailers:key=Backport-Of,key=Fixes)'

Step 3 β€” Query which branches contain a fix Jump to heading

With -x lines in place, finding every copy of a fix is a log search across branches.

fix=4e7a91c2d9b8f0a1e3c5d7f9b1a3c5e7d9f1b3a5
for b in $(git for-each-ref --format='%(refname:short)' refs/remotes/origin/release/); do
  hit=$(git log --format=%h --grep="cherry picked from commit $fix" "$b" | head -1)
  printf '%-22s %s\n' "$b" "${hit:-missing}"
done
Where one security fix landedAn example query for a single fix: present on main through the original commit, present on the two newest release branches through recorded backports, and missing on the oldest supported branch, which tells the release manager exactly what remains.fix 4e7a91c present by branch (example)mainoriginalrelease/2.4backport a8c21f0release/2.3backport 77d0b19release/2.2missingthe missing bar is the action item for the advisory

For tags, git tag --contains works on the original commit only. To include backports, search each release tag’s history for the -x line instead.

for t in $(git tag --list 'v2.*'); do
  git log --format=%h --grep="cherry picked from commit $fix" "$t" | head -1 | sed "s|^|$t |"
done

Step 4 β€” Avoid double-applying a fix Jump to heading

When a release branch is later merged forward into main, or a backport is picked again by mistake, the recorded source helps detect duplication before it causes a conflict or a duplicated migration.

# Before backporting, check the target branch does not already have this fix
git log --format=%h --grep="cherry picked from commit $fix" origin/release/2.4 | grep -q . \
  && echo "already backported" || git backport "$fix"

git cherry, described in finding unported commits with git cherry, complements this: it compares patch content rather than messages, so it catches backports made without -x as long as they were not adapted.

Step 5 β€” Enforce the convention in CI Jump to heading

A convention that is not checked fades. On release branches, require every non-merge commit to carry either a cherry picked from commit line or an explicit Release-Only: trailer explaining why it exists only on that branch.

# CI on pull requests targeting release/*
git log --format='%H%x09%B%x00' "origin/$BASE_REF..HEAD" --no-merges |
awk -v RS='\0' -F'\t' '$2 !~ /cherry picked from commit/ && $2 !~ /Release-Only:/ {print substr($1,1,10)}' |
  grep . && { echo "commits above lack a backport record or Release-Only trailer"; exit 1; } || true
Keeping backport records completeBackports are made with an alias that always adds -x. Reviewers add trailers for adaptation and issue links. CI on release branches rejects commits with neither a source record nor a release-only explanation. Advisory queries then rely on the records being complete.git backportalias for -xTrailersAdapted, FixesCI checksource or Release-OnlyQuerieswhich releases have itthe queries are only as good as the least disciplined backport

Validation checklist Jump to heading

Frequently Asked Questions Jump to heading

Does -x affect how the change is applied? Jump to heading

No. It only changes the commit message. The resulting tree is identical to a cherry-pick without it.

What if I forgot -x on a backport that is already pushed? Jump to heading

Do not rewrite a shared release branch to add it. Record the link elsewhere: a note with git notes add -m "cherry picked from commit <sha>" <backport> or the pull request description. Notes travel only if you push refs/notes/*, so make that part of your release process if you rely on them.

Git cannot change the original commit, but notes or the pull request can. Many teams rely on the forge: the backport pull request links the original, and the forge shows the cross-reference on both.