Soft resets beat merge --squash
merge --squash looked clean on paper but kept biting me with detached histories, lost commit metadata, and surprise conflicts that were hard to replay. The workflow that finally stuck is even simpler: fast-forward main, soft-reset the feature branch to that point, and create the single commit I actually want.