Git Rebase vs Merge: When to Use Each (With Examples)
On this page
I've had this argument at every company I've worked at. The rebase vs merge debate is one of the longest-running in software development, and teams get genuinely heated about it. Both integrate changes from one branch into another, but the way they do it has real consequences for your workflow, code reviews, and whether your git history is useful or a tangled mess.
TL;DR: Understand the real difference between git rebase and git merge. Learn when to use each with practical examples and team workflow guidelines.
What Merge Does
git merge creates a new "merge commit" that ties two branches together. The history of both branches is preserved exactly as it happened.
# You're on feature-branch, want to integrate changes from main
git checkout feature-branch
git merge main
The resulting history looks like this:
* Merge branch 'main' into feature-branch (merge commit)
|\
| * Fix: update API endpoint (main)
| * Add rate limiting (main)
* | Add user profile page (feature-branch)
* | Fix profile image upload (feature-branch)
|/
* Initial commit
The merge commit (* at the top) has two parents, forming a visible junction in the history.
What Rebase Does
git rebase replays your commits on top of another branch. It rewrites history to make it appear as if you branched from the latest commit on the target branch.
# You're on feature-branch, want to integrate changes from main
git checkout feature-branch
git rebase main
The resulting history is linear:
* Add user profile page (feature-branch, rebased)
* Fix profile image upload (feature-branch, rebased)
* Fix: update API endpoint (main)
* Add rate limiting (main)
* Initial commit
No merge commit. Your feature branch commits now sit on top of main's latest changes, as if you just started working on them.
A Practical Example
Let's walk through a real scenario.
Starting Point
You and a teammate are both working from the same main branch:
# main branch has commits A → B → C
# You create feature-branch from C
git checkout -b feature-auth
# You make commits D and E
git commit -m "Add login form" # D
git commit -m "Add authentication API" # E
# Meanwhile, your teammate merges their work to main: commits F and G
# main is now A → B → C → F → G
# Your branch is A → B → C → D → E
Using Merge
git checkout feature-auth
git merge main
Result: A → B → C → D → E → M (where M is the merge commit that also includes F and G)
Your commits D and E stay in their original position. The merge commit M integrates the divergent histories.
Using Rebase
git checkout feature-auth
git rebase main
Result: A → B → C → F → G → D' → E'
Your commits D and E are rewritten as D' and E' (new commit hashes) and placed after main's latest commits. The history is linear.
When to Use Merge
1. Integrating Feature Branches into Main
When a feature branch is complete and reviewed, merge it to preserve the complete context:
git checkout main
git merge --no-ff feature-auth
The --no-ff flag forces a merge commit even if a fast-forward is possible. This creates a clear marker in history: "this group of commits was the auth feature."
2. Shared Branches
If multiple people are working on the same branch, never rebase. Rebase rewrites commit hashes, which means everyone else's local copies become incompatible:
# NEVER do this on a shared branch
git checkout shared-branch
git rebase main
git push --force # This breaks everyone else's local copy
3. When History Accuracy Matters
For regulated environments or projects where you need to prove exactly when changes were made, merge preserves the true chronological order.
When to Use Rebase
1. Keeping Feature Branches Up to Date
While working on a feature branch, rebase onto main regularly to stay current:
git checkout feature-auth
git rebase main
This keeps your branch's diff clean for code review. Reviewers see only your changes, not a tangle of merge commits from integrating main.
2. Cleaning Up Local Commits Before Merging
Interactive rebase lets you squash, reorder, and reword commits before creating a pull request:
git rebase -i HEAD~3
This opens an editor where you can combine your "WIP", "fix typo", and "actually fix the bug" commits into a single clean commit.
3. When You Want a Linear History
Some teams prefer a linear main branch where every commit is a complete, working change. Rebase enables this:
# On feature branch, before merging
git rebase main
git checkout main
git merge --ff-only feature-auth # Fast-forward: no merge commit
Handling Rebase Conflicts
Rebasing can produce conflicts at each replayed commit. This is the main pain point:
git rebase main
# CONFLICT in src/auth.ts
# Fix the conflict, then:
git add src/auth.ts
git rebase --continue
# If you want to abort and go back to before the rebase:
git rebase --abort
Pro tip: If you get the same conflict repeatedly (because your branch has many commits that touch the same lines), enable rerere:
git config --global rerere.enabled true
rerere (reuse recorded resolution) remembers how you resolved a conflict and applies the same resolution automatically if it encounters it again.
The Golden Rule of Rebasing
Never rebase commits that have been pushed to a shared branch.
If you have pushed your commits and someone else has pulled them, rebasing rewrites those commits' hashes. When you force-push the rewritten history, everyone else's local branch diverges from the remote. They will get confusing merge conflicts and potentially lose work.
# Safe: rebase local commits that only you have
git rebase main # ✓ fine
# Dangerous: rebase commits others may have pulled
git push --force # ✗ can break teammates' work
If you must force-push a rebased branch (common for PR branches where you are the only contributor), use --force-with-lease:
git push --force-with-lease
This fails if someone else has pushed to the branch since your last pull, preventing accidental overwrites.
Team Workflow Recommendations
For Most Teams: Merge Main, Rebase Features
This is the most common and practical approach:
- Developers rebase their feature branches onto main before creating a PR
- Feature branches are merged into main with a merge commit (
--no-ff) - Main branch shows a clear sequence of merged features
# Developer workflow
git checkout feature-x
git rebase main # Clean up before PR
git push --force-with-lease
# After review, merge with merge commit
git checkout main
git merge --no-ff feature-x
For Small Teams: Squash and Merge
GitHub and GitLab offer "Squash and Merge" which combines all feature branch commits into a single commit on main:
# Equivalent to:
git checkout main
git merge --squash feature-x
git commit -m "Add feature X"
This produces the cleanest main branch history but loses individual commit granularity.
For Solo Projects: Rebase Everything
If you are the only contributor, rebase freely. A linear history is easier to read and git bisect works better with it.
Quick Decision Guide
Use merge when:
- Integrating completed feature branches into main
- Working on a shared branch with other developers
- You need to preserve the complete history
- You want to avoid rewriting commits
Use rebase when:
- Keeping your feature branch up to date with main
- Cleaning up messy local commits before a PR
- You want a linear, readable history
- You are the only person working on the branch
Key Takeaways
- Merge preserves history as it happened; rebase rewrites it for clarity
- Never rebase commits that others have pulled
- Use
--force-with-leaseinstead of--forcewhen pushing rebased branches - Enable
rerereto avoid re-resolving the same conflicts - Most teams benefit from rebasing feature branches and merging to main
Sources
Looking for more? Check out Adaptels.
Related Articles
How to Debug Node.js Memory Leaks (Step-by-Step Guide)
Learn how to detect, diagnose, and fix Node.js memory leaks using heap snapshots, Chrome DevTools, and clinic.js — with real code examples.
How to Set Up GitHub Actions for CI/CD (Beginner-Friendly Guide)
Learn how to set up GitHub Actions for CI/CD pipelines — from your first workflow file to automated deployments with real YAML examples.
Building an AI Chatbot With LangChain: Practical Developer Guide
Build a production-ready AI chatbot with LangChain, Python, and OpenAI. Step-by-step guide with memory, RAG, streaming, and deployment tips.