Credit is the primary currency of the free software world. Whatever people may say about their motivations for participating in a project, I don't know many developers who would be happy doing all their work anonymously, or under someone else's name. There are tangible reasons for this: one's reputation in a project roughly governs how much influence one has, and participation in an open source project can also indirectly have monetary value, because many employers now look for it on resumés. There are also intangible reasons, perhaps even more powerful: people simply want to be appreciated, and instinctively look for signs that their work was recognized by others. The promise of credit is therefore one of best motivators the project has. When small contributions are acknowledged, people come back to do more.
One of the most important features of collaborative development software (see Chapter 3, Technical Infrastructure) is that it keeps accurate records of who did what, when. Wherever possible, use these existing mechanisms to make sure that credit is distributed accurately, and be specific about the nature of the contribution. Don't just write "Thanks to J. Random <firstname.lastname@example.org>" if instead you can write "Thanks to J. Random <email@example.com> for the bug report and reproduction recipe" in a log message.
In Subversion, we have an informal but consistent policy of crediting the reporter of a bug in either the ticket filed, if there is one, or the log message of the commit that fixes the bug, if not. A quick survey of Subversion commit logs up to commit number 14525 shows that about 10% of commits give credit to someone by name and email address, usually the person who reported or analyzed the bug fixed by that commit. Note that this person is different from the developer who actually made the commit, whose name is already recorded automatically by the version control system. As of mid-2005, when I last did this calculation, slightly over two-thirds were credited in the commit logs, usually multiple times, before they became committers themselves. This does not, of course, prove that being credited was a factor in their continued involvement, but it surely can't hurt to set up an atmosphere in which people know they can count on their contributions being acknowledged. 
It is important to distinguish between routine acknowledgement and special thanks. When discussing a particular piece of code, or some other contribution someone made, it is fine to acknowledge their work. For example, saying "Daniel's recent changes to the delta code mean we can now implement feature X" simultaneously helps people identify which changes you're talking about and acknowledges Daniel's work. On the other hand, posting solely to thank Daniel for the delta code changes serves no immediate practical purpose. It doesn't add any information, since the version control system and other mechanisms have already recorded the fact that he made the changes. Thanking everyone for everything would be distracting and ultimately information-free, since thanks are effective largely by how much they stand out from the default, background level of favorable comment going on all the time. This does not mean, of course, that you should never thank people. Just make sure to do it in ways that tend not to lead to credit inflation. Following these guidelines will help:
The more ephemeral the forum, the more free you should feel to express thanks there. For example, thanking someone for their bugfix in passing during an IRC conversation is fine, as is an aside in an email devoted mainly to other topics. But don't post a new email solely to thank someone, unless it's for a truly unusual feat, or if it's just one followup in a topic-specific thread already focused on the thing that person did.
Likewise, don't clutter the project's web pages with expressions of gratitude. Once you start that, it'll never be clear when or where to stop. And never put thanks into comments in the code; that would only be a distraction from the primary purpose of comments, which is to help the reader understand the code.
The less involved someone is in the project, the more appropriate it is to thank her for something she did. This may sound counterintuitive, but it fits with the attitude that expressing thanks is something you do when someone contributes even more than you thought she would. Thus, to constantly thank regular contributors for doing what they normally do would be to express a lower expectation of them than they have of themselves. If anything, you want to aim for the opposite effect!
There are occasional exceptions to this rule. It's acceptable to thank someone for fulfilling his expected role when that role involves temporary, intense efforts from time to time. The canonical example is the release manager, who goes into high gear around the time of each release, but otherwise lies dormant (dormant as a release manager, in any case — he may also be an active developer, but that's a different matter).
As with criticism and crediting, gratitude should be specific. Don't thank people just for being great, even if they are. Thank them for something they did that was out of the ordinary, and for bonus points, say exactly why what they did was so great.
In general, there is always a tension between making sure that people's individual contributions are recognized, and making sure the project is a group effort rather than a collection of individual glories. Just remain aware of this tension and try to err on the side of group, and things won't get out of hand.
 Brian Fitzpatrick has written about the employment value of open source activity in The Virtual Referral (http://www.onlamp.com/pub/a/onlamp/2005/07/14/osdevelopers.html) and The Virtual Internship (http://www.onlamp.com/pub/a/onlamp/2005/08/01/opensourcedevelopers.html).
 Eventually this crediting system became a bit more formalized, as described in http://subversion.apache.org/docs/community-guide/conventions.html#crediting, thus improving the project's ability to find and encourage long-term participants, via a system known as the Contribulyzer. See the section called “The Automation Ratio” for more about this example.