Fast-Forward and Other Merge Strategies
15.1 What Is a Fast-Forward Merge?
A fast-forward merge occurs when the target branch has not diverged from the source branch.
Example history before merge:
Since main has no new commits after B, Git simply moves the main pointer forward:
Result:
No merge commit is created.
When to use fast-forward:
• Small feature branches
• Solo development
• When a simple, linear history is preferred
Example history before merge:
1main: A — B
2 \
3 C — D (feature)Since main has no new commits after B, Git simply moves the main pointer forward:
1git checkout main
2git merge feature
3# Output: Fast-forwardResult:
1main → A — B — C — DNo merge commit is created.
When to use fast-forward:
• Small feature branches
• Solo development
• When a simple, linear history is preferred
15.2 The --no-ff (No Fast-Forward) Merge
A non-fast-forward merge forces Git to create a merge commit even if a fast-forward was possible.
Result history:
Why use --no-ff ?
• Preserves the idea of a branch in history
• Makes it clear what work belonged to which feature
• Helpful in team environments
Many teams use:as a standard practice.
1git merge --no-ff featureResult history:
1A — B — C — D — M
2 ↖ featureWhy use --no-ff ?
• Preserves the idea of a branch in history
• Makes it clear what work belonged to which feature
• Helpful in team environments
Many teams use:
1git merge --no-ff feature-branch15.3 The 3-Way Merge (Most Common Case)
Used when branches have diverged, i.e., both have new commits.
History example:
Command:
Git finds:
• Base commit (B)
• Current branch commit (C)
• Branch being merged commit (E)
It combines all three → creates a merge commit.
3-way merges preserve full history and are the standard merge type in shared repos.
History example:
1main: A — B — C
2 \
3feature: D — ECommand:
1git merge featureGit finds:
• Base commit (B)
• Current branch commit (C)
• Branch being merged commit (E)
It combines all three → creates a merge commit.
3-way merges preserve full history and are the standard merge type in shared repos.
15.4 Squash Merge
A squash merge compresses all commits of a branch into one.
Result:
Why squash?
• Simplifies messy or experimental commit history
• Keeps main very clean
It is ideal for:
• Early stage prototypes
• Inexperienced contributors
• Large PRs broken into many small commits
1git merge --squash feature
2git commit -m "Add login feature"Result:
1A — B — C — D (single combined commit)Why squash?
• Simplifies messy or experimental commit history
• Keeps main very clean
It is ideal for:
• Early stage prototypes
• Inexperienced contributors
• Large PRs broken into many small commits
15.5 Merge Strategy Options (--strategy)
Git merges can be influenced using strategies.
5.1 Recursive Strategy (default)
The standard for merging two branches.
5.2 Ours Strategy
Keeps your branch's changes, ignores the incoming branch.Useful for:
• Marking a branch as merged
• Keeping history but discarding code
5.3 Octopus Strategy
For merging multiple branches at once.
Used mainly in large automated integration flows.
5.1 Recursive Strategy (default)
The standard for merging two branches.
1git merge -s recursive feature5.2 Ours Strategy
Keeps your branch's changes, ignores the incoming branch.
1git merge -s ours feature• Marking a branch as merged
• Keeping history but discarding code
5.3 Octopus Strategy
For merging multiple branches at once.
1git merge branch1 branch2 branch315.6 Choosing the Right Merge Behavior
Your decision depends on your team's workflow:
Fast-Forward (Default)
• Clean linear history
• Simple and useful for solo developers
No Fast-Forward
• Keeps feature branches visible in history
• Enables better code review tracking
Squash
• Great for tidying up messy branches
• Best for feature branches with many commits
3-Way Merge
• Safe, preserves all contributions
• Standard in teams with parallel work
Fast-Forward (Default)
• Clean linear history
• Simple and useful for solo developers
No Fast-Forward
• Keeps feature branches visible in history
• Enables better code review tracking
Squash
• Great for tidying up messy branches
• Best for feature branches with many commits
3-Way Merge
• Safe, preserves all contributions
• Standard in teams with parallel work
15.7 Best Practices
• Fast-forward for small or personal branches
• No-ff for major features to preserve branch structure
• Squash for cleanup
• Avoid rewriting history on shared branches
• Keep branches short-lived to avoid complex merges
• No-ff for major features to preserve branch structure
• Squash for cleanup
• Avoid rewriting history on shared branches
• Keep branches short-lived to avoid complex merges
15.8 Key Takeaways
• Fast-forward moves the branch pointer directly—no merge commit.
• No-fast-forward creates a merge commit, even if not needed.
• 3-way merge handles diverged branches with a new commit.
• Squash merge compresses all commits into one.
• Merge strategies (recursive, ours, octopus) offer additional control.
• Choose merge type based on whether you want a clean history, explicit feature boundaries, or simplified commits.
• No-fast-forward creates a merge commit, even if not needed.
• 3-way merge handles diverged branches with a new commit.
• Squash merge compresses all commits into one.
• Merge strategies (recursive, ours, octopus) offer additional control.
• Choose merge type based on whether you want a clean history, explicit feature boundaries, or simplified commits.