Git Versioning

Git can be used for versioning. It is great, because version number autoincrements with every check-in. Even if you branch, each version will remain unique. Version label is easy to control with git tags.

Advantages:

Depending on your goal it is a PRO or CON:

Overview

Git versioning uses most recent tag of current branch. Thus, you have to have at least one tag. Tag text can be anything.

Run git command:

git describe --tag

If the most recent tag is “1.0” and current checkout is 11 commits after ‘1.0’ tag, then version will look like the following:

1.0-11-gd5653d4

where

If there is more than one tag, then most recent tag is used.

Versioning in .NET Core 2

.NET Core is a bit different from previous generation of .NET like Microsoft .NET 4.

In previous .NET versions versioning was controlled within AssemblyInfo.cs file or through direct specification of version in csproj file (if I recall correctly). Thus, the procedure would have to be updated to work with one of those locations.

.NET Core there is more than one way to do things. Here is one way.

The following is not a complete process and tuning is most likely required. It reconstructed from real life setup without spending additional verification time.

Directory.Build.Props

Create file Directory.Build.Props in the same directory as solution file with the following content. This file is loaded by .NET Core during compilation.

<Project>
    <PropertyGroup>
        <Version></Version>
    </PropertyGroup>
</Project>

It is assumed that csrpoj file is in a subdirectory of the sln file.

Update-BuildProps.ps1

Create a script to update content of the template file with the following content:

param (
    [Parameter(Mandatory=$true)]
    [string] $PropsFile
)

$v = git describe --tag
Write-Output "Setting $PropsFile to version $v"
(Get-Content $PropsFile) -replace "<Version>(.*)</Version>","<Version>$v</Version>" | Set-Content $PropsFile

The script can be called with command:

&.\Update-BuildProps.ps1 -PropsFile .\Directory.Build.Props

Directory.Build.targets

Now we need to ensure that .NET Core build process updates Directory.Build.Props file prior to project compilation phase.

To accomplish that we create Directory.Build.targets file in the same directory as csproj file.

The following is an example content:

<?xml version="1.0" encoding="utf-8"?>
<Project>
    <Target Name="UpdateVersion" BeforeTargets="Build">
        <Message Importance="High" Text="Updating version" />
        <Copy SourceFiles=".\Directory.Build.Props" DestinationFolder="$(ProjectDir).." />
        <Exec WorkingDirectory="$(ProjectDir).." Command="powershell.exe -NonInteractive –ExecutionPolicy Unrestricted  -Command &quot;&amp;{ .\Update-BuildProps.ps1 -PropsFile Directory.Build.Props}&quot;" />
    </Target>
</Project>

The content above could be added to csproj, but by placing it outside of csproj file we make it easy to separate automatically maintained csproj from manually controlled parts of it.

The target above is executed before Build target. .NET Core then uses specially named file to load version information about the project.

Multiple .NET Projects setup

Ideally the solution above is placed into a csproj that has no actual code in it. Then every other project is made as a dependency of this project, which ensures proper version update for each individual project without maintaining code duplication.

This potentially imposes rule that all projects must be at the same level. Subject to practical verification.

Loading Version from C# code

The following code fragment is in ASP.NET context:

string appVersion = typeof(Startup).GetTypeInfo()
    .Assembly.GetCustomAttribute<AssemblyInformationalVersionAttribute>().InformationalVersion;
string runtimeVersion = typeof(RuntimeEnvironment).GetTypeInfo()
    .Assembly.GetCustomAttribute<AssemblyFileVersionAttribute>().Version;

Shell Script to get Version

Script get\_version.sh

#!/bin/sh

git describe --tag | head -n 1

Returns version without new line character.

Loading Version in Meson Build System

Meson configuration file:

confData = configuration_data();
confData.set(
  "version",
  run_command("git", ["describe", "--tag"])
    .stdout()
    .strip()
);

Versioning in C

In C we usually have a header file that has a DEFINE with version number string:

#!/bin/sh

echo \#define VERSION_STR \"`get_version.sh`\" > config.h

Versioning in GO Language

Version number can be passed during compilation with:

# GNUmakefile syntax, Linux shell environment

go build -ldflags "-X 'main.buildStamp=$(buildStamp)'" main.go

To use define global variable with the same name:

var (
    buildStamp = "manual build"
)
func main() {
    log.Printf("Build Version: %s\n", buildStamp)
}

Complete Example

Versioning in JavaScript

Use process.env.