Git Advanced (Rebase/Cherry-pick) Cheat Sheet
Advanced Git history manipulation techniques including interactive rebase, cherry-picking, and conflict resolution.
Rebasing onto Main
Replay your branch's commits on top of the latest main.
git fetch origingit checkout feature-branchgit rebase origin/main# If conflicts occur, resolve files then:git add <resolved-file>git rebase --continue# Abort and return to pre-rebase stategit rebase --abort
Interactive Rebase
Rewrite the last 4 commits: squash, reword, or drop them.
git rebase -i HEAD~4# In the editor, change 'pick' to:# reword - edit the commit message# squash - combine into previous commit, keep both messages# fixup - combine into previous commit, discard this message# drop - remove the commit entirely# edit - pause to amend the commit
Cherry-picking Commits
Apply a specific commit from another branch onto the current one.
git cherry-pick abc1234# Cherry-pick a range of commits (exclusive of first)git cherry-pick abc1234..def5678# Cherry-pick without auto-committing, to inspect firstgit cherry-pick -n abc1234# Continue after resolving a cherry-pick conflictgit cherry-pick --continue
Recovering with reflog
Find and restore commits that seem lost after a bad rebase or reset.
git reflog# e.g. abc1234 HEAD@{2}: rebase (start): checkout maingit reset --hard HEAD@{2} # restore to a previous state# orgit cherry-pick abc1234 # reapply a specific lost commit
Rebase vs Merge
When to choose one strategy over the other.
- Rebase- Produces a linear history by replaying commits; rewrites SHAs, avoid on shared/public branches
- Merge- Preserves true history with a merge commit; safe on shared branches
- golden rule- Never rebase commits that have already been pushed and pulled by others
Autosquash with fixup! and squash!
Automatically fold fixup commits into their target during interactive rebase without manual reordering.
# Make a fix targeting an earlier commitgit commit --fixup=abc1234# Or write a message that will be squashed instead of just appliedgit commit --squash=abc1234# Rebase interactively; fixup!/squash! commits are auto-reordered# and marked next to their target, no manual editing neededgit rebase -i --autosquash abc1234~1# Make it the default so you never need the flaggit config --global rebase.autosquash true
Reuse Recorded Resolutions (rerere)
Have Git remember how you resolved a conflict so repeated rebases don't make you redo it.
git config --global rerere.enabled true# First time you hit a conflict, resolve normally:git rebase origin/main# ...edit conflicted files...git add <file>git rebase --continue# Next time the SAME conflict pattern appears (e.g. rebase# after amending), Git auto-applies the recorded resolutiongit rerere statusgit rerere diff
rebase --exec and --onto
Run a command after every replayed commit, and transplant commits onto a different base entirely.
# Run tests after each commit while rebasing, halting on failuregit rebase -i HEAD~5 --exec "npm test"# Move a range of commits from one base to another# ("replay commits after <since> up to <branch>, rooted on <newbase>")git rebase --onto main feature-base feature-branch# Common case: drop a range of already-merged commits from a branchgit rebase --onto main~1 main~1 topic
Cherry-picking Merge Commits & Conflicts
Pick a commit from a merge parent, and use rerere/mergetool for multi-commit cherry-pick sessions.
# Cherry-pick a merge commit, choosing which parent is 'mainline'git cherry-pick -m 1 <merge-commit-sha># Cherry-pick a series but keep going after conflicts,# recording each skip/resolutiongit cherry-pick abc123^..def456# on conflict:git statusgit checkout --ours -- path/to/file # or --theirs, or hand-editgit add path/to/filegit cherry-pick --continue# Bail out of the whole sequence cleanlygit cherry-pick --abort
History-Rewrite Safety Nets
Mechanisms that make destructive-looking operations recoverable.
- --force-with-lease- Safer than --force; refuses to push if the remote branch has commits you haven't fetched, preventing you from clobbering a teammate's work
- git reflog expire- Reflog entries expire after 90 days (unreachable) / 30 days by default — don't rely on reflog for long-term recovery
- ORIG_HEAD- Automatically set before rebase/reset/merge to the previous HEAD; `git reset --hard ORIG_HEAD` undoes the last rewrite in one step
- git commit --amend --no-edit- Amends the last commit's tree without touching the message; combine with `git rebase -i --autosquash` for bigger histories
- git fsck --lost-found- Finds dangling commits/blobs not referenced by any branch or the reflog, as a last-resort recovery path
Before an interactive rebase you're unsure about, create a safety branch (`git branch backup-before-rebase`) — if it goes wrong, `git reflog` can recover it, but a named branch pointer is faster and less error-prone.