Git merge vs git rebase is the foundational workflow decision in version control: preserve the exact chronological history with merge commits or rewrite commit history into a clean, linear timeline.
Starting State:
main: A ──► B ──► C
│
feature: └──► D ──► E
Result of git merge main:
main: A ──► B ──► C ────────────┐
│ ▼
feature: └──► D ──► E ──► M (Merge commit)
Result of git rebase main:
main: A ──► B ──► C
└──► D' ──► E' (Linear replay, new SHAs)
New to this → start with Merge vs Rebase side-by-side. Interactive squashing → Interactive rebase guide. Branch management → Checkout remote branches. Interview prep → If an interviewer asks.
Real-world analogy
- Git Merge: Two highway lanes converging at a toll booth. You can clearly see where your road joined the main highway, and the toll booth ticket (
Merge Commit) records the exact timestamp when the two roads merged. - Git Rebase: Moving your highway on-ramp 5 miles further down the interstate. It looks like you entered the highway after the latest construction project was already completed, creating a smooth, straight driving line.
Rebasing your personal car's route is fine. Demolishing and moving the public interstate on-ramp while other drivers are currently driving on it is the disaster of rebasing a shared public branch.
Merge vs Rebase side-by-side
| Aspect | git merge | git rebase |
|---|---|---|
| History Style | Non-linear with diamond graphs & merge commits | Purely linear, chronological commit log |
| Commit SHAs | Original commit SHAs are preserved intact | New commit SHAs generated for all replayed commits |
| Conflict Resolution | Resolved once inside the resulting merge commit | Resolved per commit as each commit is replayed |
| Safe for Shared Branches | Yes (Never corrupts teammates' histories) | No (Violates the Golden Rule of Rebasing) |
| Bisect & Debugging | Complex due to criss-cross merge commits | Extremely fast and clean with git bisect |
When to use git merge
Use git merge when:
- Merging a completed, approved feature branch into
mainordevelop. - Working on a collaborative feature branch shared between multiple engineers.
- Your team prioritizes preserving the exact historical truth of when features branched off.
# Merging main into your feature branch to pull latest changes:
git switch feature/payments
git fetch origin
git merge origin/main
git push origin feature/payments
When to use git rebase
Use git rebase when:
- Pulling the latest changes from
maininto your private, local feature branch before opening a PR. - Cleaning up "WIP", "fix typo", or "debug test" commits into meaningful units using interactive rebase.
- Maintaining a clean, linear git history that makes
git log --onelineeasy to read in production audits.
# Rebasing your local feature branch on top of main:
git switch feature/payments
git fetch origin
git rebase origin/main
# Push updated rebased commits to your remote branch:
git push --force-with-lease origin feature/payments
Interactive Rebasing: cleaning commits before PR
Before requesting a senior engineer review your pull request, condense your messy local commit history using interactive rebase:
# Rebase the last 4 commits on your current branch
git rebase -i HEAD~4
Git opens an editor with options:
pick e4a19b2 Add payment DTOs and validation
squash 9f1b3c4 Fix typo in validation attribute
squash 3a4c5e6 Fix unit test failure
pick 7d8e9f0 Add Stripe gateway integration
Common interactive commands:
pick: Use commit as-is.reword: Change the commit message.squash(ors): Melds the commit into the previous commit and prompts for a combined message.fixup(orf): Melds into previous commit and discards this commit's log message.drop(ord): Deletes the commit entirely.
Resolving conflicts during a rebase
If a rebase encounters a merge conflict:
# 1. Check which files have conflict markers
git status
# 2. Edit the conflicting files and resolve markers (<<<<<<< HEAD)
# 3. Stage the resolved files:
git add src/Services/PaymentService.cs
# 4. Continue the rebase (do NOT run git commit!):
git rebase --continue
# If the rebase gets stuck or you want to start over:
git rebase --abort
GitHub Pull Request Merge Strategies
When clicking "Merge" on GitHub/GitLab, understanding the 3 strategies aligns with team culture:
- Create a Merge Commit (
--no-ff): Preserves all individual feature commits plus a merge commit. Ideal for large enterprise releases. - Squash and Merge: Condenses all 15 commits in the PR into a single clean commit on
main. Great for small bug fixes and fast-moving teams. - Rebase and Merge: Replays PR commits directly onto
mainwith fast-forward. Retains individual commits while keepingmainstrictly linear.
Common mistakes and pitfalls
- Running
git push --forceinstead of--force-with-lease: If a teammate pushed a commit to your branch while you were rebasing,--forcewill delete their work forever.--force-with-leaseaborts if the remote was updated. - Rebasing
mainonto a feature branch: Never rungit switch main && git rebase feature. Always rebase the feature branch ontomain. - Committing during conflict resolution: When fixing rebase conflicts, run
git add <file>followed bygit rebase --continue. Runninggit commitcreates an unintended extra commit that interrupts the rebase sequence.
If an interviewer asks
30-second answer: git merge joins two branches by creating a merge commit, preserving the exact historical branching graph. git rebase lifts and replays your branch's commits on top of the target branch, producing a clean, linear history. We use rebase on local feature branches before opening PRs, but never rebase shared public branches.
Strong answer: In production enterprise environments, the choice between merge and rebase is governed by the Golden Rule of Rebasing: only rewrite private, unshared history. We leverage git rebase -i to clean up messy local WIP commits before code review, and always use git push --force-with-lease to guard against overwriting teammates' remote pushes. On trunk (main), we configure GitHub branch protection to enforce "Squash and Merge" or "Rebase and Merge" to ensure git log and git bisect remain fast and readable.