Git Merge Strategies: Octopus, Ours, Theirs — Using the Right Strategy to Escape Merge Hell

Git tutorial - IT technology blog
Git tutorial - IT technology blog

The 2 AM Story

Release deadline in the morning. Three teams running in parallel on three different branches. Now you need to merge everything into main before the deploy. You run git merge and get a wall of conflicts longer than your patience.

Reading the docs doesn’t always help in moments like this. What you actually need is to know which strategy to reach for — and more importantly, which one you should never use in a given situation. If you’ve already wrestled with resolving Git merge conflicts manually, you know that having the right approach upfront saves far more time than cleaning up afterward.

On an eight-person team I worked with, once we standardized our Git flow with the right merge strategies, the number of conflicts dropped dramatically. Each release went from a full-afternoon “conflict summit” down to a branch merge wrapped up in 15 minutes.

Comparing Git Merge Strategies

Git isn’t limited to one style of merge. When you run git merge, Git picks an appropriate strategy automatically — but you can override it with the -s (strategy) flag:

git merge -s <strategy> <branch>

The main strategies:

  • recursive — the default for merging 2 branches, uses 3-way merge
  • resolve — simpler than recursive, rarely used in practice
  • octopus — merges more than 2 branches at once
  • ours — keeps the current branch’s code entirely, discards all changes from the other branch
  • subtree — used for git subtree workflows

What about theirs? It’s not a standalone strategy — it’s an option for recursive: -X theirs. Easy to confuse, and I’ll clarify it below.

recursive (the default — your baseline)

Git uses this strategy by default when merging 2 branches. It finds the common ancestor, runs a 3-way merge, then stops on conflicts and leaves them for you to resolve. If you’ve ever debated whether to merge or rebase instead, Git Rebase vs Merge breaks down exactly when each approach keeps your history clean.

# You usually don't need to specify this, but you can be explicit:
git merge -s recursive feature/login

Recursive is the safest choice because it never silently discards anyone’s changes. The trade-off: when conflicts arise, you have to sit down and resolve each one yourself.

octopus — merge multiple branches at once

The name sounds odd but it’s genuinely useful. Octopus lets you merge 3, 4, even 10 branches into the current branch all at once.

# Merge 3 branches into main simultaneously
git checkout main
git merge -s octopus feature/auth feature/dashboard feature/api

Octopus works best when:

  • The branches have no conflicts with each other — octopus refuses to merge if it detects any conflict
  • You want a clean history: instead of 3 separate merge commits, you get 1 single commit with multiple parents
  • You’re folding small, independent feature branches into an integration branch

Keep in mind: Octopus does not handle conflicts. Two branches touching the same file? It throws an error and refuses to merge — no negotiation. This is fundamentally different from recursive.

# Output when octopus hits a conflict:
# error: Merge requires file-level merging
# Merge with strategy octopus failed.

ours — “my code, my rules”

This strategy works counterintuitively: you merge a branch in, but 100% of the final code belongs to the current branch. Code from the other branch is completely discarded — no warning, no prompt.

# Merge feature/old-approach but keep main's code entirely
git checkout main
git merge -s ours feature/old-approach

Sounds useless? There’s actually one very specific use case: marking a branch as “merged” in git history without actually taking its code.

Real-world example: your team has a hotfix/v1.2 branch that was applied manually to production. You want to merge it into develop so git stops complaining about an “unmerged branch”, but the hotfix changes were already handled a different way on develop. ours is exactly right for this. A common pattern is to first cherry-pick the hotfix commits into the target branch, then use -s ours to close the branch cleanly.

# Hotfix was already cherry-picked manually into develop
# Merge to close the branch without pulling in its code
git checkout develop
git merge -s ours hotfix/payment-bug
# Result: a merge commit exists, but develop's code is unchanged by a single line

-X theirs — “their version wins”

Not a strategy — an option for recursive. When a conflict occurs, instead of stopping for you to resolve it manually, Git automatically takes the code from the branch being merged in.

# Merge feature/new-config, preferring code from the feature branch on conflicts
git checkout main
git merge -X theirs feature/new-config

# The inverse: -X ours prefers code from the current branch (different from -s ours!)
git merge -X ours feature/new-config

What makes -X theirs useful: it still runs a full 3-way merge — it just auto-resolves conflicts by choosing “theirs”. Files without conflicts are merged normally.

Distinguishing -s ours from -X ours — a common source of confusion:

  • -s ours: completely ignores all changes from the other branch, even files with no conflict
  • -X ours: merges normally, only auto-resolving conflicts in favor of your current branch

Pros and Cons Breakdown

Octopus

Pros: Cleaner git history (fewer merge commits), convenient for folding multiple small feature branches in one shot.
Cons: Zero tolerance for conflicts. Any conflict at all and you have to resolve it before octopus will cooperate.

ours (strategy)

Pros: Useful for “closing” a branch without taking its code while keeping git history tidy.
Cons: Easy to shoot yourself in the foot — if you use it by mistake, you lose all changes from the other branch and git won’t warn you.

-X theirs / -X ours (options)

Pros: Fully automatic merge with no manual intervention, great for CI/CD pipelines.
Cons: You’re blindly trusting Git to know which version is correct. That’s not always a safe assumption.

Choosing the Right Strategy for Each Situation

Situation Recommended Strategy
Standard 2-branch merge recursive (default)
Merging 3+ small, conflict-free feature branches octopus
Closing an old branch without taking its code -s ours
Automated merge, preferring the newer branch -X theirs
Automated merge, preferring the current branch -X ours

Practical Implementation Guide

Scenario 1: Merging multiple feature branches into staging

# Verify there are no conflicts between branches first
git checkout staging
git merge -s octopus feature/user-auth feature/search feature/export

# If octopus fails due to conflicts, fall back to merging one branch at a time:
git merge feature/user-auth
# resolve conflicts...
git merge feature/search
git merge feature/export

Scenario 2: Closing a hotfix branch after cherry-picking

# Hotfix has already been cherry-picked into develop
# Merge to close the branch in git history
git checkout develop
git merge -s ours hotfix/critical-fix
git branch -d hotfix/critical-fix

# Verify develop's code is unchanged:
git diff HEAD~1 HEAD  # Only shows the merge commit, no code changes

Scenario 3: Auto-merge in a CI/CD pipeline

#!/bin/bash
# Merge release branch into main, preferring release branch code on conflicts

set -e

git checkout main
git fetch origin
git merge -X theirs origin/release/v2.1.0

# Log auto-resolved files for later auditing:
git log --merges -1 --format="%H" | xargs git diff-tree --no-commit-id -r --name-only

Scenario 4: Verify before using -X theirs

Before auto-resolving, I usually run a quick sanity check first:

# Preview which files would conflict
git merge --no-commit --no-ff feature/new-approach 2>&1 | grep CONFLICT

# If acceptable, abort and do the real merge with -X theirs
git merge --abort
git merge -X theirs feature/new-approach

A Few Things Worth Remembering

Don’t reach for -X theirs or -s ours on autopilot without understanding what you’re doing. I once watched a teammate use -s ours when merging a feature into main — the feature never made it into main, but git cheerfully reported “merged successfully”. It took 30 minutes to figure out what happened.

Octopus only shines when feature branches are small, independent, and thoroughly reviewed before merging. If your team regularly has conflicts between branches, octopus won’t save you.

And ultimately: the best strategy is not needing a special strategy at all. Small branches, frequent merges — fewer conflicts, and the default recursive is plenty. A solid practical Git workflow naturally minimizes the situations where you need any of the above. Everything above is situational tooling, not a habit to build.

Share: