Fast-Forward for Clean History

Updated

October 30, 2026

Creating a Fast-Forward Merge for a Clean History

After this page you can keep main a straight line when the feature branch is ahead of it.

When a fast-forward is possible

main has not moved since you branched. Every commit on the feature is a descendant of main.

 before --ff-only                   after --ff-only

 A ← B ← C          main            A ← B ← C ← D ← E   main
           ← D ← E  feat                        feat
cd ~/desk/desk-api
git switch main
git merge --ff-only feat/ping-json

--ff-only fails if Git would need a merge commit. That is the setting you already put in pull.ff only for pulls. Use it on purpose for local merges when you want a linear main.

If it fails

Someone committed to main while you worked. Options:

  1. Merge anyway (git merge feat/ping-json) → merge commit, history shows the join.
  2. Rebase the feature onto main (chapter 9), then --ff-only.
  3. git merge --no-ff feat/ping-json → always a merge commit (Git Flow release style).

See it

git log --oneline --graph --decorate

A fast-forward looks like a single chain. A merge commit is a join with two parents.

first-parent

git log --first-parent --oneline

Walks only ^1. After --no-ff merges, this is “what landed on main.” After a fast-forward, it is the same as a normal log. Chapter 15 picks a branching strategy; this page is the mechanism that strategy will call.