Rebase vs merge: two ways to combine work
Merge and rebase both bring one branch's changes into another. The difference is what they do to your project's history: merge joins the two timelines; rebase replays your commits on top of the other branch to make one straight line. Beginners can happily use merge and ignore rebase for a while — but here's what rebase is, so it stops being mysterious.
The situation
You branched feat/search off main. While you worked, teammates added commits to main. Now the two have drifted apart:
main: A─B─C─F─G (teammates added F, G)
\
feat/search: D─E (you added D, E)
You want your D─E work to sit on top of the latest main. Two ways.
Merge: join them
git switch feat/search
git merge main
Git creates a merge commit (M) that ties the two histories together:
main: A─B─C─F─G
\ \
feat/search: D─E──M
- ✅ Honest: it shows exactly what happened and when.
- ✅ Safe: nothing is rewritten.
- 🚫 History gets a bit tangled with merge commits when there are many.
Rebase: replay on top
git switch feat/search
git rebase main
Rebase takes your commits D and E, sets them aside, moves your branch to the tip of main, and re-applies D and E there as new commits (D', E'):
main: A─B─C─F─G
\
feat/search: D'─E'
- ✅ Clean, straight-line history — as if you'd started from the latest
main. - ✅ No extra merge commits.
- 🚫 It rewrites your commits (they get new IDs). That's fine on your own branch — but dangerous on shared branches.
The one rule that keeps you safe
Never rebase commits that other people have already pulled (like
mainor any shared branch).
Rebasing rewrites history. If you rewrite commits others are building on, everyone's copies fall out of sync and you create a mess. So:
- Rebase your own feature branch onto
main— good, keeps things tidy. - Rebase
mainitself, or a branch your teammate is also using — no. Use merge there.
Which should a beginner use?
Use merge. It's safe, it's honest, and you cannot corrupt shared history with it. Reach for rebase later, once you're comfortable — typically to tidy your own branch before opening a pull request:
git switch feat/search
git rebase main # replay my work on the latest main, cleanly
git push --force-with-lease # update my branch (only mine!)
Many teams simply use squash and merge on pull requests (see the merge page) to get a clean history without anyone hand-rebasing. That's a perfectly good middle path.
Takeaway: merge = join two timelines (safe, always fine). Rebase = replay your commits on top for a straight line (tidy, but only on your own branch). When in doubt, merge.