Section 2 · Branching and Merging
Rebase vs Merge, and the Golden Rule
17 min3 min readFill in the blanks
Lesson at a glance
Rebase a feature branch onto main to keep history linear, handle conflicts mid-rebase, tidy commits interactively, and know when the golden rule says to merge instead.
- 1What rebase does
- 2Conflicts during a rebase
- 3Tidying with interactive rebase
- 4The golden rule
- 5Merge or rebase?
No video here — just the real thing: a written lesson, runnable examples, a quiz and practice.
In the last two lessons, combining branches meant merging, and a diverged history earned a merge commit. That’s honest and safe, but on a busy repository git log --graph starts to look like a train map. Rebasing is the other way to combine work: instead of joining two lines, it moves your line so there’s only one.
What rebase does
Your projects-grid branch split from main at b2. Since then main gained c3 and your branch has d4 and e5. From the branch, run:
git switch projects-grid
git rebase mainSuccessfully rebased and updated refs/heads/projects-grid.Git found the commits on your branch that aren’t on main (d4, e5), set them aside, moved your branch to main’s tip, and replayed each change on top, one commit at a time.
The replayed commits are new commits. Same changes and messages, different parents, so different IDs. That’s not a detail; it’s the whole story of when rebase is safe. A commit’s ID includes its parent, so you can’t move a commit, only make a copy somewhere else.
Now main is an ancestor of your branch, so bringing the work in is a fast-forward:
git switch main
git merge projects-grid # Fast-forwardHistory is a straight line, as if you’d started the grid after the typo fix.
Conflicts during a rebase
Because rebase replays commits one at a time, a conflict stops it at a specific commit. The routine is the one you learned for merges, with different words at the end:
# Git stops: CONFLICT (content): Merge conflict in projects.html
# edit projects.html, remove the markers, check it
git add projects.html
git rebase --continue # finish this commit, replay the nextgit rebase --abort returns the branch to exactly where it was before you started. git rebase --skip drops the commit that’s conflicting, which is rarely what you want.
One surprise: during a rebase, “ours” and “theirs” swap. You’re replaying your commits onto main, so HEAD (the top half of a conflict) is main’s side, and your commit is the bottom half. Read the labels, not your instincts.
Tidying with interactive rebase
Before you share a branch, you can rewrite its commits. git rebase -i opens a to-do list in your editor:
git rebase -i mainpick 4b1e2c0 Add projects grid
pick 9a3d7f1 fix typo
pick c2e8b44 Grid gap on mobileChange a word in front of a commit and save. reword edits its message, squash or fixup folds it into the commit above (keeping or discarding its message), drop deletes it, and reordering lines reorders commits. Changing pick 9a3d7f1 to fixup 9a3d7f1 turns three commits into two clean ones. This is how professionals keep “fix typo” commits out of a pull request.
The golden rule
Rebasing replaces commits with copies. That’s harmless when you’re the only one who has them. It’s a mess when someone else has already built on the originals: their history still contains d4 and e5, yours contains d4' and e5', and the next pull produces duplicate commits and baffling conflicts.
So: don’t rebase commits that exist outside your repository and that people may have based work on. In practice:
- Rebase freely on your own branches before you push or before anyone else touches them.
- Never rebase
mainor any branch other people pull from. - Rebasing your own pull request branch after pushing it is common and fine if nobody else commits to it. Git will reject the normal push because history was rewritten, so use:
git push --force-with-lease--force-with-lease overwrites the remote branch only if it still points where you last saw it. If a teammate pushed in the meantime, it refuses instead of erasing their work.
Merge or rebase?
| Merge | Rebase | |
|---|---|---|
| History | True record, with merge commits | Linear, as if work were sequential |
| Commit IDs | Unchanged | Rewritten |
| Safe on shared branches | Yes | No |
| Conflicts | Resolved once | May recur per replayed commit |
A sensible default: rebase your own feature branch onto main to stay current and tidy it before review; merge (often through a pull request) to land it. Many teams also set git pull to rebase your unpushed commits, which you’ll configure in the next section, when your portfolio finally gets a remote.
Key takeaways
git rebase mainreplays your branch’s commits on top ofmain’s tip, creating new commits with new IDs.- After a rebase, merging the branch into
mainis a fast-forward, so history stays a straight line. - During a rebase conflict, fix the file,
git addit, thengit rebase --continue;git rebase --abortundoes the whole rebase. - The golden rule is to never rebase commits that other people may have already built on; rebase only your own unshared work.
- If you must update a branch you already pushed, use
git push --force-with-lease, never a plain--force.