Q:

git commit best practices

I am using git to manage a C++ project. When I am working on the projects, I find it hard to organize the changes into commits when changing things that are related to many places. 
For example, I may change a class interface in a .h file, which will affect the corresponding .cpp file, and also other files using it. I am not sure whether it is reasonable to put all the stuff into one big commit.
Intuitively, I think the commits should be modular, each one of them corresponds to a functional update/change, so that the collaborators could pick things accordingly. But seems that sometimes it is inevitable to include lots of files and changes to make a functional change actually work.
Searching did not yield me any good suggestion or tips. Hence I wonder if anyone could give me some best practices when doing commits.
PS. I've been using git for a while and I know how to interactively add/rebase/split/amend/... What I am asking is the PHILOSOPHY part.
Update: Thanks for all the advices. Maybe this should be learned from practicing. I will keep the problem open for some time to see if there is more suggestions.

A:

I tend to commit as you propose: a commit is a logically connected change set. My commits can be anything from a one-liner to a change in all files (for example add/change a copyright notice in the source files). The reason for change need not be a full task that I am implementing, but it is usually a milestone in the task.
If I have modified something that is not related to my current commit, I tend to do an interactive add to separate out the unrelated changes, too - even when it is a whitespace tidy up.
I have found that commits that simply dump the working state to repository makes them a lot less useful: I cannot backport a bugfix to an earlier version or include a utility functionality in another branch easily if the commits are all over the place.
One alternative to this approach is using a lot of tiny commits inside a feature branch, and once the whole feature is done, do heavy history rewriting to tidy up the commits into a logical structure. But I find this approach to be a time waster.

A:

This is exactly the use case, for which the index, the staging area, was introduced in git.
You can feel free to do as many changes unrelated to each other as possible. Then you choose what all are related and then make several atomic commits in one shot.
I do it all the time. If you use git-gui or any of the other GUI clients, you can choose not only the file that you want to commit, but also hunks within the files, so your commits are as atomic as possible.

A:

I try and follow these practices in the order...

A commit must not fail a build. Most important!
It should be made of one logical unit of change - whether a single line/character or a whole file/class with corresponding changes in other parts of code, still following #1.
What is a logical unit of change? In terms of git, if you can specify the changes in the commit message in least number of characters, in one sentence (without ANDs of-course), and you can not break that description further into smaller units, that I call one unit.
Commit message should clearly specify the essence of the commit.
Commit message should be small, typically no greater than 80 chars. Any more elaboration should be part of the description.

