Kenneth Ballenegger

Angel Investor, Engineer, Startup Founder

The Ultimate Solution For Xcode Auto-Versioning With Git

After struggling with several suboptimal solutions for years, I have finally come to find the best Xcode versioning solution for git users. First off, tip of the hat to Marcus Zarra and Johannes Gilger for posting their solutions, which inspired me in my search for the ultimate solution.

A couple advantages that make this solution better than those I’ve used in the past:

  • It’s completely filesystem independent. Save for the git binary location requirement, this would work across any Mac with no additional setup. (It should also be quite easy to edit the script to detect git using which.)
  • It works across clones and systems.
  • Because the version is the current git SHA1 hash, it always refer to a specific commit you can get back to when debugging later.
  • It processes the version number at every build immediately. Some of the solutions I’ve used in the past required a double-build, because of Xcode’s tendency to run scripts after the preprocessor. Not so here.
  • No duplication of code in projects with multiple targets.
  • Works for iPhone, Mac App Store and Mac apps.

So without further ado, my solution: I rely on an external target of type Shell Script which I call Versioning. Every other target sets Versioning as a Direct Dependency, ensuring its script is run before the preprocessor. Versioning contains the following Run Script:

cd "$PROJECT_DIR"
VERSION=`/usr/local/bin/git rev-parse --short HEAD`

cd "$PROJECT_TEMP_DIR"
echo "#define GIT_VERSION $VERSION" > revision.prefix

cd "$PROJECT_DIR"
touch Info.plist

In Info.plist, the CFBundleShortVersionString is set to GIT_VERSION. In the project’s main build settings, Preprocess Info.plist is turned on and Info.plist Preprocessor Prefix File is set to $PROJECT_TEMP_DIR/revision.prefix.