Concepts
Git Merge Deep Dive
Understand Git merge strategies, recursive merge, ours/theirs, octopus merge, and conflict resolution.
- Readers who want the history model before advanced commands
- A basic sense that commits are not just a file list
- Treating a concepts page like a command how-to
What you will learn
- Understand the core purpose of Git Merge Deep Dive
- Master the basic usage and common options of Git Merge Deep Dive
- Understand Git merge strategies, recursive merge, ours/theirs, octopus merge, and conflict resolution.
- Understand key concepts: Overview
- Know when to use this feature and when to avoid it
Start with a problem
You've encountered a conceptual question while using Git — you roughly know what it means, but you're not entirely sure about its precise definition and boundaries.
Overview
git merge joins two or more development histories. Git supports multiple merge strategies, defaulting to recursive.
Merge Strategies
1. Recursive (Default)
git merge feature
# Same as
git merge -s recursive feature
Characteristics:
- Three-way merge (common ancestor + two heads)
- Automatic rename detection
- Supports
ours/theirssub-strategies for conflicts
# Auto-choose current branch on conflict
git merge -s recursive -X ours feature
# Auto-choose incoming branch on conflict
git merge -s recursive -X theirs feature
# Ignore whitespace changes
git merge -s recursive -X ignore-space-change feature
2. Ort (Ostensibly Recursive's Twin)
Git 2.32+ modern replacement for recursive:
- Better performance (especially large repos)
- More accurate conflict detection
- Default in Git 2.37+
git merge -s ort feature
3. Ours (Ignore Incoming)
git merge -s ours feature
- Result tree = current branch exactly
- Only records merge commit, introduces no changes
- Use case: record already-merged branch, mark deprecated
4. Theirs (Take Incoming)
git merge -s theirs feature
- Result tree = incoming branch exactly
- Note: strategy-level, not
-X theirs(which is conflict resolution option)
5. Octopus (Multi-head)
git merge branch1 branch2 branch3
- Merges multiple branches simultaneously (>2 heads)
- Only works when no conflicts
- Common for release integration:
git merge feature-a feature-b feature-c
6. Resolve (Legacy Three-way)
git merge -s resolve feature
- Legacy three-way algorithm
- Weak rename/complex history handling
- Only for compatibility with very old Git
Conflict Resolution
Conflict Markers
<<<<<<< HEAD
Current branch content
=======
Incoming branch content
>>>>>>> feature
Tools
# Launch merge tool
git mergetool
# Common: vimdiff, kdiff3, meld, vscode
git config --global merge.tool vscode
Resolution Options
| Option | Effect |
|---|---|
-X ours | Choose current branch on conflict |
-X theirs | Choose incoming branch on conflict |
-X ignore-space-change | Ignore whitespace conflicts |
-X ignore-all-space | Ignore all whitespace |
-X rename-threshold=N | Rename detection threshold (default 50%) |
Merge Commit Structure
# Regular merge (no fast-forward)
git merge --no-ff feature
# Fast-forward (default if possible)
git merge feature
# Force merge commit
git merge --no-ff feature
Merge Commit Specialty
flowchart LR
A[Parent 1: current] --> C[Merge commit]
B[Parent 2: incoming] --> C
C --> D[Two parents]
Two parents enable:
git log --first-parent— mainline onlygit log --all— full topology
Advanced Usage
Merge Specific Files
# Merge single file from another branch
git checkout feature -- path/to/file
# Or
git restore -s feature -- path/to/file
# Subtree merge (preserve history)
git merge -s subtree feature
Squash Merge
# Squash all commits into one
git merge --squash feature
git commit
- No merge commit (single parent)
- Loses branch topology
- GitHub/GitLab PR "Squash and merge" uses this
Preview Before Commit
# Preview result without committing
git merge --no-commit --no-ff feature
git diff HEAD
git merge --abort # Cancel
Best Practices
- Feature branches:
--no-ff— preserves topology for traceability - Release branches: Octopus — integrate multiple features at once
- Automate conflicts with
-X— reduce manual intervention in CI - Merge upstream regularly — reduces large conflict probability
- Protect main branch — require PR + review, no direct push
Common Issues
| Issue | Cause | Fix |
|---|---|---|
| "Already up to date" | Incoming is ancestor | Nothing to merge |
| "Not possible to fast-forward" | Diverged history | Use --no-ff or rebase first |
| Many conflicts | Long divergence | Merge upstream regularly, or rebase sync |
| Too many merge commits | Frequent mainline merges | Use rebase instead of merge for sync |
Try it yourself
- Practice the git-merge-deep command in a test repository and observe state changes before and after
- Experiment with different options and compare the output differences
- Simulate a real scenario where you would need to use this, and walk through the full process
Continue Learning
commands/git-merge— git merge referenceinternals/three-way-merge-mechanics— Three-way merge internalsconcepts/merge-strategies— Strategy comparisonconcepts/git-rebase-deep— Git Rebase Deep Dive