When you use TeamCity to build a project with multiple branches, it’s desirable to have different build numbers depending on the branch. For example, instead of simple TeamCity build numbers like 15
, 16
, and so on, you might have:
- Branch
master
:1.6.15
. - Branch
release-1.5
:1.5.15
(major/minor build from branch name). - Branch
develop
:2.0.15
(different minor build). - Branch
feature-rainbows
:2.0.15-rainbows
(feature branch as a tag).
Here’s how it looks:
Handling a branching workflow like GitFlow, and using these version formats, turns out to be pretty easy with TeamCity, and in this blog post I’ll show you how. Your own versioning strategy is likely to be different, but hopefully this post will get you started.
Background
First, there are two built-in TeamCity parameters that we care about:
build.counter
: this is the auto-incrementing build counter (15 and 16 above).build.number
: this is the full build number. By default, it is%build.counter%
, but it can be more complicated.
The format of build.number
and value of build.counter
is defined in the TeamCity UI:
However, you can also set it dynamically during the build, using service messages. That is, your build script can write the following text to stdout:
##teamcity[buildNumber '1.1.15']
This will override the build number, and the new value will then be passed to the rest of the steps in the build.
Putting it together
Depending on whether the branch name is master
or develop
, we will use different major/minor build numbers. To do this, we’re going to define two parameters in TeamCity. These need to be system parameters in TeamCity so that they can build scripts.
To dynamically set the build number based on the branch name, I’m going to add a PowerShell script step as the first build step in my build:
Finally, here’s the PowerShell script:
# These are project build parameters in TeamCity
# Depending on the branch, we will use different major/minor versions
$majorMinorVersionMaster = "%system.MajorMinorVersion.Master%"
$majorMinorVersionDevelop = "%system.MajorMinorVersion.Develop%"
# TeamCity's auto-incrementing build counter; ensures each build is unique
$buildCounter = "%build.counter%"
# This gets the name of the current Git branch.
$branch = "%teamcity.build.branch%"
# Sometimes the branch will be a full path, e.g., 'refs/heads/master'.
# If so we'll base our logic just on the last part.
if ($branch.Contains("/"))
{
$branch = $branch.substring($branch.lastIndexOf("/")).trim("/")
}
Write-Host "Branch: $branch"
if ($branch -eq "master")
{
$buildNumber = "${majorMinorVersionMaster}.${buildCounter}"
}
elseif ($branch -eq "develop")
{
$buildNumber = "${majorMinorVersionDevelop}.${buildCounter}"
}
elseif ($branch -match "release-.*")
{
$specificRelease = ($branch -replace 'release-(.*)','$1')
$buildNumber = "${specificRelease}.${buildCounter}"
}
else
{
# If the branch starts with "feature-", just use the feature name
$branch = $branch.replace("feature-", "")
$buildNumber = "${majorMinorVersionDevelop}.${buildCounter}-${branch}"
}
Write-Host "##teamcity[buildNumber '$buildNumber']"
Now that %build.number%
is based on the branch, your TeamCity build has a consistent build number that can then be used in the rest of your build steps. If you are using OctoPack, for example, the build number can be used as the value of the OctoPackPackageVersion
MSBuild parameter so that your NuGet packages match the build number.
Learn more
- Documentation: Integrate TeamCity and Octopus Deploy
- How to build pipelines and package applications for .NETCore
- Deploying TeamCity to Kubernetes
- Integration 101: Octopus and Build Servers
Related posts

Configuration Management with Octopus and PowerShell DSC
At Octopus Deploy we keep rattling on about how Octopus is API first. One of the benefits of being API first is that you can do anything that the Octopus UI does via web requests.

Tenant aware lifecycles
Let's take a look at how the inclusion of tenants influences the deployment Lifecycle process.

The Power of Configuration Transformations
It is a common scenario to perform different configuration transforms depending on the Environment that is being deploying to.