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 main or develop.
  • 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 main while you're still developing.
  • Before submitting a pull request — rebasing onto the latest main reduces 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

  1. Create a feature branch from main.
  2. Commit freely while developing — messy commits are fine locally.
  3. Before opening a PR, run git rebase main to incorporate any new changes from main.
  4. Use git rebase -i to clean up your commit history.
  5. 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.