The commit message is like a title. All diff lines must be related to it or they should be in another changeset.
Personally, I don't mind lying a bit in my personal projects.
To lie, you simply make a new branch for each feature or otherwise related changeset such as a hotfix. Within that branch, you make as many commits as you want, the more the merrier.
When the branch is ready to merge, you use "git merge --squash branchname" which will pull in the changes from branchname in an uncommited form. Then, you can use "git diff" to view the differences and make one single commit with an appropriate commit message detailing each change.
The upside is that it is atomic without needing to use the git-workflow no fast-forward business. The downside is you're lying.
[1] http://paul.stadig.name/2010/12/thou-shalt-not-lie-git-rebas...
Without commit messages.
Boy, did I pay for that one.