Git Rebase
Rebasing rewrites a branch's history so it looks as if it were built starting from a newer commit, producing a cleaner, linear project history than merging does.
What rebase actually does
When you run git rebase main while on a feature branch, Git finds the commits unique to your branch, temporarily sets them aside, moves your branch pointer to the tip of main, and then replays each of your commits one by one on top of that new base. The result is a branch whose commits look like they were written after all of main's latest work, even though you actually wrote them earlier.
Rebasing a feature branch onto main
$ git checkout feature/search-filters
$ git rebase main
First, rewinding head to replay your work on top of it...
Applying: add filter dropdown component
Applying: wire filter state to search query
Applying: add tests for filter combinationsRebase vs. merge
Merging joins two branches by creating a new merge commit that has two parents, preserving exactly what happened and when. Rebasing instead rewrites commits with new hashes so history looks linear, as if there had been no divergence at all. Neither is objectively better — they trade off honesty of history against readability of history.
Interactive rebase
Interactive rebase, triggered with git rebase -i, opens an editable list of your recent commits and lets you reorder, combine, edit, or drop them before they're replayed. It's the standard tool for tidying a messy feature branch — squashing three 'fix typo' commits into the commit they were fixing, for instance — before opening a pull request.
Interactive rebase to squash the last 3 commits
$ git rebase -i HEAD~3
pick a1b2c3d add filter dropdown component
squash e4f5g6h fix dropdown alignment
squash h7i8j9k address review comment
# Rebase 0f9e8d7..h7i8j9k onto 0f9e8d7
# Commands: p=pick, r=reword, e=edit, s=squash, f=fixup, d=dropChanging pick to squash on the second and third lines tells Git to fold those commits into the one above them, prompting you to write a single combined commit message. The rest of the file — the comment lines starting with # — is just reference documentation for the available commands and is ignored when the rebase runs.
Resolving conflicts during a rebase
Because each commit is replayed individually, a rebase can pause on any commit that conflicts with the new base. Unlike a merge conflict, which you resolve once, a rebase may require resolving the same logical conflict multiple times across several commits. Git tells you exactly which commit is paused and gives you three ways forward.
Handling a conflict mid-rebase
$ git rebase main
Auto-merging src/search.js
CONFLICT (content): Merge conflict in src/search.js
error: could not apply e4f5g6h... wire filter state to search query
$ git add src/search.js
$ git rebase --continueExercise: Git Rebase
What does `git rebase` fundamentally do to your commits?