Contents

Engineering Craft › Version Control (Git)

Fast-Forward vs Merge Commit

Moving a branch pointer ahead vs recording a merge commit.

Also known as: fast-forward, no-ff merge, merge commit

When you merge branch B into branch A, Git can do one of two things. If A hasn’t changed since B split off, it can simply move A’s pointer forward to B’s latest commit. That’s a fast-forward, and it adds no commit of its own. If A has new commits of its own, Git has to combine the two lines, and it records a merge commit with two parents.

git checkout main
git merge --ff-only feature   # succeeds only if main can fast-forward to feature
git merge --no-ff feature     # always creates a merge commit, even when it could fast-forward

The fast-forward moves main straight to the feature commit, while --no-ff adds a merge commit with two parents.

The trade-off is between a straight line of history and a record of when work was combined. A fast-forward keeps history linear and easy to read with git log. A merge commit shows where a feature branch joined, which helps when you want to see or revert a whole feature at once. Neither changes the content of the code, only the shape of the history.

The classic mistake is making fast-forward the goal for every merge. If main has moved on, a fast-forward isn’t possible, so the merge creates a commit anyway. Or you might rebase a feature onto main to make the merge a fast-forward, which rewrites the branch’s commits. If the branch is shared, that rewrite causes problems, as described in rewriting history. Pick one convention for the team and apply it consistently.