Sooner or later, every developer who uses Git faces the same question: you finished work on a branch, the main branch moved forward in the meantime, and now you need to bring everything together. Should you use git merge or git rebase? Both commands integrate changes from one branch into another, but they do it in very different ways, and choosing the wrong one at the wrong time can cause confusion for your whole team.
This guide explains, step by step, what each command does to your history, the advantages and risks of each, and practical rules to decide which one to use.
The starting scenario
Imagine you created a branch called feature from main. You made two commits on feature. Meanwhile, a teammate added two commits to main. The two branches now share a common ancestor but have diverged:
A---B feature
/
C---D---E---F main
Commit D is the common ancestor. Your goal is to combine A and B with E and F. Merge and rebase offer two different paths.
How git merge works
When you run git merge, Git looks at the two branch tips and their common ancestor, combines the changes and creates a new commit that has two parents. This is called a merge commit.
git checkout main git merge feature
The resulting history looks like this, where M is the merge commit:
A---B
/ \
C---D---E---F---M main
Key points about merging:
- It preserves history exactly as it happened. Existing commits are not changed; their identifiers (hashes) stay the same.
- It is non-destructive. Because nothing is rewritten, it is safe to use on branches that other people are also working on.
- It can make history busier. In active projects, many merge commits can make the log harder to read.
There is a special case called a fast-forward merge. If main had not received new commits since you created your branch, Git can simply move the main pointer forward to B, without creating a merge commit. You can force a merge commit anyway with git merge --no-ff, which some teams prefer so that every feature is clearly grouped in the history.
How git rebase works
Rebasing takes a different approach. Instead of tying the two histories together, it moves your branch so that it starts from the latest commit on the other branch. Technically, Git takes each of your commits, calculates the changes they introduced, and reapplies them one by one on top of the new base.
git checkout feature git rebase main
The result:
A'--B' feature
/
C---D---E---F main
Notice the apostrophes: A’ and B’ are new commits. They contain the same changes as A and B, but they have different parents and therefore different hashes. After the rebase, main can be fast-forwarded to B’, producing a perfectly linear history with no merge commit.
Key points about rebasing:
- It creates a clean, linear history that is easy to read with
git log. - It rewrites commits. The original A and B are replaced by A’ and B’.
- Conflicts are resolved commit by commit. If several of your commits touch the same lines that changed on
main, you may need to resolve conflicts more than once.
Side-by-side comparison
| Aspect | git merge | git rebase |
|---|---|---|
| History shape | Branching, shows when work was integrated | Linear, as if work happened in sequence |
| Existing commits | Unchanged | Rewritten with new hashes |
| Extra commit | Usually a merge commit | No merge commit |
| Conflict resolution | Once, in the merge commit | Possibly once per replayed commit |
| Safe on shared branches | Yes | No, unless the whole team coordinates |
| Undo | Revert the merge commit | Use the reflog to find the old commits |
The golden rule of rebasing
The most important rule is simple: do not rebase commits that other people have already based work on, typically anything already pushed to a shared branch such as main.
Why? Because a rebase replaces commits with new ones. If a teammate already has the old commits, their history and yours now disagree. When they pull, Git sees two different versions of the same work, which leads to duplicated commits and confusing conflicts. To publish a rebased branch you would also need a force push (git push --force), which overwrites the remote history.
If you must force push a branch you own, prefer git push --force-with-lease. It refuses to overwrite the remote branch if someone else has pushed to it since your last fetch, adding a layer of protection.
When to use merge
- Integrating a finished feature branch into
mainor another shared branch. - Working on a branch that several people push to.
- When your team wants the history to record exactly when and how branches came together.
- When you are new to Git and want the safest option.
When to use rebase
- Updating your local, private feature branch with the latest changes from
mainbefore opening a pull request. - Cleaning up your own commits before sharing them, using interactive rebase (
git rebase -i) to reorder, squash or reword commits. - When your team prefers a linear project history.
- Pulling with
git pull --rebaseto avoid unnecessary merge commits when your local commits have not been shared yet.
Handling conflicts in each case
Conflicts happen in both approaches when the same lines were changed differently. The workflow is similar but not identical:
- During a merge: fix the conflicting files, run
git addon them and finish withgit commit. To give up, usegit merge --abort. - During a rebase: fix the files, run
git add, thengit rebase --continueto move to the next commit. You can skip a commit withgit rebase --skipor cancel everything withgit rebase --abort, returning the branch to its original state.
A practical workflow many teams use
- Create a feature branch from
main. - Commit freely while you work.
- Before opening a pull request, rebase your branch on the latest
mainand, if helpful, tidy up your commits with an interactive rebase. - Open the pull request and get it reviewed.
- Integrate it into
mainusing the method your team agreed on: a merge commit, a squash merge or a rebase merge, all of which are common options on code hosting platforms.
The best choice often depends less on technical superiority and more on team agreement. What matters is that everyone follows the same convention.
Conclusion
Merge and rebase solve the same problem with different philosophies. Merge keeps a faithful record of what happened and is safe on shared branches. Rebase rewrites your commits to produce a clean, linear story and is ideal for polishing private work before sharing it. Remember the golden rule, never rebase public history, and you will be able to use both tools with confidence.
If you want to strengthen your version control skills, Cursa offers free online courses on Git, GitHub and other developer tools, with certificates, so you can practice these workflows at your own pace.























