My favorite is the complexity of having an in-tree changelog that lists (shortlog) commits under appropriate tag headings - checked in under appropriate tags.
It roughly amounts to:
1) commit fix (git commit -m "fixes #foo bug"
2) get hash/shortlog, add to changelog
3) commit changelog referencing commit in 1)
4) tag hash in 3) with new minor version 1.1.2 to 1.1.3
5) realize you forgot that 1) warranted a bump in minor version, edit changelog to reflect new minor version
6) commit new changelog
7) move tag from 4) to 6) - hope you didn't push yet...
And people say RCS $Id:$ was a hack...
Now,the real issue is actually to find a nice way to tag actual releases, with current tag and hash. I realize this is mostly tricky when a project is "checkout and run" - without a build step (eg ruby on rails project). It's still somewhat painful to make sure there's an up to date global variable that correctly reflects the running version.