Skip to content

Merge Strategies

One-liner

Git offers multiple merge strategies — algorithms that determine how two branches are combined and conflicts resolved.

Why it matters

The default merge works 80% of the time, but using the wrong strategy can lead to silent data loss, unnecessary conflicts, or history nobody can follow. Knowing which strategy to apply in each scenario gives you precise control over how code is integrated.

Core concept

Think of merging as combining two recipe books that started from the same original. If both books changed different recipes, combination is trivial. If both changed the same recipe differently, you need a strategy: take book A's version, take book B's, blend them manually, or declare one book the authority. Git merge strategies are these different resolution policies — each optimized for a specific situation.

The most common strategy (recursive/ort) performs three-way merge using the common ancestor as a reference. But several alternatives exist for special cases.

How it works

  1. Find common ancestor — git identifies the merge base (last commit both branches share).
  2. Select strategy — by default, git uses ort (or recursive in older versions); you can override with -s <strategy>.
  3. Three-way comparison — for each file, git compares: ancestor vs ours, ancestor vs theirs.
  4. Auto-resolve — changes that don't overlap are merged automatically.
  5. Conflict — overlapping changes require manual resolution or strategy options (-X ours/-X theirs) to break ties.

Key terms

  • ort/recursive — default strategy; handles most cases including criss-cross merges with multiple ancestors
  • fast-forward — not a strategy per se; git moves the pointer when no divergence exists. --no-ff forces a merge commit anyway
  • ours (-s ours) — discards all changes from the other branch; useful for retiring dead branches
  • -X ours / -X theirs — strategy options (not strategies); only apply to conflicting hunks, not the entire merge
  • octopus — merges more than two branches at once; only works if there are no conflicts
  • subtree — merges another project into a subdirectory; alternative to submodules

Common misconceptions

  • "-s ours and -X ours are the same" — -s ours discards everything from their side. -X ours only uses our version for conflicting hunks; non-conflicting changes from their side are still merged.
  • "Fast-forward is always best" — Fast-forward loses the grouping information. --no-ff creates a merge commit that records when a feature was integrated, making revert trivial.
  • "Merge always creates a merge commit" — Only when branches have diverged. If the target hasn't moved, git fast-forwards by default.

When to use / not use

✓ Use when: integrating a completed feature (use --no-ff), accepting all upstream changes on conflict (-X theirs), retiring a superseded branch (-s ours), or combining multiple independent features (octopus).

✗ Don't use when: you want linear history (use rebase instead), you need to rewrite/clean up commits before integration (use interactive rebase), or the merge would be a no-op fast-forward and you want to keep history minimal.

Example

# Standard feature merge with merge commit
git merge --no-ff feature/auth

# Accept their changes on all conflicts
git merge -X theirs origin/main

# Merge three independent branches at once
git merge feature/logging feature/metrics feature/health

Next steps

  1. Practice the distinction between -s ours (strategy) and -X ours (option) on a test branch
  2. Learn git rerere to auto-resolve repeated conflicts across merges and rebases
  3. Explore git merge --squash for integrating a branch as a single commit without merge commit structure