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?

GitMidgitmergefast-forwardno-ffworkflowhistory

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

// WHAT INTERVIEWERS LOOK FOR

Understanding when fast-forward is possible (no divergence). Why --no-ff preserves branch topology and enables single-revert of entire feature. Knowing the three GitHub PR merge strategy options and their git equivalents.

// COMMON PITFALL

Using squash-and-merge for every PR — it gives a tidy log but makes `git bisect` point to a single giant squash commit, reducing the granularity available for debugging.