Fast-forwarding is almost never an option for us as we so often have multiple parallel feature branches on the go, each of which may get merged into master at any point. And I don't want to advocate rebasing feature branches, because it makes too many changes to the commit history that I'm uncomfortable with, and, if used inexpertly, can mess with proper commit authorship and attribution (not to mention cause major conflicts and even loss of work when branches are shared between authors).
That being said, I'm giving some serious thought to looking at Github's "Squash and merge" technique more closely, since it gives us most of the benefits (clean, linear history) without the drawbacks of having to rebase (other than the squashing itself of course, which is a form of rebasing).
With this technique, when a PR gets merged, the commit history just shows a single commit on the target branch, that is a squashed version of the entire PR. This commit is
not a real merge commit, so from the point of view of the git history it looks like a single, sequential commit on the target branch (see for example
https://github.com/eclipse/rdf4j/commit/b8797d5e14af1d6a41063716f9f7875f3a308622 which is a PR by Havard that had two commits originally, which I merged to master using squash and merge). I was worried about authorship and signing, but it looks as if Github is smart enough to keep the original author on the commit (I'm the committer, but Havard is still the author). It also automatically adds the original commit messages (including sign-offs) on the squashed commit message.