Gitversion: [BUG] GitVersion calculating wrong version when building a tag

Created on 3 Feb 2020  路  36Comments  路  Source: GitTools/GitVersion

I am running GitVersion 5.1.3 on Windows Server 2019 connecting to BitBucket Cloud, and using TeamCity and its GitVersion metarunner to generate version numbers.

With a particular GitFlow repo that I have, I am building on support/12.4 and everything is great, GitVersion calculates the version number as e.g. 12.4.11-beta0003. However, when I tag that commit which I have just built as e.g. 12.4.12, then GitVersion completely ignores that tag and grabs the version number from develop, giving me a tag something like 13.4.0-tags-12-4-11.1+8.

It only does this on the build agent; when I run GitVersion on my desktop then it calculates the version correctly.

bug

Most helpful comment

I have found another solution which is less invasive.
TaggedCommitVersionStrategy now prefers to return only the versions of tags on the current commit. If there aren't any, it will return the tags from history.
That makes all tests (incl the new one) pass for me locally. PR #2413 updated.

All 36 comments

If you define the environment variable TEAMCITY_VERSION, are you able to reproduce the behaviour locally as well? If so, are you able to step through the GitVersion codebase to see why it takes another route when the environment variable is defined vs. when it's not?

https://github.com/GitTools/GitVersion/blob/f0e5275d974d7bd694dad8dce0ac85e57e33b19f/src/GitVersionCore/BuildServers/TeamCity.cs#L13

It doesn't look like it, no. If I remote into the build agent and run gitversion there, then it too produces the unexpected values.

However, I did notice that if I try to build the tag directly then it give me the incorrect version numbers, but if I build the support/12.4 branch _after_ I have created the tag, then it builds correctly.

So is that a bug in GitVersion, or a bug in how am I using it with Git and TeamCity?

I too see this (or a similar) problem on AppVeyor. I'm also able to reproduce it by checking out the tag locally.

I expected the version to be v1.14.3, but instead it becomes v1.15.0.
This doesn't happen consistently for all tags, and I have not succeeded in finding a pattern.
There are however _no 1.15 tags_. It is the current version on our develop branch though.

$ git checkout -b v1.14.3 v1.14.3 # checking out tag v1.14.3 to branch with the same name
$ gitversion -version
5.1.3+Branch.master.Sha.bef8ebc0b62b3ddd0cdafe09b66d68bbfcaf90d5
$ gitversion
{
  "Major":1,
  "Minor":15,
  "Patch":0,
  "PreReleaseTag":"v1-14-3.1",
  "PreReleaseTagWithDash":"-v1-14-3.1",
  "PreReleaseLabel":"v1-14-3",
  "PreReleaseNumber":1,
  "WeightedPreReleaseNumber":1,
  "BuildMetaData":227,
  "BuildMetaDataPadded":"0227",
  "FullBuildMetaData":"227.Branch.v1.14.3.Sha.937964fc273dfb4b57228d9c203fd90d261de6a7",
  "MajorMinorPatch":"1.15.0",
  "SemVer":"1.15.0-v1-14-3.1",
  "LegacySemVer":"1.15.0-v1-14-3-1",
  "LegacySemVerPadded":"1.15.0-v1-14-3-0001",
  "AssemblySemVer":"1.15.0.1",
  "AssemblySemFileVer":"1.15.0.0",
  "FullSemVer":"1.15.0-v1-14-3.1+227",
  "InformationalVersion":"1.15.0-v1-14-3.1+227.Branch.v1.14.3.Sha.937964fc273dfb4b57228d9c203fd90d261de6a7",
  "BranchName":"v1.14.3",
  "Sha":"937964fc273dfb4b57228d9c203fd90d261de6a7",
  "ShortSha":"937964f",
  "NuGetVersionV2":"1.15.0-v1-14-3-0001",
  "NuGetVersion":"1.15.0-v1-14-3-0001",
  "NuGetPreReleaseTagV2":"v1-14-3-0001",
  "NuGetPreReleaseTag":"v1-14-3-0001",
  "VersionSourceSha":"decc5a0b5613f46162a7458439122c47a767da77",
  "CommitsSinceVersionSource":227,
  "CommitsSinceVersionSourcePadded":"0227",
  "CommitDate":"2020-01-30"
}

I am also seeing this with version 5.1.3. It seems to be a regression, as it works correctly in 5.1.2.

It would be interesting to find which commit or PR introduced this change, because it means we don't have tests that cover this use-case, again meaning the fact that this used to work might have been more by accident than by explicit design. I agree that checking out a tagged commit should give the build the version number of the tag, though. A PR with a RepositoryFixture test that proves this is a problem would be helpful. Even more helpful would be fixing the same problem in the PR. 馃槄

I can confirm that this is happening on Azure DevOps with GitVersion.Tool 5.2.4 as well. I tried to reproduce it locally and I can when I do exactly what Azure DevOps does:

TF_BUILD=1
BUILD_SOURCEBRANCH=refs/tags/1.0.2
git init workdir
cd workdir
git remote add origin https://github.com/myrepositoryurl
git fetch --force --tags --prune --progress --no-recurse-submodules origin
git checkout --force 09ef997d4455f25fd2307864c235c12339f63f68

Then I run GitVersion using the dotnet tool:

dotnet gitversion /output buildserver

Output:

2020-04-06T04:36:36.7242293Z ##[section]Starting: Generate Version using GitVersion
2020-04-06T04:36:36.7370577Z ==============================================================================
2020-04-06T04:36:36.7370978Z Task         : PowerShell
2020-04-06T04:36:36.7371303Z Description  : Run a PowerShell script on Linux, macOS, or Windows
2020-04-06T04:36:36.7371629Z Version      : 2.165.0
2020-04-06T04:36:36.7371887Z Author       : Microsoft Corporation
2020-04-06T04:36:36.7372291Z Help         : https://docs.microsoft.com/azure/devops/pipelines/tasks/utility/powershell
2020-04-06T04:36:36.7372732Z ==============================================================================
2020-04-06T04:36:37.6567374Z Generating script.
2020-04-06T04:36:37.7311312Z ========================== Starting Command Output ===========================
2020-04-06T04:36:37.7603100Z ##[command]"C:\windows\System32\WindowsPowerShell\v1.0\powershell.exe" -NoLogo -NoProfile -NonInteractive -ExecutionPolicy Unrestricted -Command ". 'd:\a\_temp\974e9f77-dbfb-4839-97fb-1d366f13ceaa.ps1'"
2020-04-06T04:36:38.4952683Z INFO [04/06/20 4:36:38:49] Working directory: D:\a\1\s
2020-04-06T04:36:38.5185844Z INFO [04/06/20 4:36:38:51] Applicable build agent found: 'AzurePipelines'.
2020-04-06T04:36:38.5188548Z INFO [04/06/20 4:36:38:51] Branch from build environment: refs/tags/v1.0.2
2020-04-06T04:36:38.5202474Z INFO [04/06/20 4:36:38:52] Begin: Normalizing git directory for branch 'refs/tags/v1.0.2'
2020-04-06T04:36:38.5715111Z   INFO [04/06/20 4:36:38:55] One remote found (origin -> 'https://github.com/daneSchilling/Hugger').
2020-04-06T04:36:38.5723169Z   INFO [04/06/20 4:36:38:55] Skipping fetching, if GitVersion does not calculate your version as expected you might need to allow fetching or use dynamic repositories
2020-04-06T04:36:38.5725546Z   INFO [04/06/20 4:36:38:56] Creating local branch refs/heads/tags/v1.0.2 pointing at 09ef997d4455f25fd2307864c235c12339f63f68
2020-04-06T04:36:38.5990531Z   INFO [04/06/20 4:36:38:59] Creating local branch from remote tracking 'refs/remotes/origin/development'.
2020-04-06T04:36:38.6164602Z   INFO [04/06/20 4:36:38:61] Creating local branch from remote tracking 'refs/remotes/origin/master'.
2020-04-06T04:36:38.6203914Z   INFO [04/06/20 4:36:38:62] HEAD points at branch 'refs/heads/tags/v1.0.2'.
2020-04-06T04:36:38.6214748Z   INFO [04/06/20 4:36:38:62] End: Normalizing git directory for branch 'refs/tags/v1.0.2' (Took: 101.06ms)
2020-04-06T04:36:38.6223262Z   INFO [04/06/20 4:36:38:62] Project root is: D:\a\1\s\
2020-04-06T04:36:38.6223878Z   INFO [04/06/20 4:36:38:62] DotGit directory is: D:\a\1\s\.git
2020-04-06T04:36:38.6428308Z   INFO [04/06/20 4:36:38:64] Begin: Loading version variables from disk cache
2020-04-06T04:36:38.6438849Z     INFO [04/06/20 4:36:38:64] Cache file D:\a\1\s\.git\gitversion_cache\80A4A8D6BADA6BC21120AAD836AA0D8D188B9C01.yml not found.
2020-04-06T04:36:38.6439805Z   INFO [04/06/20 4:36:38:64] End: Loading version variables from disk cache (Took: 1.19ms)
2020-04-06T04:36:38.7384287Z   INFO [04/06/20 4:36:38:73] Using latest commit on specified branch
2020-04-06T04:36:38.7489436Z   INFO [04/06/20 4:36:38:74] No branch configuration found for branch tags/v1.0.2, falling back to default configuration
2020-04-06T04:36:38.7538401Z   INFO [04/06/20 4:36:38:75] Begin: Attempting to inherit branch configuration from parent branch
2020-04-06T04:36:38.7583794Z     INFO [04/06/20 4:36:38:75] HEAD is merge commit, this is likely a pull request using development as base
2020-04-06T04:36:38.7627385Z     INFO [04/06/20 4:36:38:76] Begin: Finding branch source of 'development'
2020-04-06T04:36:38.7732975Z     INFO [04/06/20 4:36:38:77] End: Finding branch source of 'development' (Took: 10.53ms)
2020-04-06T04:36:38.7772501Z     INFO [04/06/20 4:36:38:77] Begin: Getting branches containing the commit 'dfdc20730b50ffa72c4ed99633344f8ec5619825'.
2020-04-06T04:36:38.7773307Z       INFO [04/06/20 4:36:38:77] Trying to find direct branches.
2020-04-06T04:36:38.7774000Z       INFO [04/06/20 4:36:38:77] No direct branches found, searching through all branches.
2020-04-06T04:36:38.7776449Z       INFO [04/06/20 4:36:38:77] Searching for commits reachable from 'master'.
2020-04-06T04:36:38.7852704Z       INFO [04/06/20 4:36:38:78] The branch 'master' has a matching commit.
2020-04-06T04:36:38.7901544Z       INFO [04/06/20 4:36:38:78] Searching for commits reachable from 'origin/master'.
2020-04-06T04:36:38.7904074Z       INFO [04/06/20 4:36:38:78] The branch 'origin/master' has a matching commit.
2020-04-06T04:36:38.7918488Z     INFO [04/06/20 4:36:38:78] End: Getting branches containing the commit 'dfdc20730b50ffa72c4ed99633344f8ec5619825'. (Took: 8.73ms)
2020-04-06T04:36:38.7919550Z     INFO [04/06/20 4:36:38:78] Found possible parent branches: master, origin/master
2020-04-06T04:36:38.7920424Z     WARN [04/06/20 4:36:38:78] Failed to inherit Increment branch configuration, ended up with: master, origin/master
2020-04-06T04:36:38.7921139Z Falling back to development branch config
2020-04-06T04:36:38.7921895Z   INFO [04/06/20 4:36:38:78] End: Attempting to inherit branch configuration from parent branch (Took: 34.05ms)
2020-04-06T04:36:38.8139497Z   INFO [04/06/20 4:36:38:81] Running against branch: tags/v1.0.2 (09ef997d4455f25fd2307864c235c12339f63f68)
2020-04-06T04:36:38.8148341Z   INFO [04/06/20 4:36:38:81] Current commit is tagged with version 1.0.2, version calculation is for metadata only.
2020-04-06T04:36:38.8165023Z   INFO [04/06/20 4:36:38:81] 0 commits found between 09ef997d4455f25fd2307864c235c12339f63f68 and 09ef997d4455f25fd2307864c235c12339f63f68
2020-04-06T04:36:38.8212110Z   INFO [04/06/20 4:36:38:82] Begin: Calculating base versions
2020-04-06T04:36:38.8253879Z     INFO [04/06/20 4:36:38:82] Fallback base version: 0.1.0 with commit count source 228937ace12b076b6b1a2a53259c06ee634b9d97 (Incremented: None)
2020-04-06T04:36:38.8959335Z     INFO [04/06/20 4:36:38:89] Git tag 'v1.0.2': 1.0.2 with commit count source 09ef997d4455f25fd2307864c235c12339f63f68 (Incremented: None)
2020-04-06T04:36:38.8964069Z     INFO [04/06/20 4:36:38:89] Git tag 'v1.0.1': 1.0.1 with commit count source 4c9d51a4d9822acb54c35c73212164962f00b73d (Incremented: 1.1.0)
2020-04-06T04:36:38.9031426Z     INFO [04/06/20 4:36:38:90] Found multiple base versions which will produce the same SemVer (1.1.0), taking oldest source for commit counting (Git tag 'v1.0.1')
2020-04-06T04:36:38.9032433Z     INFO [04/06/20 4:36:38:90] Base version used: Git tag 'v1.0.1': 1.0.1 with commit count source 4c9d51a4d9822acb54c35c73212164962f00b73d (Incremented: 1.1.0)
2020-04-06T04:36:38.9033269Z   INFO [04/06/20 4:36:38:90] End: Calculating base versions (Took: 82.09ms)
2020-04-06T04:36:38.9041353Z   INFO [04/06/20 4:36:38:90] 4 commits found between 4c9d51a4d9822acb54c35c73212164962f00b73d and 09ef997d4455f25fd2307864c235c12339f63f68
2020-04-06T04:36:38.9047945Z   INFO [04/06/20 4:36:38:90] Using branch name to calculate version tag
2020-04-06T04:36:38.9053798Z   INFO [04/06/20 4:36:38:90] Begin: Getting version tags from branch 'refs/heads/tags/v1.0.2'.
2020-04-06T04:36:38.9077923Z   INFO [04/06/20 4:36:38:90] End: Getting version tags from branch 'refs/heads/tags/v1.0.2'. (Took: 2.34ms)
2020-04-06T04:36:38.9142544Z   INFO [04/06/20 4:36:38:91] Begin: Creating dictionary
2020-04-06T04:36:38.9194941Z   INFO [04/06/20 4:36:38:91] End: Creating dictionary (Took: 5.24ms)
2020-04-06T04:36:38.9237716Z   INFO [04/06/20 4:36:38:92] Begin: Storing version variables to cache file D:\a\1\s\.git\gitversion_cache\80A4A8D6BADA6BC21120AAD836AA0D8D188B9C01.yml
2020-04-06T04:36:38.9648521Z   INFO [04/06/20 4:36:38:96] End: Storing version variables to cache file D:\a\1\s\.git\gitversion_cache\80A4A8D6BADA6BC21120AAD836AA0D8D188B9C01.yml (Took: 40.98ms)
2020-04-06T04:36:38.9656958Z   INFO [04/06/20 4:36:38:96] Running on Windows.
2020-04-06T04:36:38.9657610Z   INFO [04/06/20 4:36:38:96] Applicable build agent found: 'AzurePipelines'.
2020-04-06T04:36:38.9663071Z Executing GenerateSetVersionMessage for 'AzurePipelines'.
2020-04-06T04:36:39.0138538Z Executing GenerateBuildLogOutput for 'AzurePipelines'.
2020-04-06T04:36:39.2279921Z ##[section]Async Command Start: Update Build Number
2020-04-06T04:36:39.3555390Z Update build number to 1.1.0-tags-v1-0-2.1+4 for build 21
2020-04-06T04:36:39.3555839Z ##[section]Async Command End: Update Build Number
2020-04-06T04:36:39.3557490Z ##[section]Finishing: Generate Version using GitVersion

However! If I remove the environment variable BUILD_SOURCEBRANCH, then the version is calculated correctly. I suspect the way that the build servers are using the source branches is the issue. The fix that smells like it caused the issue to happen is likely: #1743

The Fix for #1743 introduced a check wherein if the tagged version is semantically less than the pre-release version, it will use the pre-release version instead.

This normally wouldn't trigger, except that when the detached head is normalized by the build server code, it will create a branch called tags/v1.0.2 which doesn't have a matching configuration, and causes a pre-release version to be created.

This is ONLY an issue if your build automation triggers on the tag creation and tries to build the tag directly, not when you build the commit directly. The difference is the setting of the source branch through the environment variable, that then gets picked up by the build server adapter, overriding the current branch name.

I was trying to reproduce it in testing, but I'm not exactly sure how to model it. I can reproduce it like this:

TF_BUILD=1
BUILD_SOURCEBRANCH=refs/tags/1.0.2
git init workdir
cd workdir
git remote add origin https://github.com/daneSchilling/Hugger
git fetch --force --tags --prune --progress --no-recurse-submodules origin
git checkout --force 09ef997d4455f25fd2307864c235c12339f63f68

dotnet tool restore
dotnet gitversion /output buildserver

If you want to try it again, you need to do:

git checkout --force 09ef997d4455f25fd2307864c235c12339f63f68
git branch -d tags/1.0.2

to reset the setup so normalize will do its thing again.

I'm willing to work to setup a repro, but could use some advice on how to model it.

A reproduction! Awesome, @garoyeri! That looks like something that should be possible to reproduce in code, no? Have you tried reproducing the problem in a RepositoryFixture test?

I tried to do ~something like this~ this exactly, but it keeps passing (infuriatingly):

```c#
[Test]
public void ShouldGenerateTaggedVersionInBuildAutomation()
{
using var fixture = new RemoteRepositoryFixture(
path =>
{
Repository.Init(path);
Console.WriteLine("Created git repository at '{0}'", path);

                var repo = new Repository(path);
                repo.MakeCommits(5);
                repo.ApplyTag("1.0.1");
                repo.MakeCommits(5);
                var commit = repo.MakeACommit();
                repo.ApplyTag("1.0.2");

                Commands.Checkout(repo, commit.Sha);

                return repo;
            });

        GitRepositoryHelper.NormalizeGitDirectory(new NullLog(), new TestEnvironment(), fixture.LocalRepositoryFixture.RepositoryPath,
            new AuthenticationInfo(), noFetch: true, currentBranch: "refs/tags/1.0.2", isDynamicRepository: false);

        fixture.AssertFullSemver("1.0.2", targetBranch: "tags/1.0.2");
        fixture.AssertFullSemver("1.0.2", repository: fixture.LocalRepositoryFixture.Repository, targetBranch: "tags/1.0.2");
    }

```

Am I doing something wrong with the test setup or assertion?

Basically, I need to make a detached head, let the normalize happen, then try to calculate a version.

Hm, yeah. Are you able to invoke a normalization in the test?

I called the Normalization from the test (see the code above). But I suspect my real issue is in how I invoke the assertion, it seems to "fix" things by the time it generates a version number.

Does my test code accurately create a detached head situation that we're talking about here? And does my assertion simulate building from a tag? I'm not entirely sure because I'm not familiar with the testing helpers.

Ah yes, I see now. I will have to do some debugging myself to see whether the provided test behaves the way we need it to or not.

I've seen a similar bug to this myself, but when it surfaced my manual normalization of the Git repository didn't work because git fetch --tags did not receive the tag from which the build was initiated. I haven't experienced this exact behaviour anywhere else than on GitHub Actions, though.

This happened to me just now on GitHub Actions here (the generated version info can be found in the gitversion artifact).

seems to confirm @garoyeri s analysis...

Can you confirm whether the tag that initiated the build was available, @rose-a?

grafik

Affirmative!

GitHub seems to checkout the tag itself...

Strange... worked perfectly on the next tag...

Resolved version info:

{
  "Major":3,
  "Minor":0,
  "Patch":3,
  "PreReleaseTag":"",
  "PreReleaseTagWithDash":"",
  "PreReleaseLabel":"",
  "PreReleaseNumber":"",
  "WeightedPreReleaseNumber":"",
  "BuildMetaData":"",
  "BuildMetaDataPadded":"",
  "FullBuildMetaData":"Branch.tags-v3.0.3.Sha.29407e0d5b38f315333644d187d103cabed01822",
  "MajorMinorPatch":"3.0.3",
  "SemVer":"3.0.3",
  "LegacySemVer":"3.0.3",
  "LegacySemVerPadded":"3.0.3",
  "AssemblySemVer":"3.0.3.0",
  "AssemblySemFileVer":"3.0.3.0",
  "FullSemVer":"3.0.3",
  "InformationalVersion":"3.0.3+Branch.tags-v3.0.3.Sha.29407e0d5b38f315333644d187d103cabed01822",
  "BranchName":"tags/v3.0.3",
  "EscapedBranchName":"tags-v3-0-3",
  "Sha":"29407e0d5b38f315333644d187d103cabed01822",
  "ShortSha":"29407e0",
  "NuGetVersionV2":"3.0.3",
  "NuGetVersion":"3.0.3",
  "NuGetPreReleaseTagV2":"",
  "NuGetPreReleaseTag":"",
  "VersionSourceSha":"29407e0d5b38f315333644d187d103cabed01822",
  "CommitsSinceVersionSource":15,
  "CommitsSinceVersionSourcePadded":"0015",
  "CommitDate":"2020-04-19"
}

That is very weird, indeed.

I just noticed that having moved that repo from GitFlow to GitHubFlow between v3.0.2 and v3.0.3 probaply has circumvented that issue (i.e. not having a develop branch)...

Here's a log for a GitHub Actions build for refs/tags/v19.2.1 that got versioned 19.3.0-tags-v19-2-1.1+1. I have edited the log to remove business information; hopefully this has not harmed its usefulness.

https://gist.github.com/wjrogers/45a7c8699c36fd429a864906bcd6fe95

Thanks for that, @wjrogers. I believe the problem happens somewhere between these lines:

2020-05-06T01:02:11.3748886Z     INFO [05/06/20 1:02:11:37] Git tag 'v19.0.0-beta.1': 19.0.0-beta.1 with commit count source 760ee0438f53760aa219ad76a30d1ff684aae3be (Incremented: 19.0.0-beta.2)
2020-05-06T01:02:11.3987746Z     INFO [05/06/20 1:02:11:39] Found multiple base versions which will produce the same SemVer (19.3.0), taking oldest source for commit counting (Git tag 'v19.2.0')
2020-05-06T01:02:11.3999085Z     INFO [05/06/20 1:02:11:39] Base version used: Git tag 'v19.2.0': 19.2.0 with commit count source a91ada1bd49287c294564f5624aa46354083cf15 (Incremented: 19.3.0)
2020-05-06T01:02:11.3999964Z   INFO [05/06/20 1:02:11:39] End: Calculating base versions (Took: 1,268.03ms)
2020-05-06T01:02:11.4010814Z   INFO [05/06/20 1:02:11:40] 1 commits found between a91ada1bd49287c294564f5624aa46354083cf15 and aca733b407c8daaffe034727a39bb42ff6f6096b
2020-05-06T01:02:11.4019302Z   INFO [05/06/20 1:02:11:40] Using branch name to calculate version tag
2020-05-06T01:02:11.4033070Z   INFO [05/06/20 1:02:11:40] Begin: Getting version tags from branch 'refs/heads/tags/v19.2.1'.
2020-05-06T01:02:12.1480029Z   INFO [05/06/20 1:02:12:14] End: Getting version tags from branch 'refs/heads/tags/v19.2.1'. (Took: 744.40ms)

I think the problem is related to how GitVersion attempts to normalize the Git repository. With v6 and hopefully a new CLI, I hope normalization can be performed explicitly with gitversion normalize at the start of the build instead of happening invisibly and seemingly randomly during version calculation. That will at least help us pinpoint the problem and better focus our energy on how to fix it.

I'm having this exact issue in one of my repositories, using GitHub Actions - on initial tag it creates 2.4.3-tags-v2-4-2-0, with subsequent tags it works fine.

I am having the same issue. The tag 1.0.1-beta.1 build is creating a version 1.1.0-tags-1-0-1-beta-1.1.

Maybe it is related, I am also running it in a build agent and I a get different PreReleaseNumber running gitversion on my workstation.

Local gitversion v5.1.3 produces:

{
  "Major":1,
  "Minor":2,
  "Patch":0,
  "PreReleaseTag":"alpha.172",
  "PreReleaseTagWithDash":"-alpha.172",
  "PreReleaseLabel":"alpha",
  "PreReleaseNumber":172,
  "WeightedPreReleaseNumber":172,
  "BuildMetaData":"",
  "BuildMetaDataPadded":"",
  "FullBuildMetaData":"Branch.develop.Sha.2207f42429e92f104978eadf8d37e233e5dfa455",
  "MajorMinorPatch":"1.2.0",
  "SemVer":"1.2.0-alpha.172",
  "LegacySemVer":"1.2.0-alpha172",
  "LegacySemVerPadded":"1.2.0-alpha0172",
  "AssemblySemVer":"1.2.0.0",
  "AssemblySemFileVer":"1.2.0.0",
  "FullSemVer":"1.2.0-alpha.172",
  "InformationalVersion":"1.2.0-alpha.172+Branch.develop.Sha.2207f42429e92f104978eadf8d37e233e5dfa455",
  "BranchName":"develop",
  "Sha":"2207f42429e92f104978eadf8d37e233e5dfa455",
  "ShortSha":"2207f42",
  "NuGetVersionV2":"1.2.0-alpha0172",
  "NuGetVersion":"1.2.0-alpha0172",
  "NuGetPreReleaseTagV2":"alpha0172",
  "NuGetPreReleaseTag":"alpha0172",
  "VersionSourceSha":"fb4e61aaa34536a093b55c39017dfaceec400866",
  "CommitsSinceVersionSource":172,
  "CommitsSinceVersionSourcePadded":"0172",
  "CommitDate":"2020-08-27"
}

In the build agent GitVersion.Tool/5.3.7/x64/dotnet-gitversion produces:

{
  "Major":1,
  "Minor":2,
  "Patch":0,
  "PreReleaseTag":"alpha.159",
  "PreReleaseTagWithDash":"-alpha.159",
  "PreReleaseLabel":"alpha",
  "PreReleaseNumber":159,
  "WeightedPreReleaseNumber":159,
  "BuildMetaData":"",
  "BuildMetaDataPadded":"",
  "FullBuildMetaData":"Branch.develop.Sha.2207f42429e92f104978eadf8d37e233e5dfa455",
  "MajorMinorPatch":"1.2.0",
  "SemVer":"1.2.0-alpha.159",
  "LegacySemVer":"1.2.0-alpha159",
  "LegacySemVerPadded":"1.2.0-alpha0159",
  "AssemblySemVer":"1.2.0.0",
  "AssemblySemFileVer":"1.2.0.0",
  "FullSemVer":"1.2.0-alpha.159",
  "InformationalVersion":"1.2.0-alpha.159+Branch.develop.Sha.2207f42429e92f104978eadf8d37e233e5dfa455",
  "BranchName":"develop",
  "EscapedBranchName":"develop",
  "Sha":"2207f42429e92f104978eadf8d37e233e5dfa455",
  "ShortSha":"2207f42",
  "NuGetVersionV2":"1.2.0-alpha0159",
  "NuGetVersion":"1.2.0-alpha0159",
  "NuGetPreReleaseTagV2":"alpha0159",
  "NuGetPreReleaseTag":"alpha0159",
  "VersionSourceSha":"27566ce2e58925f60904bef84c6778f1fedcdd7f",
  "CommitsSinceVersionSource":159,
  "CommitsSinceVersionSourcePadded":"0159",
  "CommitDate":"2020-08-27"
}

This is my GitVersion.yml

mode: ContinuousDeployment
next-version: 1.0.0
branches: {}
ignore:
  sha: []
merge-message-formats: {}

And in my pipeline I have this

steps:
  - task: UseGitVersion@5
    displayName: gitversion
    inputs:
      versionSpec: '5.x'
      updateAssemblyInfo: false
      useConfigFile: true
      configFilePath: 'GitVersion.yml'

I'm facing this issue too and I might have found an identifier to could lead to the root cause.

In the reproduction of @garoyeri on April 6th, see this line

Creating local branch refs/heads/tags/v1.0.2 pointing at 09ef997d4455f25fd2307864c235c12339f63f68

I'm having the same line in my build log. Now look at this:

C:\workspace\tagtest>git show-ref --heads --tags
d01ece1a5f70e022580bd4e7cd5264a592b677ef refs/heads/feature/278863-automate-version
d01ece1a5f70e022580bd4e7cd5264a592b677ef refs/heads/tags/v2.1
295a413d53e2d5cb1be12f9292382f2e398d2164 refs/tags/v2.1

And at this:

C:\workspace\tagtest>git branch
  feature/278863-automate-version
  master
* tags/v2.1

So I conclude that GitVersion (in buildserver mode) creates a local branch from the tag, and makes that the current checked-out branch. Git itself warns about this branch which uses the same name as the tag:

C:\workspace\tagtest>git checkout tags/v2.1
warning: refname 'tags/v2.1' is ambiguous.

In this scenario, the branch points to the same commit (7ef) as the branch where is has been taken from.
For reference:

C:\workspace\tagtest>git log
commit d01ece1a5f70e022580bd4e7cd5264a592b677ef (HEAD, tag: v2.1, origin/feature/278863-automate-version, tags/v2.1, feature/278863-automate-version)

So questions I have:

  1. Should GitVersion create a local branch from the tag?
  2. It looks like the feature branch is selected as the base. Shouldn't the tag always take precedence?

@asbjornu: can you share your comments? Any pointers to the code where to look at? Or suggestions for the test fixture?

@gerwinjansen, to answer your questions:

  1. No, this is a bug in the normalization code that needs to be fixed. To isolate and make it easier to avoid such bugs in the future, we are going to make normalize an explicit command that needs to be run in GitVersion v6.
  2. Until #2411 is merged, GitVersion expects a branch to be checked out regardless of other repository metadata. That should now change, though, so the tag is just used directly and no further calculation is performed.

I think I have found the root cause. Here are my smallest steps to reproduce (powershell script):

git init remote
cd remote
git commit --allow-empty -m "init master"
git checkout -b develop
git commit --allow-empty -m "new feature"
git checkout master
git tag -a -m "Release 1.0" v1.0
git commit --allow-empty -m "hotfix"
git tag -a -m "Release 1.0.1" v1.0.1

cd ..
git clone remote local
cd local
git checkout v1.0.1
$Env:TF_BUILD=$true
$Env:BUILD_SOURCEBRANCH="refs/tags/v1.0.1"
gitversion.exe /nocache /output buildserver

Because the branch 'tags/v1.0.1' or headless checkout do not have branch configuration in GitVersion.yml, it will try to inherit the configuration from a parent branch. But the log output shows:

WARN [09/28/20 21:47:15:05] Failed to inherit Increment branch configuration, no branches found.

Now, GitVersion tries to find the first branch in the set of {develop, master}:

var chosenBranch = repository.Branches.FirstOrDefault(b =>
    Regex.IsMatch(b.FriendlyName, developBranchRegex, RegexOptions.IgnoreCase) ||
    Regex.IsMatch(b.FriendlyName, masterBranchRegex, RegexOptions.IgnoreCase));

Repository branches are sorted and the 'd' comes before the 'm' so develop configuration is selected. And the default increment for develop is Minor.
Next GitVersion will find all tags that are in the history of the commit. Every version tag is checked if it should be incremented, based on whether HEAD itself is tagged or not.

var shouldUpdateVersion = version.Commit.Sha != context.CurrentCommit.Sha;

There are 2 tags in the history, where 1.0.1 is pointing to the same commit as HEAD and the older 1.0 to a previous commit. This means that 1.0 is marked for increment, effectively a Minor increment based on the develop configuration, so it becomes a set of {1.1, 1.0.1}.
Now GitVersion takes the max

var maxVersion = baseVersions.Aggregate((v1, v2) => v1.IncrementedVersion > v2.IncrementedVersion ? v1 : v2);

And version 1.1 is selected.

As far as I can see, GitVersion should first try to find the max from the tag(s) that are directly pointing to the same commit as HEAD. If there are none, then find the max of the remaining tags.

As far as I can see, GitVersion should first try to find the max from the tag(s) that are directly pointing to the same commit as HEAD. If there are none, then find the max of the remaining tags.

100% agreed. Thank you so much for the investigation and to have found a possible solution to this bug! Would you be up for providing a pull request with the required code adjustments and a test that reproduces the problem? We already have some remote repository tests that both look relevant and should provide useful to reproduce this specific problem so we know that when it's fixed, it will be fixed for good:

https://github.com/GitTools/GitVersion/blob/d326a8822531d1a0990d73dd68f48d9d026c0c63/src/GitVersionCore.Tests/IntegrationTests/RemoteRepositoryScenarios.cs#L103-L110

馃檹

I was able to rule the remote repository out. Here are optimized steps to reproduce:

git init local
cd local
git commit --allow-empty -m "init master"
git tag -a -m "Release 1.0" v1.0
git commit --allow-empty -m "hotfix"
git tag -a -m "Release 1.0.1" v1.0.1
git checkout -b develop
git commit --allow-empty -m "new feature"
git checkout v1.0.1
git checkout -b tags/v1.0.1
gitversion.exe

I was able to create a failing test for this scenario, see PR.

If #2411 is applied, here are alternative steps to reproduce (without creating the ambiguous branch 'tags/v1.0.1', but working on a detached head)

git init local
cd local
git commit --allow-empty -m "init master"
git tag -a -m "Release 1.0" v1.0
git commit --allow-empty -m "hotfix"
git tag -a -m "Release 1.0.1" v1.0.1
git checkout -b develop
git commit --allow-empty -m "new feature"
git checkout master
git checkout -b other
git commit --allow-empty -m "new feature 2"
git checkout v1.0.1
gitversion.exe

I'm not able to capture this scenario in a failing TestFixture. Maybe a problem with the GitTools.Testing when checking out a tag? I didn't investigate in detail.

PR #2413 has only a failing test so far.
I tried to fix the production code, but got stuck.

My solution of preferring tags-on-the-current-commit has at least a conflict with
https://github.com/GitTools/GitVersion/blob/d326a8822531d1a0990d73dd68f48d9d026c0c63/src/GitVersionCore.Tests/IntegrationTests/BranchWithoutCommitScenarios.cs#L23-L24

I'm looking for guidance / feedback.

Do we need to introduce the notion of Precedence in the code? For example, give every VersionStrategy an ordinal (10, 20, 30, ..), which it passes on to the BaseVersion when it creates one. Then TaggedCommitVersionStrategy can give tags-on-current-commit a lower ordinal (e.g. 30) than tag-from-history (e.g. 35).
After collecting all the versions from all strategies, they can be sorted on ordinal and applied in order.

Other idea's welcome. And if someone wants to take the branch to fix the code and complete the PR: feel free.

I think the idea of precedence by ordinal is great, @gerwinjansen. The seemingly random order strategies are applied now is at least not great. It will be interesting to see how many tests introducing this ordinal is going to break. 馃

I have found another solution which is less invasive.
TaggedCommitVersionStrategy now prefers to return only the versions of tags on the current commit. If there aren't any, it will return the tags from history.
That makes all tests (incl the new one) pass for me locally. PR #2413 updated.


:tada: This issue has been resolved in version 5.5.1 :tada:
The release is available on:

Your GitReleaseManager bot :package::rocket:

Was this page helpful?
0 / 5 - 0 ratings