We check stuff into trunk, and when we release, we "tag" trunk/ and make a copy in the tags/ directory that is versioned. This code never gets touched again; in this way, once the code is compiled and released, if we find a bug in version 0.39, we can do a checkout of tags/0.39 to track it down. Once the bug is found, then the code is merged into trunk and a new release is generated.
In order to commit a tag, the manual process looks like this:
Figure out what the latest version in the tags/ directory is so that we can increment it for the next version. Suppose we've committed 0.38 and we want to create 0.39.
svn copy https://our.svn.repository/product/trunk \ https://our.svn.repository/product/tags/0.39
svn commit -m "Release version 0.39"
Because our release cycle is so fast, we're doing this many times over the course of the week.
Because efficiency is a good thing, we really don't want to do this over and over again by hand.
So I created a easy little tool in perl called tagger. It figures out what repository we're currently in, does a lookup in the tags/ directory, figures out what the most likely candidate is for the next version, and then does the svn copy and svn commit for us, prompting us along the way. We can also throw tagger a flag and have it do no prompting at all.
What I particularly like about tagger is that it allows me and our developers to forget all of the steps that go into tagging a release. I run tagger, hit enter a few times, and I'm done. As an added bonus, if I ever want to see the commands tagger is executing on my behalf, I can throw it into verbose or debug mode and it will show me what it is doing or would do.
Spend a little time seeing what tasks you and your developers are doing over and over again. Then see if a little scripting can ease the pain.