Devpuff
Pricing
Log InStart Free
  1. Home
  2. Blog
  3. git cherry-pick: move one commit anywhere
Tools

git cherry-pick: move one commit anywhere

Cherry-pick copies a commit onto your current branch. It creates a new commit with a new hash, so the original stays where it was.

By Max Arthur
Co-Founder & Content Marketer·September 5, 2026·8 Min read
One commit from a feature branch being copied onto main as a new commit with a different hash

git cherry-pick takes the changes from one commit and applies them to your current branch:

git switch main
git cherry-pick 2dbdf91

The word to hold onto is copies. It does not move the commit, and it does not link the two. Measured on git 2.50.0:

source hash on feature: 2dbdf91
new hash on main:       6810a9e
same? NO
original still on feature: 2dbdf91 the one commit I want

Two commits now exist with the same changes and different hashes. That is not a bug, and understanding it is most of knowing when to use this command.

Why the hash changes

A commit hash is computed from its contents and its context: the parent commit, the author, the timestamp, the message. Applying the same changes on top of a different parent produces a different hash, necessarily.

So the copy is a genuinely separate commit that happens to make the same edits. Git keeps no record connecting them, which has a practical consequence: if the branch you picked from is later merged, git sees two commits making the same change, and depending on the content that can merge cleanly or conflict.

That is the core trade-off. Cherry-picking is quick and duplicates history.

Finding the commit

git log --oneline feature
git log --oneline --all --graph

You need the hash, and the short form is enough. git log --oneline --all --graph is the one worth learning, because it shows every branch at once and makes it obvious which commit you actually want.

To see what a commit changes before you take it:

git show 2dbdf91

Worth doing. A commit's message often describes less than it contains.

The main uses

Backporting a fix. A bug is fixed on main and needs to go onto a release branch that is not taking the rest of main. This is the textbook case and the one cherry-pick is genuinely best at.

A commit landed on the wrong branch. You committed to main instead of your feature branch. Cherry-pick it across, then remove it from main with reset or revert.

Rescuing one commit from an abandoned branch. The branch is not worth merging; one commit on it is.

Multiple commits and ranges

git cherry-pick a1b2c3 d4e5f6          # two specific commits
git cherry-pick a1b2c3..d4e5f6         # a range, EXCLUDING a1b2c3
git cherry-pick a1b2c3^..d4e5f6        # a range, INCLUDING a1b2c3

The range forms follow git's usual convention: A..B means "everything reachable from B but not from A", which excludes A itself. The ^ in the third form means "A's parent", which is how you include A.

That off-by-one is the most common cherry-pick mistake, and it fails quietly by giving you one fewer commit than you wanted.

Conflicts

Cherry-picking applies changes onto a different starting point, so conflicts are ordinary rather than exceptional. Measured, picking a commit that touches a file the target branch also changed:

AA conflict.txt
<<<<<<< HEAD
version B
=======
version A
>>>>>>> 8b30e16 (A version)

HEAD is your current branch. The incoming side is the commit being picked, and git names it with its hash and message, which is more helpful than the equivalent during a merge.

Three ways out:

# fix the file, then
git add conflict.txt
git cherry-pick --continue

git cherry-pick --skip      # skip this one, continue a range
git cherry-pick --abort     # undo everything, back to before

--abort is fully safe. Measured, the file returned to version B exactly as it was.

-x, and why it is worth using

git cherry-pick -x 26dbfe6

The resulting commit message gets a line appended:

traceable change

(cherry picked from commit 26dbfe67f5d606031ef5f5922d8f68f9e0986f2c)

Since git records no link between the original and the copy, that line is the only trace of where the change came from. Six months later, when someone asks why the same fix appears twice, it is the difference between an answer and a guess.

Use it whenever you pick onto a shared or long-lived branch. The convention is to skip it for picks onto your own unpublished work, where the extra line is noise.

Useful flags

git cherry-pick -n <hash>     # apply the changes, do NOT commit
git cherry-pick -e <hash>     # edit the message before committing

-n (--no-commit) is the flexible one. It puts the changes in your working directory and staging area and stops, so you can amend them, combine several picks into one commit, or take only part of what the commit did.

A worked example: backporting a hotfix

The case cherry-pick handles better than anything else. A bug is fixed on main, and version 2 is in production on a release branch that is not taking the rest of main.

git switch main
git log --oneline -5
#   9f8e7d6 fix null check in session handler   <- this one
#   ...

git switch release/2.x
git cherry-pick -x 9f8e7d6
# resolve any conflict, then
git push

The fix lands on the release branch as its own commit, and main is untouched. The -x records where it came from, which matters here more than anywhere: six months later, the release branch's history is the only place anyone will look to find out whether a given fix was backported.

If the fix does not apply cleanly, that is information rather than an obstacle. It usually means the code has moved since version 2, and the fix may need adapting rather than copying. Resolving the conflict by hand is the correct outcome, not a workaround.

Checking what has already been picked

Because git records no link between a commit and its copy, telling whether a fix is already on a branch is genuinely awkward. Two commands help.

git cherry -v main release/2.x

This compares two branches by the changes the commits make rather than by their hashes. Commits marked - are already present on the other branch in some form; commits marked + are not. It is the closest git gets to "has this been backported".

git log --oneline --grep="cherry picked from"

If your team uses -x consistently, this finds every picked commit and the hash it came from. That consistency is the entire argument for the flag.

Neither is perfect. A picked commit that was then amended, or one that arrived via a squash merge, will not match. When it matters, the reliable answer is a test that proves the bug is fixed on the branch, rather than an inspection of history.

When not to cherry-pick

As a substitute for merging. Picking commit after commit from a branch, rather than merging it, produces duplicate history and conflicts that get worse each time. If you want most of a branch, merge it.

Onto a branch that will later merge back. You are guaranteeing that the same change arrives twice. Sometimes unavoidable in a release-branch workflow, and worth doing deliberately rather than by habit.

When the commit depends on earlier commits. A commit that uses a function introduced two commits before will apply cleanly and then fail to build, because cherry-pick copies one commit's changes and knows nothing about what it assumed. This is the failure that looks like a broken build rather than a git problem, and it is why picking from the middle of a series is risky.

Cherry-pick versus the alternatives

Goal Command
One commit from another branch git cherry-pick
All of another branch git merge
Move your commits onto a new base git rebase
Undo a commit's changes git revert

revert is worth noting here because it is cherry-pick's mirror image: it also creates a new commit from an existing one, applying the change backwards instead of forwards.

Picking from a commit you cannot name

Sometimes the commit you want is not on any branch: it was on a branch someone deleted, or it was made in a detached HEAD. Cherry-pick works on any commit git still has, so the only problem is finding the hash.

git reflog                       # if it happened on this machine
git fsck --unreachable | grep commit   # orphaned commits
git log --all --oneline --graph        # everything reachable

Once you have a hash, the pick is ordinary:

git cherry-pick 9f8e7d6

This is worth knowing because it changes what "lost" means. A commit that exists in the object database is recoverable whether or not anything points at it, and cherry-pick is often the cleanest way to bring just the part you want back into a live branch.

Three common mistakes

Getting the range boundary wrong. A..B excludes A. You get one fewer commit than you asked for, no error, and a branch that is quietly missing a change. Use A^..B when you mean to include A, and check the count afterwards.

Picking a commit that depends on an earlier one. It applies cleanly and then fails to build, because the function it calls was added two commits earlier. Cherry-pick copies one commit and knows nothing about what that commit assumed.

Using it instead of merging. Picking commits one at a time from a branch you intend to merge later guarantees the same changes arrive twice. If you want most of a branch, merge it.

Quick reference

git cherry-pick <hash>          # copy one commit here
git cherry-pick -x <hash>       # and record where it came from
git cherry-pick A^..B           # a range, inclusive
git cherry-pick -n <hash>       # apply without committing
git cherry-pick --continue      # after fixing a conflict
git cherry-pick --abort         # cancel entirely
git log --oneline --all --graph # find the hash

Want to move commits between branches somewhere safe? Work through Git basics in a real repository in the browser, or read merge versus rebase for the two commands that move whole branches.

Keep reading

More from the blog

A successful 200 response arriving at the browser and being stopped before it reaches the page's JavaScript
September 3, 2026·7 min readTools

CORS error: what the browser is actually blocking

A CORS error is the browser refusing a response the server already returned with a 200. Here is that proved with two real origins, and the fixes.

Read more
A directory tree with git searching upward for a .git folder and finding none before reaching the top
September 2, 2026·7 min readTools

fatal: not a git repository, and how to get out of it

fatal: not a git repository means git found no .git folder here or in any parent. Four causes, and the popular fix that quietly makes things worse.

Read more
{ }
✦

Ready to write some code?

Put this into practice - start your first free lesson. No setup, no credit card.

Start learning free
Devpuff

Learn to code by doing. One tiny, playful lesson at a time.

Learn
ProgramsCoursesPricing
Company
AboutBlogResourcesAffiliates
Support
Help CenterContactStatus
Programs
Frontend DevelopmentFull-Stack DevelopmentPython Developer
Courses
Advanced ReactAsync JavaScriptAsync PythonCSS BasicsCSS LayoutDSA Basics
Learn to Code
Learn JavaScriptLearn PythonLearn SQLLearn HTMLLearn CSSLearn ReactBrowse All Topics
Platform Comparisons
Devpuff vs CodecademyDevpuff vs MimoDevpuff vs Sololearn
© 2026 Devpuff. All rights reserved.Privacy PolicyTerms and ConditionsCookies PolicyRefund Policy
Devpuff vs freeCodeCamp
Read All Comparisons