That's what the commit history is for. If you don't like seeing merges use git log --no-merges. You can use rebase to avoid seeing merge commits, but it's awfully unnecessary with the nasty side-effect of destroying history.
I was suggesting tags as way to keep an alternate history of features or releases. Features can be developed in separate branches for them, but you could tag features when you merge them in if you want an easy history of feature merges. You can list tags by date, use prefix's for sorting, etc.
What you want is a logical sequence of correct changes (or, as correct as anyone could tell at the time; of course no one's perfect).
If you you have to do code review, track down a bug by bisecting a commit history, or figure out what patches from one branch need to be ported to another, you want to have good history. False starts and fixes to typos from previous patches have no value; in fact, they have negative value, as they obscure the interesting information that a good history provides.
Cleaning up history really doesn't take that long. When something is about ready to merge, take a quick look through the history to figure out which patches are redundant or logically belong as part of previous patches, do a "git rebase -i", and squash them into the appropriate patches. In the process, make sure your commit message are actually good enough that someone doing a code review can actually follow what you're doing (no "fixed a bug in this function; fixed a bug in that function"; actually explain what you fixed and why your fix is the right one).
> make sure your commit message are actually good enough that someone doing a code review can actually follow what you're doing
Yes, this is a very important point for rebasing.
I don't know what you're going on about with this "destroying history" as if the sequence of your little typo mistakes are some kind of precious documentary that needs to be preserved in case some forensic expert wants to trace every step you made along the process of adding a widget. You might as well go find a system that records and tracks every key you type, because after all, every time you hit the backspace key, you are destroying history.
Tags do not keep alternate histories. They are simply labels on commits. You use them to mark certain commits as releases, you do not use them to track every logical change to the codebase. They are used sparingly to track the occasional version number bump as a result of a sufficiently large number of changes. These version tags do not provide the granularity I need when I look to see what is happening on a single branch at any point in time. To add them to every non-trivial commit as a way of distinguishing them from the just-dicking-around commits would be ludicrous.
edit: One more thing. I think it is absolutely silly to say in one comment "stop committing non-workable intermediate stuff and finish what you're doing before committing" and then turn around in another comment and talk about how rebase has a "nasty side-effect of destroying history". You do realize that all the editing and polishing you're doing before you make your commit is the same type of destroying history that would happen if you made small, incremental commits and then cleaned them up with rebase, right? The only difference is that your way is way more dangerous as far as losing history is concerned, and you're not taking advantage of any of the benefits of Git in the process.