You've finished a feature branch and you're ready to bring it back into main. Git gives you two completely different ways to do this, merge and rebase, and most tutorials mention both without ever explaining why you'd pick one over the other, or what actually happens to your commit history either way.
The short version: both end with your changes in main. What differs is the shape of the history left behind, and that shape matters more than most beginners realize once a project has more than one contributor.
Welcome to BytebaseX. I'm Suptojit Modak, and in this guide, I'll show exactly what each command does to your commit graph, when rebase is genuinely the better choice, and the one rule that keeps rebase from turning into a disaster on a shared branch.
What Merge Actually Does
If you're still getting comfortable with branches themselves, our beginner's guide to Git branching covers that first. Assuming you've got a feature branch ready to bring into main:
git switch main
git merge feature-login
Merge takes all the commits from feature-login and combines them into main by creating a new commit, called a merge commit, that has two parents: the last commit on main, and the last commit on your feature branch. Nothing on either branch gets rewritten. Both histories stay exactly as they happened, and the merge commit is just a new point where they join back together.
Merge preserves history exactly as it happened, including every side branch, every small "fix typo" commit, and the literal order things occurred in. Nothing is rewritten, ever.
What Rebase Actually Does
Rebase takes a completely different approach:
git switch feature-login
git rebase main
Instead of creating a merge commit, rebase takes every commit on feature-login, temporarily sets them aside, moves your branch to start from the current tip of main, and then replays each of your commits one by one on top of that new starting point. The end result looks like you built your entire feature branch starting from today's main, even if you actually started it a week ago.
A Live Demo: Watching the Two Histories Diverge
Click each button to see what the commit graph looks like after merging versus rebasing the exact same feature branch onto main.
The One Rule That Matters More Than Any Command
This is the single most important thing in this entire guide: never rebase a branch that other people are already working on or have already pulled.
Since rebase creates brand new commits with new hashes, anyone else who already has the old commits now has a history that's diverged from yours in a way Git can't cleanly reconcile. Their next pull turns into a confusing mess of duplicate-looking commits, or a forced push fight. This is why the common guidance is: rebase your own local, not-yet-shared branches freely, but merge (never rebase) once a branch is shared or is something like main that other people build on.
git push --force. Use git push --force-with-lease instead, which refuses to overwrite commits you haven't seen yet, covered in more detail in our guide on undoing Git mistakes.Interactive Rebase: Cleaning Up Before You Share
Beyond just moving commits, rebase has an interactive mode that's genuinely useful even on branches you're about to merge:
git rebase -i HEAD~4
This opens an editor listing your last 4 commits, each with the word pick next to it. You can reorder lines, change pick to squash to combine a commit into the one before it, or reword to edit just the commit message without touching the code:
pick a1b2c3d Add login form
squash e4f5g6h Fix typo in login form
squash i7j8k9l Fix another typo
reword m1n2o3p Add login validation
This turns four small, messy "work in progress" commits into one clean commit with a proper message, before anyone else ever sees your branch. This is genuinely one of the best uses of rebase: cleaning up your own local mess before it becomes permanent shared history.
Handling a Rebase Conflict
Rebase conflicts feel different from merge conflicts because they can happen more than once, once per commit being replayed that touches a conflicting line. When it happens, Git pauses and shows you the conflict markers, the same format covered in the branching guide. Fix the file, then:
git add resolved-file.js
git rebase --continue
If it's turning into more trouble than it's worth partway through, bail out completely and go back to exactly how things were before you started:
git rebase --abort
When to Actually Use Which
| Situation | Use |
|---|---|
| Bringing a finished feature branch into main | Merge (safe default, especially in a team) |
| Cleaning up your own messy commits before opening a pull request | Interactive rebase |
| Keeping your local feature branch up to date with main while you work | Rebase (on your own unshared branch only) |
| A branch other people have already pulled or are also committing to | Merge, never rebase |
| You want to preserve the exact record of when things happened | Merge |
| You want a clean, linear history that reads like it was written in order | Rebase |
Frequently Asked Questions
Does rebase lose any of my work?
No, as long as it completes without you force-discarding it. Your changes are preserved, just recreated as new commits with new hashes on top of the new base. If a rebase goes badly, the original commits are still recoverable through the reflog for a while, the same recovery method covered in our guide on undoing Git mistakes.
Why do some teams ban rebase entirely?
Usually because someone rebased a shared branch once and it caused real confusion for the whole team. Rather than trust everyone to remember the "never rebase shared branches" rule, some teams simplify things by just banning rebase entirely and using merge everywhere. It's a reasonable, if blunt, way to avoid the mistake.
What does "squash merging" on GitHub or GitLab actually do?
It's a hybrid approach available on most Git hosting platforms: all the commits in a pull request get combined into a single new commit on the target branch, similar to squash from interactive rebase, but done as part of the merge action rather than requiring you to rebase manually first. It keeps main's history clean without anyone needing to rebase their own branch.
Can I rebase onto something other than main?
Yes. git rebase works against any branch or commit reference, not just main. Rebasing onto a shared feature branch that a few teammates are building on together follows the exact same risk rule: fine if nobody else has pulled the commits you're about to rewrite, risky if they have.
Is rebase harder to learn than merge?
The commands themselves aren't more complex, but rebase requires understanding that commit hashes change, which merge never does. That one conceptual difference is what causes most rebase confusion, not the commands. Once that clicks, the actual mechanics are no harder than merge.
Conclusion
Merge preserves exactly what happened, including the messy parts. Rebase rewrites your branch's story to look cleaner than it actually was. Neither is "correct" in general, they're different tools for different priorities: choose merge when history should stay exactly as it happened or when a branch is shared, and reach for interactive rebase to clean up your own commits before anyone else sees them. The one rule that actually matters, more than any command syntax, is simple: rebase your own unshared work freely, and merge everything that's already shared with someone else.