Git Merge Strategies Explained: Fast-Forward, Merge Commit, and Squash
Adam C. |

When working with Git, merging branches is a fundamental part of collaboration. But not all merges are the same. There are three main merge strategies you can use, and each one impacts your repository history differently.

Photo by Raimond Klavins on Unsplash

Here’s a clear breakdown of each method:

✅ 1. Fast-Forward Merge (when possible)

This is the cleanest type of merge. Git simply moves the pointer of the current branch forward — no new commit is created.

git merge feature-branch              # if fast-forward is possible
git merge --ff-only feature-branch    # enforce fast-forward only

What happens:

No new commit is created

Branch history remains linear

It looks like all work was done directly on main

Use when: main hasn’t changed since feature-branch was created.

🔁 2. Merge Commit (default when branches diverge)

This is Git’s default behavior when branches have diverged.

git merge feature-branch

What happens:

Git creates a new merge commit

Both branches' histories are preserved

The history becomes non-linear, with a visible merge point

Use when: You want to retain the full commit history of both branches.

🧱 3. Squash Merge (--squash)

This strategy takes all the changes in the feature branch and squashes them into a single commit.

git merge --squash feature-branch
git commit -m "Add feature"

What happens:

All commits in the branch are combined into one

No merge commit is created automatically

The branch structure is not recorded in history

Use when: You want a clean, one-commit-per-feature history (e.g., for open-source projects or public repos).

⚙️ Other Merge-related Options

OptionWhat it does
--no-ffForces a merge commit even if fast-forward is possible
--ff-onlyFails the merge if fast-forward isn’t possible
--squashCombines all changes into one new commit
--no-commitPrepares the merge but doesn’t commit it (review first)

🔁 Summary Table

StrategyCommandNew Commit?Keeps History?Clean?Notes
Fast-forwardgit merge or --ff-only❌ No✅ Yes✅ YesPointer move only
Merge commitgit merge or --no-ff✅ Yes✅ Yes❌ NoDefault if divergent
Squashgit merge --squash✅ Yes❌ No✅ YesFlattens to one commit

For public projects like SwimSnap, adopting --ff-only or squash merges ensures a readable, maintainable Git history. It helps contributors and maintainers stay focused on features, not merge clutter.

Want help automating your merge strategy or enforcing it on GitHub? Just ask!