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.
Here’s a clear breakdown of each method:
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.
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.
--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).
Option | What it does |
---|---|
--no-ff | Forces a merge commit even if fast-forward is possible |
--ff-only | Fails the merge if fast-forward isn’t possible |
--squash | Combines all changes into one new commit |
--no-commit | Prepares the merge but doesn’t commit it (review first) |
Strategy | Command | New Commit? | Keeps History? | Clean? | Notes |
---|---|---|---|---|---|
Fast-forward | git merge or --ff-only | ❌ No | ✅ Yes | ✅ Yes | Pointer move only |
Merge commit | git merge or --no-ff | ✅ Yes | ✅ Yes | ❌ No | Default if divergent |
Squash | git merge --squash | ✅ Yes | ❌ No | ✅ Yes | Flattens 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!