Skip to content

Merge vs Rebase: When and How to Use Each in Git

DodaTech Updated 2026-06-22 5 min read

In this tutorial, you'll learn about Merge vs Rebase: When and How to Use Each in Git. We cover key concepts, practical examples, and best practices.

Git merge and rebase both combine work from different branches but produce different history graphs — merge preserves chronology while rebase rewrites it.

In this tutorial, you'll learn the critical differences between Git merge and rebase — two commands that integrate changes from one branch into another. Choosing merge vs rebase shapes your commit history, affects collaboration, and can make the difference between a readable project log and an incomprehensible tangle. By the end, you'll know exactly when to use each and how to avoid the common pitfalls that trip up even experienced developers.

flowchart LR
  subgraph Before
    A[main: A] --> B[main: B]
    A --> C[feature: C]
    C --> D[feature: D]
  end
  subgraph After Merge
    B --> E[Merge Commit]
    D --> E
  end
  subgraph After Rebase
    B --> C2[C']
    C2 --> D2[D']
  end

How Git Merge Works

Merge creates a special merge commit that has two parent commits. It preserves the exact timeline of both branches. This is the safest option for shared branches because it never rewrites history.

# Setup: two branches with diverging work
git checkout -b feature/payments main
echo "payment code" > payment.py
git add payment.py
git commit -m "Add payment processing"

git checkout main
echo "hotfix" >}} README.md
git add README.md
git commit -m "Fix critical typo"

# Merge feature into main
git merge feature/payments

Expected output:

Merge made by the 'ort' strategy.
 payment.py | 1 +
 1 file changed, 1 insertion(+)

The commit graph now shows a three-way join. The merge commit documents exactly when the integration happened.

How Git Rebase Works

Rebase rewrites your feature branch commits on top of the target branch's current tip. Instead of a merge commit, your commits appear as if they were written on top of the latest code.

git checkout feature/payments
git rebase main

Expected output:

Successfully rebased and updated refs/heads/feature/payments.

Your commits are reapplied one by one. If conflicts occur during rebase, Git pauses at each conflicting commit.

Resolving Conflicts During Rebase

When git rebase main encounters a conflict:

# Git pauses; fix the conflicting files
git add resolved_file.py
git rebase --continue
# Or skip this commit: git rebase --skip
# Or abort entirely: git rebase --abort

Expected output:

Applying: Add payment processing
Applying: Add payment validation

Merge vs Rebase Comparison

Aspect Merge Rebase
History Preserves exact chronology Linearizes history
Merge commits Creates one None
Safety Safe for shared branches Rewrites history — dangerous for shared
Conflict resolution One-time at merge Per-commit during rebase
Traceability Clear when integration happened Cleaner log, less detail
CI/CD impact Triggers once Triggers on each rebased commit
Team convention Standard for public branches Used for private feature branches

The Golden Rule

Never rebase commits that have been pushed to a shared branch. Once you push a branch and others pull it, rebasing creates divergent histories. Your teammates will see duplicate commits and Git will refuse to pull cleanly.

Common Errors

Error Cause Fix
merge conflict during rebase Conflicting changes on both branches Fix each commit's conflict, git rebase --continue
fatal: refusing to merge unrelated histories Two repos with no common ancestor Use --allow-unrelated-histories
There is no tracking information Branch not linked to remote Set upstream with git branch -u
Divergent history after push Rebased a shared branch Use git push --force-with-lease (with caution)
Already up to date Nothing new on target branch Check branch names
Lost commits after rebase Accidentally skipped or aborted Use git reflog to recover
Merge commit in rebased branch Rebase stopped mid-way git rebase --abort and retry
CONFLICT (content) repeated Many commits with same conflict Squash commits first with git rebase -i

Interactive Rebase for Clean History

Use interactive rebase to squash, reorder, or edit commits:

git rebase -i HEAD~3

An editor opens showing the last three commits. Change pick to squash to combine commits, reword to rename, or edit to split.

Practice Questions

When should I use merge instead of rebase?

Use merge when integrating a feature branch into a shared branch like main or develop. Merge preserves history and is safe for branches that other team members have pulled. Use rebase for cleaning up local commits before pushing a feature branch.

Does rebase lose commits?

Rebase does not lose commits if done correctly. It rewrites commit objects with new parent references. The original commits remain in the reflog for 90 days. If a rebase goes wrong, use git reflog to find the original commits and reset.

What is the difference between git rebase and git merge --ff-only?

git merge --ff-only only merges if a fast-forward is possible (no divergent work). It does not create a merge commit. Rebase rewrites commits to appear sequential. With --ff-only, your branch tip just moves forward; with rebase, your commits are recreated with new hashes.

What is --force-with-lease?

git push --force-with-lease is a safer alternative to --force. It checks that your remote-tracking branch matches the remote before overwriting. This prevents accidentally overwriting someone else's pushes. Always use --force-with-lease instead of --force.

Can I undo a merge?

Yes. If the merge hasn't been pushed, use git reset --hard ORIG_HEAD or git reset --hard HEAD~1. If it's been pushed, use git revert -m 1 HEAD to create a revert commit that undoes the merge

Challenge

Create a repository with three commits on main. Branch off, add two commits. Switch back to main and add one commit. First, merge the branch and note the graph. Reset to before the merge. Now rebase the branch onto main and note how the graph changes. Compare the two histories using git log --graph --oneline. Write the full command sequence.

Real-World Task

In a team repository, you have a feature branch with six messy commits (typo fixes, debug statements, partial work). Use interactive rebase to squash them into two logical commits: "Add feature implementation" and "Add tests for feature". Then rebase onto the latest main and push. This cleanup workflow is standard at DodaTech for tools like DodaZIP where clean history helps Kubernetes-based deployments track which changes caused issues.


Built by the developers of Doda Browser, DodaZIP, and Durga Antivirus Pro.

Built by the developers of DodaTech

Doda Browser, DodaZIP & Durga Antivirus Pro