I'm a habitual committer and I found that suits me, but admittedly my commit messages are almost always like,
Age: 9 mins [*] Working on implementing and testing PaintSystem.
Age: 17 mins [*] Working on implementing and testing PaintSystem.
Age: 37 mins [*] Working on implementing and testing PaintSystem.
Age: 52 mins [*] Working on implementing and testing PaintSystem.
So I can't exactly say that making such frequent and habitual commits to my branch (mercurial) has exactly encouraged the most detailed commit logs. Sometimes I'll even commit code halfway done if, say, my wife asks me to go out for dinner at which point I'll just hastily copy and use the previous "Working on [...]" commit message.
My commit log patterns are typically like,
"Working on [...] Working on [...] Working [...] Completed [...] Started working on [...] Working on [...] Completed [...] Started working on [...]"
On the flip side though, it has saved my butt. Sometimes I do run into an edge case I didn't anticipate and test against, at which point the frequent commits help me figure out exactly where I introduced the mistake.
So I don't know about the best habits and I'm certainly not one to listen to as far as ideal commit logging habits, but I can certainly say that committing more frequently can definitely help out when you need to perform a regression.
Should each one-line change get a commit?
I've committed one-line changes before but usually tricky ones and maybe I was short on time. My commits don't always resemble perfect and complete units of work or change. As said, sometimes they're just the result of my wife asking me to go out for dinner unexpectedly.
TBH a lot of my commits which follow that
"Working on [...]" log pattern are not modeling coherent units of change (why I often cannot come up with a message better than
"Working on [...]") but just the result of me taking a breather, like making myself a cup of coffee. The
"Completed [...]" message indicates the end of that unit of work, and there I often write a much more detailed message along with the first
"Started working on [...]" type messages when I just start working on something. If you average commits like once every 15 mins, then those "Working on [...]" messages are more like in-betweeners for what someone might commit in one bulkier commit with a more detailed message.
Should I commit before any test (e.g., at least for syntax/compiling
errors and then have to totally undo it; as the idea didn't work or
the message is a lie)?
I just go ahead and commit it before even running tests sometimes (again if I had an unexpected event). Also even though I'm solo, I do push to a server (just one running here at home on a LAN) that does CI. That might seem like overkill but dunno, I got so used to leaning on that in my former workplaces. Plus I don't wanna be bothered having to run all my unit and integration tests by hand each time. I like having that all tied to just pushing. If a test fails it's easy enough to work in a forward-moving fashion where I do the regression, correct the mistake in the latest rev, and keep going. That said, I do at least build the code against a debug build before I commit.
Should I make sure I commit each morning/afternoon before I stop
working for dinner while its still fresh?
I like to commit before I go out and have a break between programming. I didn't really put much thought into why exactly until I encountered this question. I suppose it's to prevent myself from picking up where I left off without a commit log there in place of where I left off that I can diff and so forth. Hmm, I need to get back to you on that since it's maybe not theoretically needed given how frequently I commit. I still feel more comfortable committing and pushing before I leave the computer for whatever reason. Some of it might be that former psychological fear of, say, the computer catching on fire after I leave and having project managers back in the days when we were using SVN with the devs sometimes going for weeks without commits breathing down our necks and constantly reminding us to check in code as often as possible while reminding us that our code is the company's property. Also it's a little bit more efficient especially with the pushing so that my CI process can start running all the tests while I'm away so that I can come back and see the results.
Oh and sometimes I get a bit drunk after I leave and it's usually a bad idea to try to write complex code while drunk (though not always; one time I came up with a really nice context menu system after having an eureka moment while drunk, but I only had like 6 beers and it wasn't that complex to code). If I attempt to do that, at least I committed the soberly-written code before I left to revert back towards instead of mixing the drunk code with the sober code, at which point my commit log might read like,
"Reverting back to code written before Jagermeister shots." I don't do this very frequently unless I got a drunken code inspiration, but in those rare cases, it really did help that I committed something before I went out and got drunk.