Git Rebase vs Merge: 2026 Decision Guide for Engineering Teams
Quick decision: shared branch → merge; your branch only → rebase; cleaning a PR → squash-merge. Below: the full decision tree, recovery commands, and what 10 major tech companies actually do.
Updated April 2026 · Git 2.40+ · Conventional Commits
Quick decision matrix
| Situation | Recommended action | Avoid |
|---|---|---|
| Solo feature branch, not pushed | Rebase freely | — |
| Solo branch, already pushed | Rebase + force-with-lease | --force (without lease) |
| Branch shared with teammates | Merge main into feature | Rebase (will break their work) |
| PR with messy WIP commits | Squash-and-merge to main | Plain merge with 47 commits |
| PR with thoughtful atomic commits | Rebase-and-merge (preserve commits) | Squash (loses your work) |
| Long-lived OSS project | Merge with explicit merge commits | Squash (loses contributor history) |
| Botched rebase, want to undo | git reflog → reset --hard HEAD@{N} | Panic + delete branch |
Frequently asked questions
Should I rebase or merge my feature branch?▼
Default decision tree 2026: (1) IS THE BRANCH SHARED with anyone else? If YES → merge (rebasing rewrites history that others have based commits on). (2) IS THE BRANCH ONLY YOURS and not yet pushed? → rebase freely. (3) HAS THE BRANCH BEEN PUSHED but only YOU work on it AND your team allows force-with-lease? → rebase, then `git push --force-with-lease`. (4) DOES YOUR TEAM PROHIBIT REWRITTEN HISTORY ON REMOTE? → merge only. The split among major engineering orgs (2026 surveys): Linear, Vercel, Stripe, Shopify favor squash-and-merge (clean history, atomic feature commits). GitLab, Kubernetes, Linux kernel favor explicit merge commits (preserve full development history). Microsoft, Google internal repos use rebase-and-merge (linear history with individual commits). The "right answer" is your team's policy — disagreement on this is the #1 cause of git workflow conflict, NOT a technical question.
What is the difference between rebase, merge, and squash-merge?▼
MERGE (`git merge feature`): creates a merge commit on main that has TWO parents (main + feature tip). Preserves all commits from feature branch with original SHAs and timestamps. History shows the branching structure. Pros: preserves true history, never rewrites. Cons: history can become messy with many short-lived branches. REBASE (`git rebase main`): replays your feature commits on top of main as if you started from latest main. Each replayed commit gets a NEW SHA. History becomes linear (no merge commits). Pros: clean linear history, easy to read with `git log --oneline`. Cons: rewrites history (dangerous on shared branches), loses chronological accuracy. SQUASH-MERGE (`git merge --squash` or GitHub squash button): combines all feature commits into a single commit on main. Original commits in feature branch remain unchanged but only one commit lands on main. Pros: one commit per PR (cleanest main history), easy revert. Cons: loses commit-level granularity, makes `git bisect` less useful for finding bugs.
When does rebase break things?▼
Top 5 ways rebase causes problems 2026: (1) Rebasing PUSHED commits that others pulled — they will see divergent history and `git pull` may merge their old commits back in. Rule: never rebase commits you have pushed unless you and the team agree. (2) Rebasing a branch with merge commits — destroys the merge structure unless you use `--rebase-merges`. (3) Resolving the same conflict multiple times — rebase replays each commit, so a conflict in commit 3 may need resolving in commit 3, 4, 5, 6 separately. Use `git rerere` to record resolutions. (4) Rebasing inside hooks (pre-commit, pre-push) that fail — leaves you in detached HEAD state. (5) Force-pushing without `--force-with-lease` — can overwrite a teammate's push between your fetch and push. ALWAYS use `git push --force-with-lease` instead of `--force`. The "golden rule of rebase" per the Pro Git book: "Do not rebase commits that exist outside your repository and that people may have based work on."
How do I rebase safely on a shared branch?▼
Three safe patterns 2026: PATTERN 1 — Solo rebase: only YOU commit to feature branch. Run `git fetch origin && git rebase origin/main`, resolve conflicts, then `git push --force-with-lease`. Safe because no one else pushed in between. PATTERN 2 — Coordinated rebase: tell teammates "rebasing now, hold pushes for 5 min." Run rebase, force-with-lease push, announce done. Teammates run `git fetch && git reset --hard origin/feature-branch` (DESTROYS local work — ensure they have backed up). PATTERN 3 — Never rebase, always merge: when in doubt, do `git merge main` into your feature branch. Creates an "ugly" merge commit in feature history but is safe for everyone. The merge commit gets squashed away anyway when you squash-merge to main. Tools that help: GitHub branch protection rules can require linear history (forces rebase/squash, blocks merge commits). GitLab "Fast-forward merge" setting same effect. CI checks can validate `git log --merges feature..main` is empty before merge.
What is squash-and-merge and when should I use it?▼
Squash-and-merge: takes all commits in a PR/MR and combines them into ONE commit on main. Use it when: (1) Your PR has 50+ "WIP", "fix typo", "address review" commits that have no individual value. (2) You want clean main history where each commit = one feature/fix. (3) You use atomic commits + cherry-picking (one commit per PR makes cherry-pick to release branch trivial). (4) Your team standard is "main always builds" — squashing means each main commit was tested as a unit. AVOID squash when: (1) You crafted thoughtful atomic commits during development that each tell a story. (2) You need granular `git bisect` for debugging (squashed commits hide which sub-change broke things). (3) Your team values full development history. Real-world policies: Vercel/Stripe → squash-merge default (clean main, atomic features). Kubernetes → no squash (preserve all author commits). GitHub itself → mostly squash. The trend in 2024-2026: small startups + product teams choose squash; large open-source projects choose merge or rebase.
How do I undo a botched rebase?▼
Recovery toolkit 2026: (1) `git reflog` shows EVERY position HEAD has been at, even after rebase. Find the commit BEFORE rebase (e.g. `HEAD@{5}`). (2) `git reset --hard HEAD@{5}` returns the branch to pre-rebase state. (3) If you already force-pushed: locally still in reflog, run reset, then `git push --force-with-lease` again to restore remote. (4) If teammates pushed in between: download their work BEFORE resetting (`git fetch && git log origin/branch`), cherry-pick if needed. (5) `git rebase --abort` mid-rebase to cancel. (6) `git rebase --skip` to skip a problematic commit. (7) ORIG_HEAD is automatically set before rebase: `git reset --hard ORIG_HEAD` works in same session. PREVENTION: enable reflog expiration to 90+ days (`git config gc.reflogExpire 90.days.ago`), so reflog survives garbage collection longer. Set up daily auto-fetch cron — your local clone is your safety net. Don't panic — almost every "lost" commit is recoverable from reflog within 30 days.
What does interactive rebase let you do?▼
`git rebase -i HEAD~N` opens an editor with N commits and these actions per commit: PICK (default) — keep commit as-is. REWORD — keep commit but change message. EDIT — pause for amending changes/files. SQUASH — combine into previous commit, keep both messages. FIXUP — combine into previous, discard this message. DROP — delete this commit. EXEC — run shell command between commits (e.g. tests). LABEL/RESET — for advanced reordering. Common workflows: (1) "Clean up before PR": squash WIP commits, reword messages, drop dead-end experiments. (2) "Split a giant commit": EDIT it, `git reset HEAD~`, commit smaller pieces. (3) "Fix old commit": commit fix, `git rebase -i HEAD~5`, mark fix as FIXUP after target. Modern shortcut: `git commit --fixup=<sha>` then `git rebase -i --autosquash HEAD~N` auto-orders fixups. (4) "Reorder commits": rearrange lines in editor. Pro tip: set `git config rebase.autoSquash true` and `git config rebase.autoStash true` for cleaner workflow.
Which git workflow do major tech companies use in 2026?▼
Engineering blog policies (April 2026): VERCEL — squash-and-merge with conventional commits enforced by CI. LINEAR — squash-and-merge, every PR is one commit. STRIPE — squash-merge to main; cherry-pick to release branches. SHOPIFY — squash-merge with mandatory atomic-feature scope. GITLAB (their own product) — fast-forward merges, rebase before merge, no merge commits. GOOGLE (internal "monorepo google3") — submit equivalent to rebase-and-merge, every change is one commit. MICROSOFT (Azure DevOps internal) — squash-merge for product teams, merge-with-history for OSS contributions. KUBERNETES — explicit merge commits, no rebasing master. LINUX KERNEL — pull-based merges with explicit merge commits, signed-off-by trails. RAILS — merge with extensive history. The bimodal distribution: "fast-moving product orgs" pick squash for clean main; "long-lived OSS projects" pick merge for full history. Both are correct for their context — argument is over context, not the technical merits.