A build number is an identifying number assigned to a software release. The software displays the build number to the user in some fashion, such as in an About dialog. Subsequent releases should have increasing build numbers (but the build numbers don’t have to be contiguous), so you can say to a customer, "If you have build number N or higher, then you have the fix to that bug."

A commit to Subversion increments the repository revision number which identifies the state of the repository after applying the changes. If your source code is in Subversion, an obvious choice for the build number is the repository revision number checked out to build the release.

Deriving a build number from Git is not so obvious. The SHA-1 hash Git uses to identify each commit does not have a naturally ordering. You can’t tell just by looking at the SHA-1 hashes of two commits which commit comes after the other. So using the SHA-1 hash as the build number doesn’t make sense.

I’m going to outline a scheme using the git describe command, which counts how many commits are traversed to reach a tag. Create a tag pointing to some commit in the history. A likely candidate is the first commit in the repository. The build number is the number of commits between the current commit and the tag. To guarantee an increasing build number, all these conditions must be satisfied:

  1. Make all releases from the same Git repository.

  2. Make all releases from the same branch.

  3. Do not rewrite history.

Create a tag named build pointing to the first commit in the repository:

% git tag -a -m "For calculating build number" build `git rev-list HEAD | tail -1`

The git describe command by default searches to the nearest tag. Use the --match option to specify the tag name. Trying the command, you see your build script needs to extract the build number from the output (12 in the example):

% git describe --match build
build-12-g53e5502

This Ant task extracts the build number into the BUILD_NUMBER property:

<exec executable="git" outputproperty="BUILD_NUMBER">
  <arg value="describe"/>
  <arg value="--match"/>
  <arg value="build"/>
  <redirector>
    <outputfilterchain>
      <tokenfilter>
        <replaceregex pattern="^[^-]+-" replace=""/>
        <replaceregex pattern="-.+$" replace=""/>
      </tokenfilter>
   </outputfilterchain>
 </redirector>
</exec>

This CMake script parses the build number into the BUILD_NUMBER variable:

find_package(Git)
if(GIT_FOUND)
    execute_process(
            COMMAND ${GIT_EXECUTABLE} describe --match build
            OUTPUT_VARIABLE DESCRIBE_BUILD
            OUTPUT_STRIP_TRAILING_WHITESPACE)
    string(REGEX MATCH "[0-9]+" BUILD_NUMBER ${DESCRIBE_BUILD})
endif()