From Kiln co-creator Benjamin Pollack:

At Fog Creek, we use tags that match a regex to set the build number. For example, the current version of Kiln 2.0 that’s on On Demand is generation 240, so there’s a tag called Hosted_Kiln_240. Every time we cut a new build, we make a new tag, and the build scripts know to look for Hosted_Kiln_(\d+) to set the build number.

That works great for us. We only make a couple of builds per day, and we make lots and lots of commits. But if you had, say, a continuous integration system running, it’d be incredibly annoying; your commits would get drowned out by the new tags.

The “right” thing to do is to use the changeset numbers. I say “right” because it’s the only thing that will be constant across all repositories. They just happen to be ugly.

Thankfully, if you want something that’s a lot more readable and will work just fine (with some caveats), there are two solutions:

  1. If you’re always building from the same repository, you can simply use Mercurial’s revision number. Just remember that it’s not constant across repositories, so if you cut builds for the same product from two different repos, you’re in for a world of pain. Otherwise, though, you should be fine. When we first switched to Mercurial, Copilot used that scheme, and it served us well until we switched to a tag/regex-based solution.
  2. If you want something similar, but more informative and (slightly) more resilient to you switching repositories, you can use Mercurial’s latesttag and latesttagdistance template tags. These tags will tell you what the most recent tag was in the repository, and how many changesets sit between the changeset in question and that tag.

    For example, from your project, try running hg parents --template '{latesttag}+{latesttagdistance}\n'. On my system, for example, that gives back Hosted_Kiln_240+11, meaning that my team made 11 new changesets since we cut version 240. If you were using more traditional version numbers for your tags, it’d be pretty reasonable to just grab {latesttag}.{latesttagdistance} to get a traditional <major>.<minor>.<bugfix>.<build>-style version number.

As I said, both of these methods are “bad” in the sense that they are repository-dependent. If you really need cross-repository build consistency, you probably really do want to suck it up and go the tagging route. But, as long as you keep the caveats in mind, this should provide you clean, easy-to-use build numbers that’ll still reliably identify what changesets ended up in the build.