Master Git Cherry-Pick: Selective Commit Application
What is Git Cherry-Pick?
Git cherry-pick is a powerful command that allows you to apply specific commits from one branch to another. Unlike merging or rebasing, which apply entire branches, cherry-pick lets you select individual commits to copy.
Simple Analogy: Imagine you have a basket of fruit (commits) from different trees (branches). Cherry-picking lets you select only the ripest cherries (specific commits) and add them to your current basket, rather than taking the whole branch.
# Takes commit B from feature/login
# Applies it as new commit B' on main
When to Use Cherry-Pick
- Hotfix application: Apply a bug fix from development to production
- Feature extraction: Take specific features without merging entire branches
- Commit recovery: Restore lost commits from reflog or other branches
- Branch synchronization: Sync specific changes between parallel branches
- Code review incorporation: Apply suggested changes from review comments
Important: Cherry-pick creates new commits with different hashes. Use it judiciously—it can create duplicate commits if not managed properly.
Basic Cherry-Pick Commands
1. Single Commit Cherry-Pick
The most common use case:
git log --oneline feature/branch -5
# b2c3d4e Fix login validation bug
# a1b2c3d Add login feature
# Switch to target branch
git checkout main
# Cherry-pick the specific commit
git cherry-pick b2c3d4e
# Verify the new commit
git log --oneline -3
2. Multiple Commits
Apply several commits in sequence:
git cherry-pick a1b2c3d b2c3d4e c3d4e5f
# Or use a range
git cherry-pick a1b2c3d..c3d4e5f
# Range excludes start commit, includes end commit
# Use ^ to include start: a1b2c3d^..c3d4e5f
3. Cherry-Pick with Options
Control how cherry-pick behaves:
git cherry-pick -n a1b2c3d
# Edit commit message before applying
git cherry-pick -e a1b2c3d
# Sign the new commit
git cherry-pick -s a1b2c3d
# Continue after conflict resolution
git cherry-pick --continue
# Abort cherry-pick operation
git cherry-pick --abort
Practical Use Cases
Hotfix to Production
Situation: A bug was fixed in development branch, needs immediate production deployment.
git checkout production
# Find the fix commit
git log develop --grep="fix" --oneline -5
# Apply just the fix
git cherry-pick abc1234
Feature Backporting
Situation: A feature from new-version branch needs to work in old-version branch.
git log new-version --oneline --grep="feature" -10
# Apply to old version
git checkout old-version
git cherry-pick commit1 commit2 commit3
# May need manual adjustments for compatibility
Commit Recovery
Situation: Lost commits after a bad reset or branch deletion.
git reflog
# Identify the lost commit hashes
# abc1234 HEAD@{5}: commit: Important work
# Recover them
git cherry-pick abc1234
# Or recover multiple
git cherry-pick abc1234..def5678
Advanced Cherry-Pick Techniques
1. Interactive Cherry-Pick
When you need to pick commits interactively or modify them:
git rebase -i --onto main feature-start
# Or use sequence editing
git cherry-pick --continue
git cherry-pick --skip
git cherry-pick --quit
2. Cherry-Pick with Conflict Resolution
Handle conflicts during cherry-pick:
git status
# Shows conflicted files
# Resolve conflicts manually
# Edit files, remove conflict markers
# Mark as resolved
git add resolved-file.js
# Continue cherry-pick
git cherry-pick --continue
# Or abort if too complex
git cherry-pick --abort
Pro Tip: Use git mergetool for visual conflict resolution during cherry-pick operations.
3. Cherry-Pick from Another Repository
Apply commits from a different Git repository:
git remote add other-repo /path/to/other
# Fetch their commits
git fetch other-repo
# Cherry-pick from their branch
git cherry-pick other-repo/feature-branch~3..other-repo/feature-branch
# Clean up remote
git remote remove other-repo
4. Using --strategy-option
Control merge strategy during cherry-pick:
git cherry-pick -X ours abc1234
# Prefer their version in conflicts
git cherry-pick -X theirs abc1234
# Ignore whitespace changes
git cherry-pick -X ignore-all-space abc1234
# Rename detection
git cherry-pick -X find-renames abc1234
Cherry-Pick vs Merge vs Rebase
| Operation | Purpose | History Effect | When to Use |
|---|---|---|---|
| Cherry-Pick | Apply specific commits | Creates new commits (different hashes) | Selective changes, hotfixes, recovery |
| Merge | Combine branch histories | Preserves all commits, adds merge commit | Complete feature integration |
| Rebase | Rewrite branch onto another | Replays commits (new hashes), linear history | Clean history before PR |
Rule of Thumb: Use cherry-pick for surgical precision, merge for complete integration, and rebase for history cleaning. Cherry-pick should be the exception, not the rule.
Interactive Cherry-Pick Demo
Try It: Cherry-Pick Simulation
Common Pitfalls and Solutions
1. Duplicate Commits
Problem: Cherry-picking the same commit multiple times creates duplicates.
git log --grep="original message" --oneline
# Use cherry-pick with --ff to fast-forward if possible
git cherry-pick --ff abc1234
# Or skip already applied commits
git cherry-pick --skip
2. Missing Dependencies
Problem: Cherry-picked commit depends on previous commits not picked.
git show --stat abc1234
git log --oneline abc1234^..abc1234
# Cherry-pick the chain of commits
git cherry-pick dependency^..feature-commit
# Or use -x flag to preserve reference
git cherry-pick -x abc1234
3. Merge Conflicts
Problem: Complex conflicts make cherry-pick difficult.
git cherry-pick -m 1 abc1234
# Apply but don't commit, resolve manually
git cherry-pick -n abc1234
git status
git add -p
git commit -m "Manual cherry-pick resolution"
# Consider if merge would be better
git merge --no-ff feature-branch
Command Reference
Basic Operations
git cherry-pick abc1234
# Cherry-pick multiple commits
git cherry-pick abc1234 def5678 ghi9012
# Cherry-pick range of commits
git cherry-pick start-commit..end-commit
# Cherry-pick with original author
git cherry-pick -x abc1234
Advanced Options
git cherry-pick -n abc1234
# Edit commit message before applying
git cherry-pick -e abc1234
# Sign the new commit
git cherry-pick -s abc1234
# Use mainline parent for merge commits
git cherry-pick -m 1 merge-commit
# Control merge strategy
git cherry-pick -X ours abc1234
Control and Recovery
git cherry-pick --continue
# Skip current commit
git cherry-pick --skip
# Abort entire operation
git cherry-pick --abort
# Quit but keep changes
git cherry-pick --quit
# See what would be cherry-picked
git cherry -v main..feature
Best Practices
When to Use Cherry-Pick
- Apply hotfixes to multiple branches
- Recover lost commits from reflog
- Backport features to older versions
- Extract specific changes from feature branches
- Apply code review suggestions selectively
When to Avoid Cherry-Pick
- Complete feature integration (use merge)
- History cleanup (use rebase)
- When commits have complex dependencies
- For regular sync between long-lived branches
- When team workflow prefers other methods
Pro Tips
- Use
-xflag to preserve original commit reference - Always test cherry-picked changes thoroughly
- Document why cherry-pick was used
- Consider using patches for complex scenarios
- Set up CI to detect duplicate commits
Frequently Asked Questions
No, cherry-pick creates a new commit with a different hash. While the changes (diff) are the same, several things differ:
- Commit hash: Completely different (SHA-1 calculation includes timestamp, parent, etc.)
- Parent commit: Points to current HEAD, not original parent
- Timestamp: New commit time (when cherry-picked)
- Commiter: Person who performed cherry-pick
- Author: Can be preserved (original author) or changed
Preserving original info:
git cherry-pick abc1234
# Also add reference to original commit
git cherry-pick -x abc1234
# Adds: (cherry picked from commit abc1234)
# Keep original author only
git cherry-pick --keep-author abc1234
Note: Even with -x, it's still a different commit. Git won't recognize it as the same commit for merge purposes.
Cherry-picking merge commits requires special handling because they have multiple parents:
git log --oneline --merges -5
# abc1234 Merge branch 'feature' into 'main'
# View parents
git show --pretty=raw abc1234
# parent def5678 (main)
# parent ghi9012 (feature)
# Cherry-pick merge commit (specify mainline parent)
git cherry-pick -m 1 abc1234
# -m 1 uses first parent (main) as base
# -m 2 uses second parent (feature) as base
What happens: Git computes the diff between the merge commit and the specified parent, then applies that diff.
Warning: This can be complex and may create conflicts. Consider alternatives:
- Cherry-pick individual commits from the feature branch instead
- Create a new merge if that's what you actually need
- Use rebase if appropriate for your workflow
Best practice: Avoid cherry-picking merge commits when possible. They're designed to join histories, not to be moved.
Yes, you can undo a cherry-pick in several ways:
- If not pushed: Use reset
# Undo last commit (cherry-pick)
git reset --soft HEAD~1
# Or discard completely
git reset --hard HEAD~1 - If pushed: Use revert
# Revert the cherry-picked commit
git revert NEW_COMMIT_HASH
git push origin branch - During cherry-pick: Use abort
# If in middle of cherry-pick with conflicts
git cherry-pick --abort - Using reflog: Recovery
# Find state before cherry-pick
git reflog
# abc1234 HEAD@{2}: cherry-pick: Add feature
# def5678 HEAD@{3}: commit: Previous work
git reset --hard HEAD@{3}
Prevention: Test cherry-picks in a separate branch first:
git checkout -b test-cherry-pick main
git cherry-pick abc1234
# Test thoroughly...
git checkout main
git merge test-cherry-pick
You can cherry-pick commits from a GitHub PR using several methods:
- Using PR branch directly:
# Add PR remote
git remote add pr-author https://github.com/username/repo.git
git fetch pr-author
# Cherry-pick specific commits
git cherry-pick pr-author/branch~3..pr-author/branch - Using GitHub CLI:
gh pr checkout 123
# Now you have the PR branch locally
git cherry-pick abc1234 - Using patch files:
# On GitHub, click "View file" then "Raw"
# Save as patch, then apply:
git apply pr-changes.patch
# Or for specific commit patch:
git format-patch -1 abc1234 --stdout > fix.patch
git am fix.patch - Direct from PR number:
# Fetch PR commits
git fetch origin pull/123/head:pr-123
git checkout pr-123
# Now cherry-pick from this branch
git checkout main
git cherry-pick abc1234
GitHub-specific tip: You can also use "Cherry-pick" button in the GitHub UI for individual commits in the PR.
Both can apply changes from one place to another, but with different approaches:
| Aspect | git cherry-pick |
git format-patch / git am |
|---|---|---|
| Purpose | Apply commits directly | Create/apply patch files |
| Method | Direct commit-to-commit transfer | File-based transfer |
| Preserves | Author, message, changes | Changes only (configurable) |
| Use case | Within same repo or closely related | Email, cross-repo, code review |
| Complexity | Simple, one command | Two-step process |
Example workflow comparison:
git cherry-pick abc1234
# Patch approach
git format-patch -1 abc1234 --stdout > fix.patch
git am fix.patch
# Or apply without commit metadata
git apply fix.patch
When to use patches instead:
- When emailing changes to others
- When working across unrelated repositories
- When you need to review changes before applying
- When preserving exact commit metadata isn't important
- For code review workflows (like mailing lists)