Jun 9, 2010

Automate version numbering using Git

Anar here...

Since the time I moved from SVN to Git, I was looking for a convenient and automated way to build version numbers for my projects. Same as always, it appears to be very easy with Git ;)

So, coming to the subject. Every time I make a stable release, I create a tag object in git with "git tag -a vX.Y".
Now using "git describe --abbrev=4 HEAD" I can get a canonical version number, something like this: vX.Y-NN-SSSS, where: vX.Y is the latest tag, NN is a number of commits since the tag and SSSS is object's hash or just vX.Y if I would check out an exactly released tag.

The possible workflow could be the following:
  1. Check that project's git repo. is accessible. This is a normal case for developers builds (see #2). If it is a user who runs the build from projects's source tarball, than the repo will be inaccessible (see #3).
  2. If the repo is accessible, use "git describe" to get an annotated version number. Process some needed customizations of the version string (for example, change '-' to '.' and remove leading 'v'). Write the version string to a version file, which will be distributed in source tarballs.
  3. If the repo is inaccessible, just read the version string from the version file or use a default one.
Simple is that...

It is much easer now to maintain versioning. Every stable release, which is done after a tagging, will be named as a tag name. For example, if you have tagged v2.2, than this algorithms will return a "2.2" as a version of the project. But all nightly releases or patch releases will get additional info, like "2.2-110-gede7". Using this information you can also easily find out what exactly were changed by asking git log or git describe and giving them a version string as a parameter.

There is no need now to have 3 sections in a version string when tagging: Major.Minor.Patch. Since all patch releases will get a patch (commit) counter automatically, like: "2.2.110.ssss" and accordingly a stable release will be just "2.2".

Well I use cmake as a build system for my projects, it was therefore easer for me to implement the algorithm in the CMakeLists.txt - a build rules file. One can do the same using an external shell script or something like that.
This is what I wrote on short notice:
if( EXISTS "${CMAKE_SOURCE_DIR}/.git" )

execute_process(COMMAND git describe --abbrev=4 HEAD
COMMAND sed -e "s/-/./g"
OUTPUT_VARIABLE POD_VERSION
OUTPUT_STRIP_TRAILING_WHITESPACE)
# remove leading "v"
string(REGEX REPLACE "^v(.*)" "\\1" POD_VERSION ${POD_VERSION})
execute_process( COMMAND bash -c "echo \"${POD_VERSION}\" > ${CMAKE_SOURCE_DIR}/etc/version" )

else( EXISTS "${CMAKE_SOURCE_DIR}/.git" )

execute_process(COMMAND cat ${CMAKE_SOURCE_DIR}/etc/version
OUTPUT_VARIABLE POD_VERSION
OUTPUT_STRIP_TRAILING_WHITESPACE)

endif( EXISTS "${CMAKE_SOURCE_DIR}/.git" )
This implementation returns X.Y for stable releases and X.Y.Z.SS for patch releases and nightly builds.

UPDATE: By the way, I've just came across a GIT-VERSION-GEN script, which is used in the Git distributions. It does exactly this task, but a bit differently. It's very much recommend to check it out.

7 comments:

Anonymous said...

Thanks for idea. This leaves one problem: when you commit something which doesn't change CMakeLists, the version string won't update if you just rebuild the project using "make" command. How do you cope with such problem?

Anar Manafov said...

Hi Man,

indeed, to update the version string you need to remove everything in your build folder, I prefer out-of-source builds, and rebuild (cmake) it again.
This is by the way perfectly fits into the concept of versioning, I think.

Your users get the "version" file with the source tarball, so they don't need .git or something.
But you need to distclean if you committed something and need a version string updated.

But if you really need to generate the version string after you push (or commit), you can write a custom target (add_custom_target) and you need your "make all" to be depended on that target (add_dependencies). This should work.
Anyway the essential part, which Git is giving us will not change at all ;) I mean, I really love Git :)

Miami Vending Machines said...

Just read the version string from the version file or use a default one.
Miami Vending Machines

oakleyses said...

louboutin pas cher, nike free, polo ralph lauren outlet online, louis vuitton, polo outlet, nike air max, longchamp pas cher, jordan shoes, ray ban sunglasses, gucci handbags, tiffany and co, jordan pas cher, cheap oakley sunglasses, louis vuitton outlet, oakley sunglasses, christian louboutin uk, nike free run, sac longchamp pas cher, nike air max, oakley sunglasses, longchamp outlet, prada outlet, kate spade outlet, longchamp outlet, louis vuitton, oakley sunglasses wholesale, polo ralph lauren, longchamp outlet, christian louboutin outlet, chanel handbags, louis vuitton outlet, tiffany jewelry, michael kors pas cher, replica watches, replica watches, ray ban sunglasses, ugg boots, burberry pas cher, tory burch outlet, nike roshe, oakley sunglasses, louis vuitton outlet, ray ban sunglasses, prada handbags, ugg boots, nike outlet, christian louboutin shoes, uggs on sale, christian louboutin

oakleyses said...

guess pas cher, north face, lululemon canada, michael kors, michael kors outlet online, true religion outlet, oakley pas cher, nike free uk, michael kors outlet, abercrombie and fitch uk, hollister uk, true religion outlet, hollister pas cher, ray ban pas cher, polo lacoste, north face uk, michael kors outlet online, coach outlet store online, ray ban uk, mulberry uk, burberry handbags, michael kors outlet, hogan outlet, nike blazer pas cher, nike air max, nike air max uk, true religion outlet, uggs outlet, coach outlet, nike air force, nike air max uk, sac hermes, uggs outlet, michael kors outlet, michael kors, michael kors outlet online, nike roshe run uk, vans pas cher, true religion jeans, replica handbags, ralph lauren uk, sac vanessa bruno, burberry outlet, nike tn, coach purses, new balance, michael kors outlet online, kate spade, timberland pas cher

oakleyses said...

hermes belt, hollister, lancel, abercrombie and fitch, chi flat iron, instyler, north face outlet, louboutin, asics running shoes, nfl jerseys, ferragamo shoes, new balance shoes, mont blanc pens, vans outlet, celine handbags, hollister clothing, mcm handbags, mac cosmetics, beats by dre, giuseppe zanotti outlet, converse outlet, nike air max, longchamp uk, oakley, reebok outlet, bottega veneta, nike air max, timberland boots, insanity workout, nike trainers uk, gucci, lululemon, baseball bats, soccer shoes, soccer jerseys, north face outlet, valentino shoes, wedding dresses, hollister, nike roshe run, vans, ray ban, babyliss, jimmy choo outlet, nike huaraches, p90x workout, ghd hair, ralph lauren, herve leger, iphone cases

oakleyses said...

ugg,uggs,uggs canada, barbour uk, moncler outlet, coach outlet, ugg,ugg australia,ugg italia, moncler, thomas sabo, canada goose, moncler outlet, links of london, canada goose outlet, juicy couture outlet, moncler uk, pandora jewelry, montre pas cher, marc jacobs, replica watches, louis vuitton, moncler, canada goose jackets, swarovski, pandora charms, canada goose outlet, toms shoes, moncler, swarovski crystal, doudoune moncler, louis vuitton, moncler, pandora jewelry, ugg, barbour, louis vuitton, hollister, canada goose outlet, karen millen uk, ugg pas cher, supra shoes, canada goose, juicy couture outlet, louis vuitton, wedding dresses, pandora uk, canada goose, ugg uk, canada goose uk, louis vuitton