A squash merge applies a branch's combined change to main as one new commit with one new message. Sam adds a last fix to feat/min-rating and lands it that way:
git switch -q feat/min-rating
# Edit app.js: skip the filter when ?minRating= is not a number
git commit -qam "Ignore a minRating that is not a number"
git switch -q main
git merge --squash feat/min-rating
git commit -qm "feat(api): filter books by minimum rating" \
-m "GET /api/books?minRating=4.5 returns only books rated 4.5 or higher."
git branch -d feat/min-rating
git branch -qD feat/min-rating && git push -q origin --delete feat/min-rating
git push -q && git log --oneline -3... Squash commit -- not updating HEAD Automatic merge went well; stopped before committing as requested ... error: the branch 'feat/min-rating' is not fully merged hint: If you are sure you want to delete it, run 'git branch -D feat/min-rating' ... 92f2964 feat(api): filter books by minimum rating 0abb28f chore: share a commit message template d396523 build: check commit messages with commitlint
The three branch commits used the old message style, and it no longer matters: only the squash message reaches main, and commitlint 18,754 checked it; many teams lint only the pull request title for this reason. The price shows in git branch -d: the squash commit shares no ancestry with the branch, so Git 1,932 cannot tell that the work landed, and you delete the branch with -D, after checking.
Squashing also coarsens history: git blame and git bisect (git bisect) point at the whole feature, not the step inside it that broke, although one git revert then removes the whole feature. Squash branches whose commits are work in progress; preserve them, by rebasing or with a merge commit, when each is already small, tested and explained.