A colleague and I have been taking turns debating/discussing the issues/merits of integrating a version derived from the current git repository into our code whenever it builds.

We think the merits include:

  • No need to worry about human error in updating a version number
  • Traceability between what we find in a device and the source code it was derived from

The issues that have arisen (for us) include:

  • IDE derived build systems (e.g. MPLABX) can make it hard to figure out where to put these kinds of hooks in (and it can end up pretty cheesy in the end)
  • More work to actually integrate this into the build scripts/makefiles
  • Coupling to a particular build approach (e.g. what if one person builds with XCode and the other MPLABX) may create downstream surprises

So we're curious where others have landed on this debate. It's really easy for the discussion to become anecdotal. There are lots of people out there who are insistent on end-to-end automation, hang the amount of up front work and coupling it creates. And there are a lot of others on the other side of the debate, who just do the easiest thing that works and live with the risks.

Is there a reasoned answer to which side is best to land on?


5 Answers 5


We use git describe with version tags. The flow is basically:

  • create tag for the version we're working on (e.g. v1.1.2)
  • every build run git describe
  • when we ship, use the tag name

git describe provides the tag name, number of commits since the tag, and the hash of the tag. A sample tag looks like:


This has the benefit that developers get hashes, so if something breaks between builds, the developer can easily diff the changes. It's also stupid simple to manage; just have your team lead create and push the tag on a new bugfix branch and your build system takes care of the rest.

We strip the hash (and build number) because it makes it easier for users to understand our version numbers. We find that this gives us the best of both worlds, while still providing enough relevant info when engineering a release.

Currently, we have a slightly more complicated version of this, but the idea remains.

  • 1
    Just note: hash in it describe (last part of string) is not cset-id of tag, but hash of changeset, for which we get describe. In human-readable form v1.1.2-6-a3b27gae will be "Six changesets after changeset, tagged as v1.1.2-6, has short changeset-hash a3b27gae" Mar 25, 2013 at 23:49
  • @LazyBadger - Exactly. The hash for the tag itself is less useful, since you can easily git checkout v1.1.2 or list the tag's commit with git rev-list v1.1.2 | head -n 1.
    – beatgammit
    Mar 26, 2013 at 15:57

We used to be a SVN shop so this math was easy -- build number was the SVN rev and that was that. We tried to keep this going when we started moving to DCVSes and found that it failed for a few reasons.

First, who knows if rev 69bc333bc8d8 is before, after or concurrent with rev 25b0f0d1052c? There is very little context compared to the SVN system when you at least knew 101 was after 100. Second, the nature of DCVS source control makes things non linear in many ways when subsequent builds might not be advancing the same ball.

We finally settled on using a build server to distribute build numbers to things since it had the right visibility and ability to handle it.


I use the following scheme for a visual studio build system of a C# DLL to automatically generate version numbers (We have historically had issues with deployments not being performed correctly so needed a clean way of guaranteeing the deployment of the correct version happened).

  • Major - Hard coded 1, typically determined by business side
  • Minor - Hard coded 0, typically determined by business side
  • Revision - Number of days since Jan 1, 2010 (or any other arbitrary start date)
  • Build - Half the number of seconds since Midnight (Since it is a 16 bit unsigned number)

Note that this assumes you have 2 fungible 16-bit unsigned numbers to play with. Creating an equivalent system that uses smaller numbers could be done as well.

Also note that non-numeric fields can be helpful if you can attach them as meta-data. For instance adding the git version number as a the Informational Version number.


I'm directly linking the output of git status, log and diff into the executable. Then there is an option to print that. The advantage is that you are not only able to figure out which branch your binary was build from, but also which uncommitted source code changes are included. Please see:


You should be able to use those 3 files to make your own SCM state lib thing.


I would recommend the use of Autorevision.

You can get output in a variety formats, for example a c style header.

There are also a few examples (in the contribs dir) of how you can hook things up so that no matter who is building and how they are doing it they will always get the same version information, even if they are building from a tarball.

Also, since in addition to git Autorevision works with svn and hg it makes easier to switch away from svn without having to change too much once you have it set up.

  • Unfortunately Autorevision documentations seems not to give any recommendation. What information from the Autorevision generated header do you use/combine to build a unique and unambiguous software version string? Aug 7, 2016 at 21:59
  • It depends on how human readable you want it: <VCS_TAG>-<VCS_SHORT_HASH>, <VCS_TAG>-<VCS_TICK> or even <VCS_ACTION_STAMP> should all work. If you want a full list of what each of those symbols are I would suggest checking out the man page.
    – dak180
    Aug 8, 2016 at 12:01

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.