The Eternal Debate
Few topics spark more disagreement in development teams than the rebase-vs-merge question. Both commands integrate changes from one branch into another — but they do it in fundamentally different ways, with very different effects on your Git history. Understanding those differences will help you make deliberate choices rather than defaulting to whichever command you learned first.
What git merge Does
When you run git merge feature-branch, Git takes the two branch tips and creates a new merge commit that records the combination. The history is preserved exactly as it happened — every commit on both branches remains in place, and the merge commit ties them together.
Result: A non-destructive operation that adds a merge commit. Your history is accurate but can become a tangled web of branches, especially on busy repositories.
When to use merge
- Integrating a completed feature branch back into
mainordevelop. - When preserving the full, accurate history of how and when work was integrated is important.
- On shared/public branches — merging is safer because it never rewrites commits that others may have based work on.
- When you want a clear record that a feature was developed separately before being incorporated.
What git rebase Does
When you run git rebase main from a feature branch, Git takes your commits and replays them on top of the tip of main. The result is a linear history — as if you had started your feature branch from the current state of main.
Result: A cleaner, linear history, but at the cost of rewriting commits. Each replayed commit gets a new SHA hash.
When to use rebase
- Keeping a feature branch up-to-date with
mainwhile you're still developing. - Before submitting a pull request — rebasing onto the latest
mainreduces merge conflicts for the reviewer. - Cleaning up messy local commits before sharing them (interactive rebase:
git rebase -i). - Maintaining a readable linear history on a solo project or small team.
The Golden Rule of Rebasing
Never rebase commits that exist on a shared/public branch.
Because rebase rewrites commit hashes, if you rebase commits that your teammates have already pulled and built upon, their histories will diverge from yours. This creates painful conflicts that are hard to untangle. The rule is simple: rebase only your local, unpushed commits.
Interactive Rebase: The Hidden Power Tool
One of the most useful but underused Git features is git rebase -i HEAD~N (where N is the number of commits back you want to go). This opens an editor where you can:
- squash — combine multiple commits into one.
- reword — edit a commit message.
- drop — remove a commit entirely.
- reorder — change the sequence of commits.
This is invaluable for cleaning up a feature branch before opening a pull request — turning a series of "WIP", "fix", "fix again" commits into a clean, logical sequence.
A Practical Workflow That Uses Both
- Create a feature branch from
main. - Commit freely while developing — messy commits are fine locally.
- Before opening a PR, run
git rebase mainto incorporate any new changes from main. - Use
git rebase -ito clean up your commit history. - Open the PR. The reviewer merges it using a merge commit (or squash merge) to record the integration point.
Summary
| Merge | Rebase | |
|---|---|---|
| History shape | Preserves branches | Linear |
| Rewrites commits? | No | Yes |
| Safe on shared branches? | Yes | No |
| Best for | Integration points | Local cleanup, staying current |
The bottom line: use merge for integration, use rebase for keeping your local branch current and your history clean. Combine both for the best of both worlds.