Rebasing & Cherry-Picking
Where merge combines two histories with a new merge commit,
rebase rewrites one branch’s commits so they appear to start from a
different base — producing a linear history with no merge commits.
Basic rebase
git switch feature-x
git rebase main
This takes every commit unique to feature-x, temporarily sets it aside,
resets feature-x to the tip of main, then replays each commit on top
one at a time — giving each a new SHA, since its parent changed.
Merge vs. rebase
| Merge | Rebase | |
|---|---|---|
| History shape | Preserves exactly what happened, including a merge commit | Linear, as if the branch was written on top of the latest main |
| Original commit SHAs | Unchanged | Rewritten (new SHAs) |
| Safe on shared/pushed branches? | Yes, always | No — only rebase commits nobody else has pulled |
| Good for | Preserving true history, feature branches merged via PR | Cleaning up a local branch before opening a PR |
The golden rule of rebasing: never rebase commits that exist outside your local repository, i.e. that you’ve already pushed and others might have based work on. Rewriting shared history forces everyone else to reconcile diverging SHAs by hand.
Resolving conflicts during a rebase
# Git pauses at the first conflicting commit
git status # see what's conflicted
# edit files, resolve markers
git add <file>
git rebase --continue # apply the next commit
git rebase --skip # or: drop this commit entirely
git rebase --abort # or: bail out, back to pre-rebase state
Interactive rebase
git rebase -i opens an editable list of commits, letting you reorder,
edit, squash, or drop them before they’re replayed — the standard way to
clean up a messy local branch before pushing:
git rebase -i HEAD~5 # interactively edit the last 5 commits
git rebase -i main # interactively edit everything since branching from main
The editor shows one line per commit with an action keyword you can change:
| Action | Effect |
|---|---|
pick | keep the commit as-is (default) |
reword | keep the commit, but edit its message |
edit | pause after applying, so you can amend it |
squash | combine into the previous commit, merging messages |
fixup | combine into the previous commit, discarding this message |
drop | remove the commit entirely |
Reordering lines reorders the commits. Save and close the editor to run the rebase with those instructions.
Cherry-picking
git cherry-pick applies one specific commit from anywhere in the
repository’s history onto your current branch — useful for porting a
single fix to a release branch without merging everything else:
git cherry-pick <sha> # apply one commit here
git cherry-pick <sha1> <sha2> # apply several, in order
git cherry-pick A..B # apply a range (exclusive of A)
git cherry-pick --no-commit <sha> # stage the change without committing
git cherry-pick --continue # after resolving a conflict
git cherry-pick --abort # bail out
Autosquash workflow
Mark small fixups against an earlier commit as you make them, then let rebase sort out the ordering automatically:
git commit --fixup <sha> # create a fixup! commit
git rebase -i --autosquash <sha>~1 # auto-arranges + marks it "fixup"