After this lesson, you will be able to: Decide between rebase and merge for any given situation, run interactive rebase to clean up commit history, and avoid the rewrite-shared-history pitfall.
Rebase and merge both combine work from two branches. The choice between them determines what your history looks like and how easy it is to debug six months from now.
Merge: creates a new commit with two parents. Preserves both histories; result tree is the combination. History looks like a graph. Rebase: rewrites your commits as if they had been made on top of the new base. History stays linear; each commit looks 'cleaner'. Same final code state in most cases; very different history shape.
Rebase your feature branch onto main BEFORE opening a PR. Linear history is easier to review. Merge the PR into main when it lands (most teams use 'squash merge' which collapses the PR's commits into one on main, the cleanest default). NEVER rebase a branch that other people have already pulled. You rewrite SHAs; their local copies become orphaned. Pull main with `git pull --rebase` so your local main stays linear with origin.
Squash 'WIP' commits, fix typos in messages, reorder commits. The PR your reviewer sees should tell a story.
# On your feature branch, before opening the PR:git rebase -i origin/main# Opens an editor with one line per commit:# pick a1b2c3d Add user table migration# pick d4e5f6a WIP# pick 7g8h9i0 fix typo in migration# pick j1k2l3m WIP debug# pick n4o5p6q add user creation endpoint## Change 'pick' to:# pick -> keep this commit as-is# squash -> combine into the previous commit's message# fixup -> combine into previous, DROP the message# reword -> keep the commit but rewrite the message# drop -> remove the commit entirely## Save & exit; resolve any conflicts if asked.# Force-push (safely): git push --force-with-lease
Squash merge: the entire PR collapses into one commit on main. Clean history, lose intermediate detail. The most popular default. Merge commit: keeps every commit + a merge commit. Verbose history; useful for very long-running branches. Rebase merge: replays each commit linearly onto main. No merge commit. Most precise; can be confusing in cross-team reviews. GitHub lets repo admins enforce one style; pick one and stick with it.
Rebasing main onto your feature branch (backwards). The rebase target is what you want to be on top of; main goes on the BOTTOM. Force-pushing to a shared branch (e.g. main, develop). Set up branch protection so this fails at the server. Resolving rebase conflicts in a hurry and losing changes. Each conflict file is a small decision; don't speed-resolve. Rebasing 100+ commits at once. Break into smaller rebases. Treating rebase as 'better' than merge dogmatically. They're tools for different situations.
Pick the safest path.
Sign in and purchase access to unlock this lesson.