Q25 of 40 · Git
What is the difference between a fast-forward merge and a no-fast-forward (--no-ff) merge, and which should a QA team prefer?
Short answer
Short answer: Fast-forward simply moves the branch pointer forward (no merge commit, linear history). `--no-ff` always creates a merge commit, preserving the branch topology. QA teams usually prefer `--no-ff` on protected branches so feature/test work is traceable as a unit.
Detail
Fast-forward merge is possible when the target branch (e.g., main) has not diverged from the feature branch's base — it's a strict ancestor. Git simply advances the pointer without creating a merge commit. The result looks like the feature commits were always directly on main, which gives a clean, linear log but loses the grouping information.
--no-ff (no-fast-forward) always creates a merge commit even if fast-forward is possible. The merge commit records both parents, so git log --graph shows the branch as a separate lane that rejoins the trunk. This means you can later run git log --merges or git revert -m 1 <merge-sha> to revert all feature commits in one operation.
QA relevance: when a test suite lives on a feature branch (feature/add-payment-tests), merging with --no-ff keeps those 12 test commits visually grouped. If the tests later cause a regression on main, you can revert the entire merge commit instead of hunting down 12 individual SHAs.
GitHub/GitLab PR merge strategies: "Create a merge commit" = --no-ff; "Squash and merge" = squash then fast-forward; "Rebase and merge" = fast-forward after rebasing. Configure the default per-repo to enforce your team's policy.
// EXAMPLE
# Fast-forward merge (default when possible)
git switch main
git merge feature/add-payment-tests
# If main hasn't diverged, no merge commit is created
# No-fast-forward: always create a merge commit
git merge --no-ff feature/add-payment-tests -m "Merge feature/add-payment-tests into main"
# View branch topology
git log --oneline --graph --decorate --all
# Revert the entire feature in one command (only possible with --no-ff)
git revert -m 1 <merge-commit-sha>
# Force fast-forward only (fail if not possible — useful in CI)
git merge --ff-only origin/main