You're right -- the diff answers the what, so being able to answer the why concisely is what makes a good commit message.
Ticket numbers are important context, but unless it is a one-off commit you can instead put that info in the merge commit (as if saying, all of these commits I'm merging were made as part of fixing Issue #17).
Some people like to use squash extensively for that reason, but then you don't have the same granularity when it comes to reverting individual bits of that commit without reverting the entire bugfix. (This assumes that every commit leaves the code in a working state with passing tests).