March 26, 202610 min read

Git Advanced Techniques — Rebase, Cherry-Pick, Bisect, and Stash

Beyond basic git: interactive rebase, cherry-pick workflows, git bisect for bug hunting, stash management, reflog recovery, and worktrees. Real scenarios for each technique.

git rebase cherry-pick bisect advanced
Ad 336x280

You know git add, git commit, git push. You might even know git branch and git merge. But there's a tier of git commands that separates developers who fight git from developers who wield it. These commands aren't obscure -- they solve problems that come up weekly on any active team.

Interactive Rebase

Regular rebase replays commits on top of another branch. Interactive rebase lets you rewrite history: squash commits, reorder them, edit messages, or drop commits entirely.

When to Use It

  • Clean up messy WIP commits before merging to main
  • Combine "fix typo" and "oops forgot file" into the original commit
  • Reorder commits so the PR tells a logical story

How It Works

# Rebase the last 4 commits interactively
git rebase -i HEAD~4

This opens your editor with something like:

pick a1b2c3d Add user authentication
pick e4f5g6h Fix typo in auth middleware
pick i7j8k9l Add password reset flow
pick m0n1o2p Fix: forgot to export reset handler

Change the commands to reshape history:

pick a1b2c3d Add user authentication
fixup e4f5g6h Fix typo in auth middleware
pick i7j8k9l Add password reset flow
fixup m0n1o2p Fix: forgot to export reset handler
CommandWhat It Does
pickKeep the commit as-is
rewordKeep changes, edit the commit message
editPause at this commit so you can amend it
squashCombine with previous commit, edit the merged message
fixupCombine with previous commit, discard this commit's message
dropRemove the commit entirely
After saving, git replays the commits with your modifications. The result: two clean commits instead of four messy ones.

The Golden Rule

Never rebase commits that have been pushed to a shared branch. Rebase rewrites commit hashes. If someone else has based work on the original commits, you've just created a parallel timeline. Feature branches that only you work on? Rebase freely. main? Never.
# Safe: rebase your feature branch onto latest main
git checkout feature/auth
git rebase main

# Dangerous: rebase main (never do this)
git checkout main
git rebase feature/auth  # DON'T

Resolving Conflicts During Rebase

When a conflict occurs mid-rebase:

# 1. Fix the conflicted files
# 2. Stage the fixes
git add src/auth.ts

# 3. Continue the rebase
git rebase --continue

# Or abort if things go sideways
git rebase --abort

Unlike merge conflicts (which happen once), rebase conflicts can occur at each commit being replayed. If your branch has 20 commits and many touch the same files, consider squashing first to reduce conflict surface.

Cherry-Pick

Cherry-pick copies a specific commit from one branch to another. Not a merge -- just that one commit, applied as a new commit on the current branch.

Real Scenarios

Hotfix backporting: A bug fix lands on main, but you need it on the release/v2.1 branch too.
git checkout release/v2.1
git cherry-pick abc123f
Pulling one feature from a stale branch: Someone started a feature branch months ago, abandoned it, but one commit in there has useful work.
git cherry-pick def456a
Selective deployment: Your branch has 10 commits but only 3 are ready for production.
git checkout deploy-branch
git cherry-pick commit1 commit2 commit3

Cherry-Pick a Range

# Pick commits A through D (inclusive of D, exclusive of A)
git cherry-pick A..D

# Pick commits A through D (inclusive of both)
git cherry-pick A^..D

When NOT to Cherry-Pick

If you're cherry-picking more than 3-4 commits, you probably want a merge or rebase instead. Cherry-picks create duplicate commits (different hashes, same changes), which makes git history harder to follow and can cause confusing conflicts later.

Git Bisect

Bisect is git's binary search tool. You tell it "this commit is good, this commit is bad" and it walks the history to find the exact commit that introduced a bug.

The Workflow

# Start bisecting
git bisect start

# Mark the current (broken) commit as bad
git bisect bad

# Mark a known-good commit (maybe last week's release)
git bisect good v2.3.0

# Git checks out a commit halfway between good and bad
# Test it, then tell git:
git bisect good  # if this commit works
# or
git bisect bad   # if this commit is broken

# Repeat until git finds the culprit
# Git will output: "abc123f is the first bad commit"

# Done -- go back to your branch
git bisect reset

For a range of 1000 commits, bisect finds the culprit in about 10 steps (log2(1000) ≈ 10). Way faster than checking commits one by one.

Automated Bisect

If you have a test that reproduces the bug, bisect can run it automatically:

git bisect start HEAD v2.3.0
git bisect run npm test -- --grep "user login"

Git will run the command at each step. Exit code 0 means "good", non-zero means "bad". It'll find the breaking commit without you touching anything.

# You can also use a script
git bisect run ./test-bug.sh

Where test-bug.sh is:

#!/bin/bash
# Returns 0 (good) if the bug is NOT present
# Returns 1 (bad) if the bug IS present
npm run build 2>/dev/null && node -e "
const result = require('./dist/calculate').compute(42);
process.exit(result === 84 ? 0 : 1);
"

This is one of the most underused git features. It's saved me hours on multiple occasions -- especially on large codebases where the bug could be in any of hundreds of recent commits.

Git Stash

Stash temporarily shelves uncommitted changes so you can switch branches without committing half-done work.

Basic Usage

# Stash current changes
git stash

# List stashes
git stash list
# stash@{0}: WIP on feature/auth: abc123f Add login form
# stash@{1}: WIP on main: def456a Update deps

# Apply the most recent stash (keeps it in the stash list)
git stash apply

# Apply and remove from stash list
git stash pop

# Apply a specific stash
git stash apply stash@{1}

# Drop a stash
git stash drop stash@{0}

# Clear all stashes
git stash clear

Named Stashes

Default stash messages are useless. Name them:

git stash push -m "half-done payment integration"

Now git stash list shows something meaningful.

Stash Individual Files

# Stash only specific files
git stash push -m "experimental API change" src/api/routes.ts src/api/middleware.ts

# Stash everything except staged changes
git stash push --keep-index -m "stash unstaged only"

Stash Pitfall

Stashes are local and not pushed to remote. They're also easy to forget about. I've seen developers with 30+ stashes they'll never look at again. If you stash something and it's still relevant after a day, commit it to a branch instead:

# Turn a stash into a branch
git stash branch feature/payment-wip stash@{0}

Reflog -- Your Safety Net

Reflog records every movement of HEAD. Every commit, rebase, reset, checkout -- everything. It's your undo history.

Recovery Scenarios

Accidentally reset --hard and lost commits:
# See what HEAD pointed to recently
git reflog
# abc123f HEAD@{0}: reset: moving to HEAD~3
# def456a HEAD@{1}: commit: Add payment processing
# ghi789b HEAD@{2}: commit: Add order validation
# jkl012c HEAD@{3}: commit: Add cart functionality

# Recover the lost commits
git checkout def456a
# Or create a branch from the lost commit
git branch recovery def456a
Rebase went wrong:
# Find where you were before the rebase
git reflog
# ... find the entry before the rebase started

# Reset to that point
git reset --hard HEAD@{5}
Deleted a branch:
git reflog
# Find the last commit on that branch
git branch restored-branch abc123f

Reflog entries expire after 90 days by default (30 days for unreachable commits). It's local only -- not pushed to remote.

Worktrees

Worktrees let you check out multiple branches simultaneously in separate directories. Instead of stashing, switching branches, doing work, switching back, and popping the stash -- just work in both branches at the same time.

Setup

# From your main repo directory
git worktree add ../project-hotfix hotfix/critical-bug
git worktree add ../project-review feature/new-api

# List worktrees
git worktree list
# /home/user/project           abc123f [main]
# /home/user/project-hotfix    def456a [hotfix/critical-bug]
# /home/user/project-review    ghi789b [feature/new-api]

Now you have three separate directories, each on a different branch, sharing the same git history. Changes in one are visible to the others after committing.

When Worktrees Shine

  • Code review: Check out the PR branch in a worktree, run it, test it, while your main work continues undisturbed.
  • Hotfixes: Urgent fix needed while you're mid-feature. Worktree lets you fix, commit, push, and deploy without touching your feature branch.
  • Long builds: Start a build in one worktree, continue coding in another.
  • Comparing behavior: Run two versions of the app side by side on different ports.

Cleanup

# Remove a worktree (after merging the branch)
git worktree remove ../project-hotfix

# Prune stale worktree references
git worktree prune

Quick Reference

ProblemSolution
Messy commit history on feature branchgit rebase -i HEAD~N
Need one commit from another branchgit cherry-pick
Find which commit broke somethinggit bisect start + good/bad
Need to switch branches with uncommitted workgit stash push -m "description"
Lost commits after reset/rebasegit reflog + git checkout
Work on two branches simultaneouslygit worktree add
Undo the last commit (keep changes)git reset --soft HEAD~1
See what changed in a file over timegit log -p -- path/to/file
Find who changed a specific linegit blame -L 50,60 file.ts
Show what branches contain a commitgit branch --contains

Decision: Merge vs Rebase

This is the eternal debate. Here's when to use each:

ScenarioUseWhy
Updating feature branch with latest mainRebaseClean linear history
Merging feature into mainMergePreserves branch context
Shared branch (multiple people)MergeDon't rewrite shared history
Solo feature branch cleanupRebaseSquash WIP commits
Long-running release branchMergeNeed to track what was integrated when
The CodeUp git workflow articles at codeup.dev go deeper on team branching strategies. But the tools here -- rebase, cherry-pick, bisect, stash, reflog, worktrees -- cover 95% of what you'll need beyond the basics. The key is knowing they exist so you reach for them instead of clunky workarounds.
Ad 728x90