git cherry-pick
git cherry-pick lets you take a single commit — or a small range of commits — from anywhere in your Git history and replay it on top of your current branch. Instead of merging an entire branch, you surgically apply just the changes you need. The result is a brand-new commit with the same diff but a different SHA.
How cherry-pick works internally
Under the hood, cherry-pick computes the diff introduced by the target commit (what changed relative to its parent) and applies that diff to your working tree, then creates a new commit. It is essentially git diff <parent> <commit> | git apply, wrapped in a commit step.
Visual model
Before cherry-pick
──────────────────
main: A ── B ── C ── D (HEAD)
↑ you are here
feature: A ── B ── E ── F ── G
You want commit F (a hotfix) on main:
After: git cherry-pick F
──────────────────────────
main: A ── B ── C ── D ── F' (HEAD)
↑ new commit, same diff as F
feature: A ── B ── E ── F ── G (unchanged)
Note: F' has a different SHA than F.Basic syntax
# Apply a single commit by its hash git cherry-pick <commit-hash> # Example git cherry-pick a1b2c3d # Apply from a different branch by name (tip of that branch) git cherry-pick feature/login
Typical terminal output
[main 9f3e2a1] Fix null-pointer in user session handler Date: Tue May 19 14:32:00 2026 +0000 1 file changed, 4 insertions(+), 1 deletion(-)
Cherry-pick a range of commits
Use the two-dot A..B syntax to pick everything after A up to and including B. The notation is exclusive of A — A itself is NOT included.
# Pick commits E, F, G (NOT D) — exclusive of the left endpoint git cherry-pick D..G # To include D as well, use D~ (parent of D) git cherry-pick D~..G # Equivalent using the ^ syntax git cherry-pick D^..G
Range diagram
Commits on feature: ... D ── E ── F ── G
↑
NOT included in D..G
git cherry-pick D..G picks: E, F, G
git cherry-pick D~..G picks: D, E, F, GCherry-pick multiple individual commits
# Pick three non-consecutive commits in one command git cherry-pick a1b2c3d e4f5a6b 7c8d9e0 # They are applied in left-to-right order # Each becomes its own commit on the current branch
Useful flags
Flag | Meaning |
|---|---|
| Appends "(cherry picked from commit …)" to the commit message — great for traceability. |
| Applies the changes to the working tree and index but does NOT create a commit. Lets you combine multiple picks or edit before committing. |
| Opens your editor so you can change the commit message before it is saved. |
| Adds a Signed-off-by trailer to the commit message. |
| Pass a merge strategy option (e.g., |
| Allow picking a commit that results in an empty diff on the target branch. |
| Required when cherry-picking a merge commit; specify which parent (1 or 2) to treat as the mainline. |
The -x flag for traceability
git cherry-pick -x a1b2c3d
Resulting commit message
Fix null-pointer in user session handler (cherry picked from commit a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0)
The --no-commit flag
--no-commit (or -n) applies the diff to the staging area without creating a commit. This is useful when you want to cherry-pick several commits and squash them into one, or when you need to make additional edits before committing.
# Stage three commits' worth of changes without committing git cherry-pick -n a1b2c3d git cherry-pick -n e4f5a6b git cherry-pick -n 7c8d9e0 # Now inspect, adjust, then commit everything as one git diff --cached git commit -m "Backport: user session fixes (3 commits)" # Or abort and throw away the staged changes git checkout -- . git reset HEAD
Handling conflicts during cherry-pick
If the diff cannot apply cleanly, Git pauses and leaves conflict markers in the affected files — the same format you see during a merge.
Conflict output
error: could not apply a1b2c3d... Fix null-pointer in user session handler hint: After resolving the conflicts, mark them with hint: "git add/rm <pathspec>", then run hint: "git cherry-pick --continue". hint: If you want to skip this commit, run "git cherry-pick --skip". hint: If you want to abort this operation, run "git cherry-pick --abort".
# 1. Edit the conflicting files to resolve the markers # <<<<<<< HEAD … your current code # ======= … the incoming cherry-pick changes # >>>>>>> a1b2c3d vim src/session.js # 2. Stage the resolved file(s) git add src/session.js # 3. Continue the cherry-pick (creates the commit) git cherry-pick --continue # --- OR --- # Skip this commit entirely and move to the next one in a range git cherry-pick --skip # --- OR --- # Abort the entire cherry-pick and go back to where you started git cherry-pick --abort
When to use cherry-pick
Hotfixes: A critical bug is fixed on
main; you need the same fix on therelease/2.xsupport branch without merging all ofmain.Backporting: A new feature lands on
main; a paying customer on an older version needs just that one feature.
Salvaging commits: You accidentally committed to the wrong branch; cherry-pick the commits to the right one, then reset the wrong branch.
Selective inclusion: A feature branch has ten commits; only two are ready for production.
Emergency patches: A security fix needs to go to multiple release branches simultaneously.
Practical hotfix workflow
Backporting a hotfix to a release branch
# 1. Fix the bug on main (or wherever it was found) git checkout main # ... make the fix ... git add src/auth.js git commit -m "fix: prevent session token from leaking in logs" # Resulting commit: d4e5f6a # 2. Find the release branch that needs the fix git checkout release/2.8 # 3. Cherry-pick with -x so the message shows the origin git cherry-pick -x d4e5f6a # 4. Push the release branch git push origin release/2.8
Common errors
Error | Cause | Fix |
|---|---|---|
| You tried to cherry-pick a merge commit without specifying which parent to follow. | Use |
| The hash does not exist in your local repo. | Run |
Conflict markers appear in files | The diff did not apply cleanly. | Resolve conflicts manually, |
| You have uncommitted changes in the working tree. | Stash ( |
Cherry-pick vs merge vs rebase
Approach | What it does | History impact | Best for |
|---|---|---|---|
| Copies specific commits as new commits | Diverged — same diff, different SHA | Isolated hotfixes, backports |
| Integrates an entire branch, preserving all its commits | Adds a merge commit, keeps full branch history | Integrating completed features |
| Re-applies a sequence of commits on a new base | Rewrites SHAs, produces a linear history | Keeping a feature branch up to date with main |