Prerequisites
GitVersion packageGitVersion.MsBuild GitVersion versionv6 Operating systemWindows What are you seeing?Under some scenarios, merging a hotfix branch back to develop prior to merging into main causes the prerelease number of the commits on develop to regress.
#4501 discussed a very similar issue, however the resolution there was limited to version numbers being sourced from commit messages, whereas we are reliant on conventional commits to determine our numbers in our case. Some additional notes:
Is this behaving as intended? The behaviouir's dependence on order of merges seems to indicate an issue to me, but if there isn't, is there a way to configure our way around the problem? What is expected?
Steps to ReproduceMake a merge from a hotfix branch to develop prior to merging to main and tagging a release using GitFlow. RepositoryFixture Test [Test]
public static void RunFixtureSimpleMinimal()
{
const string developBranch = "develop";
const string hotfixBranch = "hotfix/hf";
var configuration = GitFlowConfigurationBuilder.New
.WithMajorVersionBumpMessage("BREAKING CHANGE")
.WithMinorVersionBumpMessage("^(feat)")
.WithPatchVersionBumpMessage("^(build|chore|ci|docs|fix|perf|refactor|revert|style|test)")
.WithCommitMessageIncrementing(CommitMessageIncrementMode.Enabled)
.WithBranch("develop", b => b
.WithLabel("develop")
.WithRegularExpression("develop")
)
.WithBranch("main", b => b
.WithLabel("")
.WithRegularExpression("main")
)
.WithBranch("hotfix", b => b
.WithLabel("hotfix")
.WithRegularExpression("^hotfix?[/-]")
.WithDeploymentMode(DeploymentMode.ContinuousDelivery)
)
.Build();
using var fixture = new BaseGitFlowRepositoryFixture("1.0.0");
fixture.NoteVersion(configuration);
// Feature
fixture.MakeACommit("feat: f1");
fixture.NoteVersion(configuration);
// Release 1.1.0
fixture.Checkout(MainBranch);
fixture.MergeNoFF(developBranch);
fixture.NoteVersion(configuration);
fixture.ApplyTag("1.1.0");
fixture.NoteVersion(configuration);
// Hotfix
fixture.Checkout(MainBranch);
fixture.BranchTo(hotfixBranch);
fixture.MakeACommit("fix: applied hotfix");
fixture.NoteVersion(configuration);
// Merge hotfix->develop
fixture.Checkout(developBranch);
fixture.MakeACommit("feat: f2");
fixture.NoteVersion(configuration);
fixture.MergeNoFF(hotfixBranch);
fixture.NoteVersion(configuration);
fixture.MakeACommit("chore: foobar");
fixture.NoteVersion(configuration);
// Merge hotfix->main
fixture.Checkout(MainBranch);
fixture.MergeNoFF(hotfixBranch);
fixture.Remove(hotfixBranch);
fixture.NoteVersion(configuration);
// tag release
fixture.ApplyTag("1.1.1");
fixture.NoteVersion(configuration);
// Feature 5
fixture.Checkout(developBranch);
fixture.NoteVersion(configuration);
fixture.MakeACommit("feat: f3");
fixture.NoteVersion(configuration);
}Note this is using a variant of the public static GitVersionVariables NoteVersion(this RepositoryFixtureBase fixture, IGitVersionConfiguration? configuration)
{
var variables = GetVersion(fixture, configuration);
fixture.SequenceDiagram.NoteOver(variables.FullSemVer, fixture.Repository.Head.FriendlyName, color: "#D3D3D3");
return variables;
}Output log or link to your CI build (if appropriate). |
Replies: 3 comments 4 replies
|
(Coming from #5077 — thanks @HHobeck for pointing here.) We hit the same regression, with one detail relevant to the "is this by design?" question: in our case the hotfix is already tagged on Our flow (concrete):
So the order is already "tag on main first, then merge to develop", and it still regresses — the merge pulls the Why this isn't just cosmetic for us: we publish these as NuGet packages. A regressing pre-release number makes the counter re-walk numbers it already published ( How I think it could behave (concrete proposal): On the alternatives you mentioned:
Happy to add a RepositoryFixture repro of the main→develop variant if that helps. |
|
Follow-up: a verified hotfix-from-main reproduction — and a correction to my earlier framing. My earlier comment blamed the Reproduction (hotfix from git init -b main && git commit --allow-empty -m init && git tag 1.0.0
git checkout -b develop
for i in 1 2 3 4 5; do git commit --allow-empty -m "d$i"; done # develop -> 1.1.0-beta.5
git checkout -b hotfix/1.0.1 main
git commit --allow-empty -m fix
# merge the hotfix into develop BEFORE it is tagged on main
git checkout develop && git merge --no-ff hotfix/1.0.1 # develop -> 1.1.0-beta.7
# finish the hotfix on main and tag it
git checkout main && git merge --no-ff hotfix/1.0.1 && git tag 1.0.1
git checkout develop # develop -> 1.1.0-beta.6 (was beta.7 -> REGRESSION)Same base, but adding the tag on The safe order is monotonic: tag on Notes:
Happy to turn this into a RepositoryFixture test if useful. |




Thank you for providing the Git commands. I think they make the scenario much easier to discuss.
That said, I still think the issue comes down to the branching, merging, and deployment strategy.
Why would you create and publish a NuGet package in the window between:
I want to point out another aspect: The workflow still requires syncing main back into develop. Once that happens, the hotfix commit is already part of the released version, so it is expected that it is no longer counted as a new commit for develop. As I mentioned earlier, from GitVersion's perspective that commit is already part …