Ensuring unique build number while using git flow and continuous integration

In the iOS world, you want to keep you build number unique (CFBundleVersion). When submitting an app to the App Store, Apple will check that your have not submitted a build with the same number before. The build number also needs to be greater than your previous build numbers. Else Apple will reject it.

So how do you keep this number straight when using a git branching model?

You can obviously keep track of the build number by hand and increment it yourself, but I find this cumbersome. You can write a script that will bump your build number every time you build in Xcode, but in my experience that starts to break down when you have multiple developers building different releases which are each on their own branch.

So today I'll walk you through a process where build number are kept in a central location so that when you create a new build you can always be sure your build number is unique.

First off, you need to pick which branch will hold the truth. In this exemple I'll use develop.

The first task when creating a new build, will be to go check on develop what the latest build number is and increment it.

# the truth for the current bundle version is on develop, switch branch and get the number
# but first save the branch we are currently on to be able to come back
BUILD_GIT_BRANCH=$(git rev-parse --abbrev-ref HEAD)

# switch branch 
git checkout develop

# get the current build number from the plist
BUNDLE_VERSION=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "app/Info.plist")

# bump and save the bundle version

Now that the new build number is known, we can go back to the release branch and save that change there.

# switch back to the branch we're building
git checkout $BUILD_GIT_BRANCH

# save the new bundle version in info.plist
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $BUNDLE_VERSION" "app/Info.plist"

echo "Build number set to: $BUNDLE_VERSION"

But wait we are not done. You can build the application here. But if we don't commit those changes and push them to git, it will be like we did not do anything. Also, since we want the develop branch to hold the truth regarding the build number, we have to save that build number there too.

I like to only save that new build number if the build actually succeeded. In which case I run the following script.

### add the change to the git index
git add app/Info.plist

# give a nice commit message
git commit -m "Bumping version"

### push changes to server for the release branch
# get the current branch
git rev-parse --abbrev-ref HEAD

# push all changes
git push --set-upstream origin $GIT_BRANCH

### cherry pick the last commit from the release branch to develop (commit with the version bump)
# first change to the develop branch
git checkout develop

#cherry pick (--strategy-option theirs forces to accept the change coming in over what is already here)
git cherry-pick $GIT_BRANCH --strategy-option theirs

# push change to develop
git push origin develop

#go back to original branch so we can keep the build process going
git checkout $GIT_BRANCH

Add some error handling and you are on your way.