Difficulty: Intermediate
Explain git cherry-pick and git bisect. When would you use each, and what are their limitations?
git cherry-pick applies the changes introduced by a specific commit onto your current branch, creating a new commit with the same changes but a different hash. It is useful when you need a specific fix from another branch without merging the entire branch. Common scenarios include back-porting a hotfix from main to a release branch or pulling a single feature commit into your branch.
git bisect performs a binary search through your commit history to find the exact commit that introduced a bug. You mark a known good commit and a known bad commit, and Git checks out the midpoint for you to test. You then mark it good or bad, and Git narrows the search by half each time. For N commits, bisect finds the culprit in roughly log2(N) steps.
Cherry-pick limitations: it creates duplicate commits with different hashes, which can cause confusion if the original branch is later merged. Bisect limitations: it requires a reproducible test for the bug, and works best when each commit is a complete, buildable state.
# Apply a specific commit to the current branch
git cherry-pick a1b2c3d
# Creates a NEW commit with the same changes but different hash
# Cherry-pick without committing (stage changes only)
git cherry-pick --no-commit a1b2c3d
git cherry-pick --no-commit e4f5g6h
# Review combined changes, then commit once:
git commit -m "Backport: auth fix and CORS fix"
# Cherry-pick a range of commits
git cherry-pick a1b2c3d..e4f5g6h
# Applies all commits AFTER a1b2c3d up to and including e4f5g6h
# Cherry-pick inclusive of both endpoints
git cherry-pick a1b2c3d^..e4f5g6h
# If cherry-pick conflicts:
# 1. Resolve the conflict in the file
# 2. git add <resolved-files>
# 3. git cherry-pick --continue
# Or abort: git cherry-pick --abort
# Real-world scenario: hotfix backport
git checkout release/2.0
git cherry-pick main~3 # apply the hotfix from main
git push origin release/2.0
Cherry-pick copies a commit's changes to your branch. Use --no-commit to combine multiple cherry-picks into a single commit. Always note which commits were cherry-picked to avoid confusion.
# Start bisecting
git bisect start
# Mark the current commit as bad (has the bug)
git bisect bad
# Mark a known good commit (did not have the bug)
git bisect good v1.0.0
# Bisecting: 15 revisions left to test (roughly 4 steps)
# Git checks out the midpoint commit
# Test your application, then mark it:
git bisect good # if the bug is NOT present
# OR
git bisect bad # if the bug IS present
# Repeat until Git identifies the first bad commit:
# a1b2c3d is the first bad commit
# commit a1b2c3d
# Author: John
# Date: Mon Jan 15
# feat: change auth validation
# End the bisect session
git bisect reset
# Returns to the branch you were on before
# View bisect log
git bisect log
# Shows all good/bad markings for reference
Bisect uses binary search: for 1000 commits, it finds the bug in about 10 steps instead of checking all 1000. Mark good/bad at each step and Git narrows down automatically.
# Automate bisect with a test script
git bisect start HEAD v1.0.0
git bisect run npm test
# Git runs 'npm test' at each midpoint
# Exit code 0 = good, non-zero = bad
# Fully automatic bug finding!
# Use a custom test script
git bisect run ./test-for-bug.sh
# test-for-bug.sh:
#!/bin/bash
# npm run build && node -e "require('./dist').validate('test')"
# Exit 0 if OK, exit 1 if bug exists
# Skip a commit that cannot be tested (broken build)
git bisect skip
# Git picks a nearby commit instead
# Bisect with paths (only check specific files)
git bisect start -- src/auth/
# Only considers commits that touched src/auth/
Automated bisect is extremely powerful. Write a small script that exits 0 for good and non-zero for bad, and Git finds the exact breaking commit hands-free.
git cherry-pick, git bisect, Selective Commits, Bug Hunting, Binary Search