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?
0
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:
v1.1.2-6-a3b27gae
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.
2
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:
https://github.com/colding/MercuryFIX/tree/master/stdlib/scm_state
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.
2