Semantic Versioning with GitVersion (GitFlow)

Raul Naupari - Aug 31 - - Dev Community

Versioning software artifacts (Assemblies, NuGet, or NPM packages) has been proved to be a challenging procedure. Today, Semantic Versioning is a practice that has been on the rise over the last few years, but how to apply it to your projects?. Here is were GitVersion come in place.

GitVersion is a tool that generates a Semantic Version number based on your Git history. The version number generated from GitVersion can then be used for various different purposes.

To test how GitVersion helps us get version numbers, today we are going to use GitFlow as a branching strategy. There are several ways to install GitVersion. Here we are using the .NET global tool option:

dotnet tool install --global GitVersion.Tool --version 5.*
Enter fullscreen mode Exit fullscreen mode

Let's create a new Git repository:

mkdir gitversion-giflow
cd .\gitversion-giflow\
git init
Enter fullscreen mode Exit fullscreen mode

Now it is time to see our first GitVersion command:

dotnet-gitversion init
Enter fullscreen mode Exit fullscreen mode

We are going thru the configuration process depending on the branch strategy mentioned before:

GitVersion init will guide you through setting GitVersion up to work for you

Which would you like to change?

0) Save changes and exit
1) Exit without saving

2) Run getting started wizard

3) Set next version number
4) Branch specific configuration
5) Branch Increment mode (per commit/after tag) (Current: )
6) Assembly versioning scheme (Current: )
7) Setup build scripts
Enter fullscreen mode Exit fullscreen mode

Select the option 2:

The way you will use GitVersion will change a lot based on your branching strategy. What branching strategy will you be using:

1) GitFlow (or similar)
2) GitHubFlow
3) Unsure, tell me more
Enter fullscreen mode Exit fullscreen mode

Select the option 1:

By default GitVersion will only increment the version of the 'develop' branch every commit, all other branches will increment when tagged

What do you want the default increment mode to be (can be overriden per branch):

1) Follow SemVer and only increment when a release has been tagged (continuous delivery mode)
2) Increment based on branch config every commit (continuous deployment mode)
3) Each merged branch against main will increment the version (mainline mode)
4) Skip
Enter fullscreen mode Exit fullscreen mode

Again option 1. As the last step, the wizard is going to show us to the first menu, select option 0 (Save changes and exit). Run the following command to see the current GitVersion configuration:

dotnet-gitversion /showconfig
Enter fullscreen mode Exit fullscreen mode

GitVersion added a file called GitVersion.yml.

mode: ContinuousDelivery
branches: {}
ignore:
  sha: []
merge-message-formats: {}

Enter fullscreen mode Exit fullscreen mode

Let's add the first commit with this file:

git add .
git commit -m 'initial commit' 
Enter fullscreen mode Exit fullscreen mode

Then run the dotnet-gitversion command:

{
  "Minor": 1,
  "Patch": 0,
  "PreReleaseTag": "",
  "PreReleaseTagWithDash": "",
  "PreReleaseLabel": "",
  "PreReleaseLabelWithDash": "",
  "PreReleaseNumber": null,
  "WeightedPreReleaseNumber": 60000,
  "BuildMetaData": 0,
  "BuildMetaDataPadded": "0000",
  "FullBuildMetaData": "0.Branch.master.Sha.17de78f354ad96dc7766c2d1242634cc903d8e2f",
  "MajorMinorPatch": "0.1.0",
  "SemVer": "0.1.0",
  "LegacySemVer": "0.1.0",
  "LegacySemVerPadded": "0.1.0",
  "AssemblySemVer": "0.1.0.0",
  "AssemblySemFileVer": "0.1.0.0",
  "FullSemVer": "0.1.0+0",
  "InformationalVersion": "0.1.0+0.Branch.master.Sha.17de78f354ad96dc7766c2d1242634cc903d8e2f",
  "BranchName": "master",
  "EscapedBranchName": "master",
  "Sha": "17de78f354ad96dc7766c2d1242634cc903d8e2f",
  "ShortSha": "17de78f",
  "NuGetVersionV2": "0.1.0",
  "NuGetVersion": "0.1.0",
  "NuGetPreReleaseTagV2": "",
  "NuGetPreReleaseTag": "",
  "VersionSourceSha": "17de78f354ad96dc7766c2d1242634cc903d8e2f",
  "CommitsSinceVersionSource": 0,
  "CommitsSinceVersionSourcePadded": "0000",
  "UncommittedChanges": 0,
  "CommitDate": "2022-05-22"
}
Enter fullscreen mode Exit fullscreen mode

There is a lot of information, but the one that we will use will be FullSemVer. Notice that GitVersion uses by default version number 0.1.0. Create a develop branch from master:

git checkout -b develop
Enter fullscreen mode Exit fullscreen mode

And then create a feature branch from develop:

git checkout -b feature/myFeatureA
Enter fullscreen mode Exit fullscreen mode

Run the command dotnet-gitversion /showvariable FullSemVer:

0.1.0-myFeatureA.1+0
Enter fullscreen mode Exit fullscreen mode

Add another commit (we are going to use empty commits by practicality):

git commit -m 'featurea A: change 1' --allow-empty
Enter fullscreen mode Exit fullscreen mode

Run again dotnet-gitversion /showvariable FullSemVer to see how the last number is moving:

0.1.0-myFeatureA.1+1
Enter fullscreen mode Exit fullscreen mode

Time to finalize the feature branch:

git checkout develop
git merge --no-ff feature/myFeatureA
git branch -d feature/myFeatureA
Enter fullscreen mode Exit fullscreen mode

Run dotnet-gitversion /showvariable FullSemVer:

0.1.0-alpha.2
Enter fullscreen mode Exit fullscreen mode

Create a new feature branch and repeat all steps until finalizing it and see how the version number changes in the develop branch:

0.1.0-alpha.4
Enter fullscreen mode Exit fullscreen mode

Run the command git log --oneline --graph to see the log history for the develop branch:

*   fe48f23 (HEAD -> develop) Merge branch 'feature/myFeatureB' into develop
|\
| * 4ad9aa8 featurea B: change 1
|/
*   20481b3 Merge branch 'feature/myFeatureA' into develop
|\
| * df2170f featurea A: change 1
|/
* 17de78f (master) initial commit
Enter fullscreen mode Exit fullscreen mode

Now it is time to create a release branch:

git checkout -b release/1.0.0 develop
Enter fullscreen mode Exit fullscreen mode

Run dotnet-gitversion /showvariable FullSemVer:

1.0.0-beta.1+0
Enter fullscreen mode Exit fullscreen mode

Add a commit to simulate a bug fix under the release branch:

git commit -m 'bug fix' --allow-empty
Enter fullscreen mode Exit fullscreen mode

And check the version number:

1.0.0-beta.1+1
Enter fullscreen mode Exit fullscreen mode

Assume that we want to release this branch to production:

git checkout master
git merge --no-ff release/1.0.0
git tag '1.0.0'
git checkout develop
git merge --no-ff release/1.0.0
git branch -d release/1.0.0
Enter fullscreen mode Exit fullscreen mode

Now running dotnet-gitversion /showvariable FullSemVer under master will see 1.0.0 because the tag tells GitVersion that this is the new version number. If you check the version number in the develop branch, GitVersion figures out 1.1.0-alpha.2 as a new value. Let's do a hotfix now:

git checkout master
git checkout -b hotfix/1.0.1 
Enter fullscreen mode Exit fullscreen mode

Add a commit:

git commit -m 'bug fix' --allow-empty
Enter fullscreen mode Exit fullscreen mode

Run dotnet-gitversion /showvariable FullSemVer:

1.0.1-beta.1+7
Enter fullscreen mode Exit fullscreen mode

And finalize a hotfix branch:

git checkout master
git merge --no-ff hotfix/1.0.1
git tag  '1.0.1'
git checkout develop
git merge --no-ff hotfix/1.0.1
git branch -d hotfix/1.0.1
Enter fullscreen mode Exit fullscreen mode

Run dotnet-gitversion /showvariable FullSemVer under master branch to see 1.0.1 as version number.

To see more examples using GitFlow, you can check the official documentation here.

. . . . . . . . .