Cherry-Pick & Bisect
Quick Summary
git cherry-pick copies a specific commit from one branch to another — like picking one cherry from the tree without taking the whole branch. git bisect performs a binary search through your commit history to find exactly which commit introduced a bug.
git cherry-pick
When to Use
- Apply a hotfix from
mainto a release branch - Port a single commit without merging an entire branch
- Recover a commit from a deleted branch
Syntax
# Cherry-pick a single commit
git cherry-pick <commit-hash>
# Cherry-pick multiple commits
git cherry-pick <hash1> <hash2> <hash3>
# Cherry-pick a range (exclusive of first commit)
git cherry-pick A..B
# Cherry-pick without committing (stage only)
git cherry-pick --no-commit <hash>
# Abort a cherry-pick in progress
git cherry-pick --abort
Example
# You're on main, and need a specific fix from feature branch
git log --oneline feature/auth
# d4e5f6a feat: add auth validation (← this one!)
# c3d4e5f feat: add auth UI
# b2c3d4e feat: add auth models
git checkout main
git cherry-pick d4e5f6a
[main e5f6a7b] feat: add auth validation
1 file changed, 15 insertions(+)
Cherry-pick creates a NEW commit
The cherry-picked commit gets a new SHA hash on the target branch. If you later merge the source branch, Git may flag the duplicate change.
git bisect
The Problem
Your app worked last week but is broken now. You have 50 commits since then. Which commit broke it?
Without bisect: Test each commit manually (50 checks)
With bisect: Binary search (6 checks for 50 commits)
How It Works
flowchart LR
C1["C1 ✅"] --> C2["C2"] --> C3["C3"] --> C4["C4"] --> C5["C5 🐛"] --> C6["C6"] --> C7["C7 ❌"]
style C1 fill:#4CAF50
style C5 fill:#f44336
style C7 fill:#f44336
# 1. Start bisect
git bisect start
# 2. Mark current commit as bad
git bisect bad
# 3. Mark a known good commit
git bisect good v1.0 # or a specific commit hash
# Git checks out the middle commit
# Bisecting: 25 revisions left to test (roughly 5 steps)
# 4. Test the code, then tell Git the result
git bisect good # This commit works → bug is in later commits
# or
git bisect bad # This commit is broken → bug is in earlier commits
# 5. Git narrows down and checks out the next middle commit
# Repeat step 4 until Git finds the exact commit
# 6. Git reports the first bad commit
# b2c3d4e is the first bad commit
# commit b2c3d4e
# Author: donnyaw
# Date: Mon Feb 10
#
# refactor: change auth token format
# 7. End bisect (go back to your branch)
git bisect reset
Automated Bisect
If you have a test script that exits 0 for good and non-zero for bad:
git bisect start HEAD v1.0
git bisect run npm test
# Git automatically tests each commit and finds the culprit!
git bisect reset
Decision Guide
| What You Want | Command |
|---|---|
| Copy one commit to current branch | git cherry-pick <hash> |
| Copy commits without committing | git cherry-pick --no-commit <hash> |
| Find which commit introduced a bug | git bisect start + good / bad |
| Automate bug finding | git bisect run <test-script> |
Best Practices
- Prefer merge/rebase over cherry-pick — cherry-pick should be for exceptional cases
- Use bisect with automated tests — eliminates human error in the search process
- Always
git bisect resetwhen done — returns you to your original branch - Document cherry-picked commits — note the source in the commit message
What's Next
- Submodules & Subtrees — Include external repositories in your project
- Hooks & Automation — Automate tasks with Git hooks