Skip to main content
RunBook Academy

Git, CI/CD & GitOpsXIII · Cherry-PickBackporting

Backporting hotfixes — moving a fix without merging everything

Advanced⏱ ~22 mingit

What you'll learn

  • Explain what a release or maintenance branch is and why a fix on `main` does not automatically reach older releases
  • Backport a single fix from `main` to a maintenance branch with `git cherry-pick -x`
  • Verify that the backport builds, tests, and ships as if the change had been written on the maintenance branch
  • Recognise the difference between a backport (one commit) and a merge (whole history) and choose deliberately
  • Record the backport in release notes so the change is auditable in both branches

Prerequisites

Verified against Git 2.55.x teaching target; 2.40+ minimum · GitHub Actions continuous service; Aug 2026 documentation baseline · Argo CD v3.5.x teaching target; v3.0+ minimum · Flux v2.9.x · Sigstore Cosign v3.1.x · SLSA v1.2 · OCI Distribution Specification v1.1 · Git LFS v3.7.1 · Kubernetes (cross-course target) 1.36.x

Not yet marked complete on this device.

A backport is the production use case that justifies cherry-pick existing at all. A team ships a release branch (say release-2.x), cuts a tagged release (v2.4.7), and continues developing on main. Months later, a critical fix lands on main. The fix must also ship on release-2.x because customers on the older release need it, but the team does not want every other commit between v2.4.7 and the fix to flow into the maintenance branch. The answer is: cherry-pick the single commit, with -x, into the maintenance branch, verify, tag, ship.

The release/maintenance topology

The branch topology of a typical production project is not a single line. It is a fan-out from a release cut and a fan-in back when the maintenance branch is eventually retired:

gitGraph
    commit id: "v247"
    branch release_2x
    checkout release_2x
    commit id: "release_2x_tip"
    checkout main
    commit id: "featA"
    commit id: "fixF" tag: "needs_backport"
    commit id: "featB"
    checkout release_2x
    commit id: "backport_fixF" tag: "v248"

main keeps moving; release-2.x stays near v2.4.7 plus a handful of backports. A merge of main into release-2.x would drag feat A, feat B, and everything else with it. The cherry-pick of fix F moves only the fix.

How to backport safely

The backport is a four-step operation. None of the steps is optional in production:

COMMIT=fixF
TARGET=release-2.x
git checkout $TARGET
git pull --ff-only
git cherry-pick -x $COMMIT
# resolve any conflicts, verify, push
git push origin $TARGET

Step by step:

  1. Check out the target branch and fast-forward fetch. You are about to add a commit; make sure your local copy of the branch is current. --ff-only fails noisily if the local copy has diverged, which is the right behaviour for a shared branch.
  2. Cherry-pick with -x. The -x records the source hash so the backport is traceable from either branch. Without it, the duplicated history has no audit trail.
  3. Resolve conflicts, verify, push. A backport is a merge with a one-commit history. Conflicts are resolved the same way; a CI run is the only authoritative verification that the backport makes sense on the older branch.
  4. Tag and release. Once CI is green, the maintenance branch gets a new tag (e.g. v2.4.8) and the release pipeline ships.

What to backport and what to leave

Not every commit on main belongs on a maintenance branch. The rule of thumb:

  • Backport: security fixes, correctness fixes that affect shipped behaviour, dependency upgrades that close CVEs, bug fixes documented in the release notes as “fixed in v2.4.8”.
  • Do not backport: new features, refactors that change behaviour, dependency upgrades for non-security reasons, anything that changes the public API of the software.

The discipline matters because every backport is a long-term maintenance liability. The fix must continue to apply on the maintenance branch for as long as the branch is supported, which is often years. A backport of a refactor pulls in a refactor that must also be kept working; a backport of a feature pulls in a feature that must also be supported.

Release notes and auditability

The -x line on the cherry-picked commit is necessary but not sufficient. The full audit trail needs a release-notes entry that maps the source commit hash to the backport commit hash:

git log --grep="cherry picked from commit $COMMIT" --format='%H'

Pair this with a CHANGELOG entry, a security advisory reference, or a ticket link, and the move is fully traceable from either direction. Without the release-notes entry, an auditor on the maintenance branch sees a fix that has no obvious origin; without the -x line, an auditor on main sees a fix that has no obvious destination.

UnderTheHood: what the merge base tells you

The merge base of a backport cherry-pick is the parent of the source commit on main. If the maintenance branch has moved far from that parent — for example, because the maintenance branch has its own in-flight refactors — the textual conflict rate will be high. A team that wants to keep backports cheap keeps its maintenance branches small, narrowly scoped, and close to the release they cut from. A team that lets its maintenance branches drift will see every backport turn into a long conflict-resolution session.

Production discipline

The production discipline for backports has four rules:

  1. Backport only what is documented. If the backport is not in the release notes with a clear rationale, it does not ship.
  2. Always use -x. The recorded hash is the audit trail.
  3. Tag every backport batch. Each release of the maintenance branch is a tag; the diff between consecutive tags is the list of backports in that release.
  4. Retire maintenance branches on a schedule. A maintenance branch that is never retired accumulates backports until it is indistinguishable from a second main. The end-of-life date must be set when the branch is cut, not when the team remembers to ask.

Cross-course references

  • Git, CI/CD & GitOps — Part XII (Trade-offs) — the merge-window vs cherry-pick-backport choice is the same shape as the merge-vs-rebase choice at the team level.
  • Semantic Versioning 2.0.0 — the public contract that says which fixes are allowed to ship on a patch release (1.x.y) versus which require a minor bump (1.x.0).
  • Linux for Production Sysadmins — Part XXVII (Stable Kernels) — the stable-kernel workflow is the canonical large-scale example of cherry-pick backporting in production.

Quiz

Knowledge check · 4 questions

  1. Q1. A team has `main` and `release-2.x`. A critical security fix lands on `main`. Why is cherry-pick the right tool to get the fix onto `release-2.x`?

  2. Q2. When backporting a security fix with `git cherry-pick -x`, the `-x` flag is what produces a release-notes entry on the maintenance branch.

  3. Q3. Name the flag that records the source commit hash when cherry-picking a backport, and the kind of change that should *not* be backported.

  4. Q4. Plan the backport of a critical IAM fix from `main` to `release-2.x`, including verification and audit-trail steps.

    A CVE in IAM policy generation is fixed on `main` as commit `i4m0a11`. The team supports `release-2.x` for another 18 months. The fix is small (one file, four lines) but touches a region of `iam.tf` that has been refactored on `main` since `release-2.x` was cut. The maintenance branch has its own pending refactor of the same file.

Passing score: 75%. Answers are checked in this browser.