Git Merge vs Rebase: When to Use Each

Tested on RHEL 10.2 (Coughlan)
Package git 2.52.0
Applies to Any host with Git installed
Privilege Normal user
Scope Compare merge and rebase on the same diverged branch split, read the resulting history graph, choose merge vs rebase vs fast-forward, and contrast git pull with merge vs git pull --rebase. Not a full merge-conflict or interactive rebase tutorial.
Related guides Git merge examples
Git rebase tutorial
Git pull command examples
Git branch examples
Git workflow

git merge and git rebase both bring work from one branch into another — but they change history differently. Merge keeps the branch split visible and adds a merge commit when branches diverged. Rebase replays your commits on top of a newer base so the log reads like a straight line.

Four decisions this article covers:

  • read the same branch split after merge vs after rebase;
  • pick merge, rebase, or fast-forward for your situation;
  • integrate a feature branch with merge or rebase-then-merge;
  • choose git pull vs git pull --rebase when origin moved.

Pick your question in the table below, then jump to that section.


Merge vs Rebase at a Glance

Assume main gained commit E while feature added C and D from the older tip:

text
Before integration:

A---B---E  main
     \
      C---D  feature
Merge on main Rebase feature onto main
History Both lines stay visible; merge commit joins them C and D become new commits after E
Commit hashes Existing commits unchanged Replayed commits get new hashes
Best for Shared branches, release merges, preserving branch topology Private feature branch cleanup before merge
Risk on shared branches Low — no rewrite High — others may have based work on old hashes

For command-level merge and rebase walkthroughs, see Git merge examples and Git rebase tutorial.


Choose Merge or Rebase

Your situation Prefer
Integrate a shared or release branch git merge
Refresh a local feature branch before opening a PR git rebase main on the feature branch
main has not diverged — feature is a straight extension Fast-forward merge (still a merge, no merge commit)
You already pushed the feature branch only you use Rebase, then force-with-lease push — see Git rebase tutorial
Teammates based work on your branch commits Merge — do not rebase those commits
Pull when origin moved and you have local commits Team policy: git pull --no-rebase or git pull --rebase

Neither command is universally better. The choice is whether you need preserved branch structure or a linear log — and whether rewriting commits would break someone else's clone.


Same Split, Merge Result

Scenario: main and feature both moved forward from B. You are on main and want feature's work integrated.

Merge combines the branches and records how they joined:

bash
git merge feature
output
Merge made by the 'ort' strategy.
 c.txt | 1 +
 d.txt | 1 +
 2 files changed, 2 insertions(+)
 create mode 100644 c.txt
 create mode 100644 d.txt

The graph shows both lines plus a merge commit at the tip of main:

bash
git log --oneline --graph --decorate -6
output
*   be32cd9 (HEAD -> main) Merge branch 'feature'
|\  
| * 9cc8f96 (feature) D
| * cbec3c8 C
* | d88184e E
|/  
* fddf8fe B
* 4a96b36 A

The merge commit (be32cd9) is the integration point. Every original commit hash is still there — useful when you need to see exactly when feature diverged and merged.


Same Split, Rebase Result

Scenario: the same starting split, but you want feature replayed on top of today's main before merging.

Switch to the feature branch and rebase onto main:

bash
git switch feature

Replay the feature commits on top of the current main tip:

bash
git rebase main
output
Rebasing (1/2)
Rebasing (2/2)
Successfully rebased and updated refs/heads/feature.

The feature branch now looks linear — new commits sit after E:

bash
git log --oneline --graph --decorate -6
output
* 9dca12e (HEAD -> feature) D
* e9ac229 C
* d88184e (main) E
* fddf8fe B
* 4a96b36 A

main itself did not move during the rebase. Commits A, B, and E keep the same hashes — only the replayed feature commits changed (cbec3c8/9cc8f96 became e9ac229/9dca12e). From here many teams fast-forward main to feature or open a merge request with a single-line history.


Fast-Forward Merge

Scenario: feature branched from main, main did not gain new commits, and you merge feature into main.

When main is a direct ancestor of feature, Git can move the pointer without a merge commit:

bash
git merge feature
output
Updating 93dd446..b374167
Fast-forward
 c.txt | 1 +
 1 file changed, 1 insertion(+)
 create mode 100644 c.txt

Confirm the pointer moved with no merge commit in the graph:

bash
git log --oneline --graph --decorate -4
output
* b374167 (HEAD -> main, feature) C
* 93dd446 B
* 27df931 A

No merge commit appears — main simply catches up to feature. A rebase onto an unchanged main would also look linear, but fast-forward merge does not rewrite commit hashes.


Integrate a Feature Branch

Two common team patterns after main moved while you worked on feature.

Merge workflow — one merge commit on main, full branch visible:

bash
git switch main

Bring feature into main with a merge commit:

bash
git merge feature

Rebase-then-integrate workflow — linear feature history first, then bring it into main:

bash
git switch feature

Replay feature onto the latest main:

bash
git rebase main

Return to main once the rebase finishes:

bash
git switch main

Integrate the rebased feature — often a fast-forward:

bash
git merge feature

After a successful rebase, that final merge is often a fast-forward. The difference is whether intermediate history shows the old branch split (merge-only) or a straight line (rebase first). For conflict handling during either path, see Git merge examples and Git rebase tutorial.


git pull With Merge vs --rebase

Scenario: you have a local commit, origin/main moved, and you need to integrate the fetched updates.

git pull --no-rebase tells Git to integrate the fetched branch with a merge — when histories diverged, that produces a merge commit:

bash
git pull --no-rebase
output
Merge made by the 'ort' strategy.
 remote.txt | 1 +
 1 file changed, 1 insertion(+)
 create mode 100644 remote.txt

The merge pull leaves a join commit in the graph:

bash
git log --oneline --graph --decorate -5
output
*   ac6a640 (HEAD -> main) Merge branch 'main' of origin
|\  
| * 5c741c7 (origin/main) Remote commit on origin
* | 3a46547 Local commit before pull
|/  
* be2104a Shared base on origin

git pull --rebase replays your local commits on top of the fetched tip instead:

bash
git pull --rebase
output
Rebasing (1/1)
Successfully rebased and updated refs/heads/main.

After rebase pull, the log is linear with your local commit on top:

bash
git log --oneline --graph --decorate -5
output
* a227dbb (HEAD -> main) Local commit before pull
* 147691f (origin/main) Remote commit on origin
* 61920a1 Shared base on origin

Short status after rebase pull shows one commit ahead — no merge commit:

bash
git status -sb
output
## main...origin/main [ahead 1]

You can configure pull.rebase true if your team prefers rebase-based pulls, or use git pull --no-rebase when you explicitly want merge-based integration. Match your team's policy before rebasing commits others might already have.


When Not to Rebase

Rebase rewrites commits. Avoid it when:

  • others already pulled the commits you would replay;
  • the commits are on a shared integration branch and others may already have based work on them;
  • you are unsure whether anyone based work on your SHAs.

Merge is the safer default for those cases because it adds a merge commit without changing existing hashes. If you already rebased a pushed branch by mistake, recovery starts with git reflog — see Git reflog tutorial.

git reset is a different tool entirely — it moves a branch pointer rather than replaying commits. See Git reset examples when you need to undo local commits, not integrate branches.


Troubleshooting

Symptom Likely cause Fix
git rebase stops with conflicts Diverged changes in the same lines Fix files, git add, git rebase --continue — or git rebase --abort
Teammate's branch breaks after your push You rebased commits they already had Avoid rebasing shared history; coordinate force-with-lease only on private branches
History looks tangled after many merges Normal merge workflow on busy main Expected with merge; use rebase on local features before integrating if team allows
Expected fast-forward but got merge commit main diverged from feature A fast-forward is no longer possible because both branches contain unique commits. Merge them as-is, or rebase feature onto main first if your workflow requires linear history
git pull --no-rebase created a merge commit you did not want Pull was configured or requested to merge Use git pull --rebase if team policy allows
Merge or rebase stopped and you are not sure which operation is active An unfinished merge or rebase is still open Run git status; Git reports whether a merge or rebase is currently in progress — see unmerged files pull error

References


Summary

git merge and git rebase solve the same problem — bringing branch work together — with different history shapes. On a diverged split, merge keeps both lines and adds a merge commit; rebase replays your commits after the newer base with new hashes.

Fast-forward merge is the simple case where main can move forward without a merge commit. Many feature workflows rebase onto main first for a linear log, then merge or fast-forward into main. When local and remote diverged, git pull --no-rebase integrates with a merge commit; git pull --rebase replays your local commits on top of the fetched tip instead.

Choose merge when the branch timeline must stay intact or the branch is shared. Choose rebase on local feature work you have not shared — or when your team standardizes on rebase pulls — and avoid rewriting commits others already built on. Step-by-step merge and rebase commands live in Git merge examples and Git rebase tutorial.


Frequently Asked Questions

1. What is the difference between git merge and git rebase?

git merge combines branches and usually keeps both histories visible in the log. git rebase replays your branch commits on top of another tip, rewriting their hashes for a straighter line.

2. When should I use git merge vs git rebase?

Use merge on shared branches and when you want the exact branch timeline preserved. Use rebase on a local feature branch to refresh it against main before you merge or open a pull request.

3. Is git rebase dangerous?

Rebase is safest for commits you have not shared, or on a private branch that only you use. If you rebase commits already pushed, the rewritten branch normally requires a force push.

4. What is fast-forward merge vs rebase?

A fast-forward merge simply moves the branch forward without changing commit hashes. Rebase normally creates new commits when it must replay your work onto a different base.

5. Can I use git rebase instead of merge?

On a local feature branch, you can rebase onto main, then switch to main and merge the rebased feature branch, often as a fast-forward. Do not use rebase as a drop-in replacement for merging shared integration branches.

6. Does git merge rewrite history?

No. git merge does not rewrite existing commits. When branches have diverged, it normally creates a merge commit; when a fast-forward is possible, it simply moves the branch forward without creating one.

7. Should beginners use git merge or rebase?

Start with merge until branch history and git log --graph make sense. Add rebase on private feature branches once you understand that it rewrites commits you have not shared yet.
Deepak Prasad

R&D Engineer

Founder of GoLinuxCloud with more than 15 years of expertise in Linux, Python, Go, Laravel, DevOps, Kubernetes, Git, Shell scripting, OpenShift, AWS, Networking, and Security. With extensive experience, he excels across development, DevOps, networking, and security, delivering robust and efficient solutions for diverse projects.

  • Go (programming language)
  • Python (programming language)
  • DevOps
  • Computer Security
  • Cloud Computing
  • Kubernetes
  • Linux
  • Ansible (software)