backend / git / 08_cherry_pick.md

Cherry-pick — Apply a Commit From Another Branch

6 interview angles 5 min read source

Cherry-pick — Apply a Commit From Another Branch

git cherry-pick <sha> takes the changes introduced by a specific commit and applies them as a new commit on the current branch. Useful for hotfixes, backports, and rescuing one commit from a wrong branch.

The basic command

git cherry-pick a1b2c3d                  # apply that one commit
git cherry-pick a1b2c3d e4f5g6h          # multiple commits, in order
git cherry-pick a1b2c3d^..h7i8j9k        # range (exclusive of the first)
git cherry-pick branch-name              # apply the tip of that branch

The original commit stays where it was. A new commit with the same diff (different SHA) lands on the current branch.

Common scenarios

Hotfix to main, also need it on the release branch

git switch main
git commit -m "fix critical bug"
# pushed and deployed

git switch release/v1.4
git cherry-pick main                     # apply the latest main commit
git push

Wrong branch — move a commit

git log -1                                # note the SHA: a1b2c3d
git reset --hard HEAD~                    # remove from current branch (assuming local-only)
git switch correct-branch
git cherry-pick a1b2c3d

Rescue commits from a branch you’re abandoning

git switch new-branch
git cherry-pick old-branch~3..old-branch  # apply last 3 commits from old-branch
git branch -D old-branch

Cherry-pick options

Flag Effect
-x append (cherry picked from commit <sha>) to the message — leaves a paper trail
-n, --no-commit apply changes but don’t commit yet (you can squash/edit before committing)
-e open editor to edit the commit message
-s add Signed-off-by trailer
--continue resume after resolving conflicts
--abort bail out, return to pre-cherry-pick state
--skip skip this commit, continue with the next (in a range)

-x is best practice for cross-branch picks (release branches, hotfixes) — easy to find the original later.

Conflicts during cherry-pick

git cherry-pick a1b2c3d
# error: could not apply a1b2c3d... Some message
# CONFLICT (content): Merge conflict in file.py

Resolve like any merge conflict:

# edit file.py to resolve
git add file.py
git cherry-pick --continue

Or bail:

git cherry-pick --abort

Range syntax pitfalls

git cherry-pick a..b means “commits after a, up to and including b.” So a itself is not included.

git cherry-pick a1b2c3d^..h7i8j9k        # use ^ to include a1b2c3d
git cherry-pick --first-parent a..b      # follow only the first parent (skip merged-in commits)

For a single commit, just use the SHA. For multiple, list them or use a range.

Cherry-picking a merge commit

A merge commit has two parents — git needs to know which side’s changes to apply.

git cherry-pick -m 1 <merge-sha>          # use first parent as the "mainline"

-m 1 means “treat parent 1 as the existing line of history; apply the diff from parent 2.” Almost always 1 (the branch you merged into).

In practice: avoid cherry-picking merges if you can. Cherry-pick the underlying feature commits instead.

Duplicate-detection

If you cherry-pick a commit that’s already on the target branch (different SHA, same content), git detects this:

The previous cherry-pick is now empty, possibly due to conflict resolution.

Use git cherry-pick --skip to move on, or --allow-empty to keep the empty commit.

When cherry-pick is the wrong tool

  • You want all of branch A on branch B. Use git merge or git rebase, not 50 cherry-picks.
  • You’re moving a feature branch to a new base. git rebase --onto is cleaner. See 03_interactive_rebase.md.
  • You want to “copy” a commit. Same diff, new SHA — but the original branches diverge. People debugging later will see two commits with the same content and wonder why. -x annotation helps.

Cherry-pick anti-pattern: parallel maintenance

Cherry-picking every fix from main to release/v1.4, release/v1.5, release/v1.6 indefinitely. The branches drift; conflicts compound; eventually you stop trying.

Better:

  • Backport explicitly with PRs, not ad-hoc cherry-picks. Each backport is a tracked PR with CI.
  • Limit number of supported releases. Two, max. Sunset old ones.
  • Or skip release branches entirely — use feature flags / canary deploys to ship from main.

Cherry-pick vs rebase –onto

Cherry-pick Rebase –onto
Best for one or a few commits a contiguous range / whole branch
Result new commits on current branch branch pointer rewritten
Discovery “this commit was picked from X” “this branch was rebased onto Y”
Reversibility undo with git revert undo with reflog reset

Common interview confusions

  • “Cherry-pick moves the commit.” — it copies. Original stays.
  • “Cherry-pick creates a duplicate commit on both branches.” — same diff, different SHA. They’re not the same commit object.
  • “You can cherry-pick a merge commit like any other.” — needs -m N to choose the parent. Usually avoid by picking the underlying commits.

Interview angle

  • “What does git cherry-pick do?” — applies the changes of a specific commit (or range) on top of the current branch as new commits.
  • “Common use case?” — hotfix on main needs to land on a release branch; rescuing one commit from a branch you don’t want to merge whole; moving an accidental commit to the right branch.
  • “What does -x do?” — appends (cherry picked from commit <sha>) to the message — paper trail for cross-branch picks.
  • “Cherry-pick a merge commit?” — needs -m N to specify which parent to treat as the “mainline.” Usually -m 1. Often better to pick the original commits instead.
  • “When is cherry-pick the wrong tool?” — when you want all of branch A in branch B (use merge or rebase), or when you’ll do it repeatedly across many releases (use proper backport workflow with PRs).
  • “How does cherry-pick compare to rebase?” — pick is for individual commits; rebase replays a series of commits onto a new base. rebase --onto is the surgical tool when picking would mean dozens of individual commands.