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:
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-forward

Result:
1main → A — B — C — D

No 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.
1git merge --no-ff feature

Result history:
1A — B — C — D — M 2 ↖ feature

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:
1git merge --no-ff feature-branch
as a standard practice.

15.3 The 3-Way Merge (Most Common Case)

Used when branches have diverged, i.e., both have new commits.

History example:
1main: A — B — C 2 \ 3feature: D — E

Command:
1git merge feature

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.

15.4 Squash Merge

A squash merge compresses all commits of a branch into one.

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.
1git merge -s recursive feature

5.2 Ours Strategy

Keeps your branch's changes, ignores the incoming branch.
1git merge -s ours feature
Useful for:
• Marking a branch as merged
• Keeping history but discarding code

5.3 Octopus Strategy

For merging multiple branches at once.
1git merge branch1 branch2 branch3
Used mainly in large automated integration flows.

15.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

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

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.