Is there a way to make git auto generate a version number file for a --version option?

23,154

Solution 1

See nice solution in here: https://coderwall.com/p/mk18zq/automatic-git-version-tagging-for-npm-modules

Basically do it the other way around. Create a text file or header file. Lets say: Version.h:

#define VERSION 10.1.2

And create post-commit hook which looks for changes in the file. To deploy: modify the version and commit the file. The hook will create a matching tag.

Solution 2

I know this question is old, but I just came across it because I'm trying to do the same thing. The one other answer here shows how to create a new Git tag every time a version file changes, but I and the OP want to do the reverse: Update a code file to contain a new version number every time I create a new Git tag for a "release." Here's how I did it in my C++ project:

First, create a header file called, for example, include/myproj/git_version.hpp that defines some constants:

#pragma once
namespace myproject {
extern const int MAJOR_VERSION;
extern const int MINOR_VERSION;
extern const int PATCH_VERSION;
extern const int COMMITS_AHEAD_OF_VERSION;
extern const char* VERSION_STRING;
extern const char* VERSION_STRING_PLUS_COMMITS;
}

Second, create a pre-commit hook (.git/hooks/pre-commit) that generates the corresponding .cpp file defining the constants, using the output of git describe:

#!/bin/bash

version_regex='v([0-9]+)\.([0-9]+)\.?([0-9]*)-([0-9]+)-g([0-9|a-z]+)'
git_string=$(git describe --tags --long)

if [[ $git_string =~ $version_regex ]]; then
    major_version="${BASH_REMATCH[1]}"
    minor_version="${BASH_REMATCH[2]}"
    patch_version="${BASH_REMATCH[3]}"
    commits_ahead="${BASH_REMATCH[4]}"
else
    echo "Error: git describe did not output a valid version string. Unable to update git_version.cpp" >&2
    exit 1
fi

version_num="${major_version}.${minor_version}.${patch_version}"
version_num_plus_commits="${version_num}+${commits_ahead}"

# Working directory of a git hook is always the root of the repo
cat > $(pwd)/src/git_version.cpp <<EOM
#include <myproject/git_version.hpp>

namespace myproject {
const int MAJOR_VERSION = $major_version;
const int MINOR_VERSION = $minor_version;
const int PATCH_VERSION = $patch_version;
const int COMMITS_AHEAD_OF_VERSION = $commits_ahead;
const char* VERSION_STRING = "${version_num}";
const char* VERSION_STRING_PLUS_COMMITS = "${version_num_plus_commits}";
}
EOM

git add $(pwd)/src/git_version.cpp

Note that the updated version of the git_constants.cpp file will be included as part of the commit, so any commit based on a new tag will also include a constants file reflecting the version in that tag.

This isn't perfect, because it requires you to create a new commit to update the constants file even if all you want to do is create a new tag (which otherwise wouldn't require a new commit). On the other hand, it does allow your in-code version number to track the number of commits, which is more fine-grained than the tagged versions alone.

Share:
23,154
os x nerd
Author by

os x nerd

Updated on November 16, 2020

Comments

  • os x nerd
    os x nerd over 3 years

    I have a project that is moving out of the alpha phase and that I'm ready to start releasing regularly. I know GitHub has a 'magic' release button but I generally don't like 'magic' features that I don't know exactly what they do:

    https://github.com/blog/1547-release-your-software

    As far as I can tell this 'magic' release feature on GitHub just creates a tag on the source repository for a certain state of the code or uses an existing tag. According to that link the tag names must reflect the semantic version number i.e. Major.Minor.Patch ex: v10.1.2 or some thing like that.

    Generally the accepted Git way to do releases seems to be to simply create tags. What I'd like to do is for Git to automatically create some sort of file in my code tree named version.txt or version.h file that contains the name of the git tag I created so that this file can be automatically sourced when the user issues myporgram --version on the command line. Preferably I'd like an auto generated header file since this gets integrated into the binary when the program is built. Is there some way to do this automatically or do I have to automatically pipe the tag number into the file before I issue the git tag command?

  • nick fox
    nick fox almost 8 years
    Can this be done the other way round? Can a post-commit hook update the text file with an incrementing version number or simply the commit number?
  • Michał Marszałek
    Michał Marszałek about 4 years
    I have done exactly the same. But not in .git/hooks but in CmakeList.txt I check and change file if commit is changed in build time. As i ignored version file. It is perfect, as long as someone build it from git and not from zip.