Skip to content

Commit 1dc79b7

Browse files
committed
Ability to merge release back to develop
This preserves the correct version when merging a release back into develop. This also changes the semantics of the 0+1 part of the semantic version so that it represents the number of changes since the previous tagged release (e.g. version 1.0.0-beta.1+5 gets reset to 1.0.0-beta.2+0)
1 parent 963a024 commit 1dc79b7

File tree

4 files changed

+109
-8
lines changed

4 files changed

+109
-8
lines changed

GitVersionCore.Tests/GitFlow/UncycloScenarios.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ public void MinorReleaseExample()
7676

7777
// Make a commit after a tag should bump up the beta
7878
fixture.Repository.MakeACommit();
79-
fixture.AssertFullSemver("1.3.0-beta.2+2");
79+
fixture.AssertFullSemver("1.3.0-beta.2+0");
8080

8181
// Merge release branch to master
8282
fixture.Repository.Checkout("master");

GitVersionCore.Tests/GitHubFlow/ReleaseBranchTests.cs

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -57,4 +57,40 @@ public void WhenReleaseBranchIsMergedIntoMasterHighestVersionIsTakenWithIt()
5757
fixture.AssertFullSemver("2.0.0+11");
5858
}
5959
}
60+
61+
[Test]
62+
public void WhenMergingReleaseBackToDevShouldNotResetBetaVersion()
63+
{
64+
using (var fixture = new EmptyRepositoryFixture())
65+
{
66+
const string TaggedVersion = "1.0.3";
67+
fixture.Repository.MakeATaggedCommit(TaggedVersion);
68+
fixture.Repository.CreateBranch("develop");
69+
fixture.Repository.Checkout("develop");
70+
71+
fixture.Repository.MakeCommits(1);
72+
73+
fixture.Repository.CreateBranch("release-2.0.0");
74+
fixture.Repository.Checkout("release-2.0.0");
75+
fixture.Repository.MakeCommits(1);
76+
77+
fixture.AssertFullSemver("2.0.0-beta.1+1");
78+
79+
//tag it to bump to beta 2
80+
fixture.Repository.ApplyTag("2.0.0-beta1");
81+
82+
fixture.Repository.MakeCommits(1);
83+
84+
fixture.AssertFullSemver("2.0.0-beta.2+0");
85+
86+
//merge down to develop
87+
fixture.Repository.Checkout("develop");
88+
fixture.Repository.MergeNoFF("release-2.0.0", Constants.SignatureNow());
89+
90+
//but keep working on the release
91+
fixture.Repository.Checkout("release-2.0.0");
92+
93+
fixture.AssertFullSemver("2.0.0-beta.2+0");
94+
}
95+
}
6096
}

GitVersionCore/GitFlow/BranchFinders/ReleaseVersionFinder.cs

Lines changed: 55 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
namespace GitVersion
22
{
3+
using System.Collections.Generic;
34
using System.Linq;
45
using LibGit2Sharp;
56

@@ -11,26 +12,73 @@ public SemanticVersion FindVersion(GitVersionContext context)
1112
var shortVersion = ShortVersionParser.Parse(versionString);
1213

1314
EnsureVersionIsValid(shortVersion, context.CurrentBranch);
14-
var semanticVersionPreReleaseTag = "beta.1";
15-
16-
var nbHotfixCommits = BranchCommitDifferenceFinder.NumberOfCommitsInBranchNotKnownFromBaseBranch(context.Repository, context.CurrentBranch, BranchType.Release, "develop");
15+
SemanticVersionPreReleaseTag semanticVersionPreReleaseTag = "beta.1";
1716

18-
var tagVersion = RecentTagVersionExtractor.RetrieveMostRecentOptionalTagVersion(context.Repository, shortVersion, context.CurrentBranch.Commits.Take(nbHotfixCommits + 1));
17+
var tagsApplicableToBranchVersion = context.Repository.SemVerTagsRelatedToVersion(shortVersion).OrderByDescending(tag => SemanticVersion.Parse(tag.Name)).ToList();
18+
var latestTaggedCommit = tagsApplicableToBranchVersion.Select(tag => tag.Target).FirstOrDefault();
19+
20+
var numberOfCommitsSinceLastTagOrBranchPoint = NumberOfCommitsSinceLastTagOrBranchPoint(context, tagsApplicableToBranchVersion, "develop");
21+
22+
var tagVersion = RetrieveMostRecentOptionalTagVersion(tagsApplicableToBranchVersion);
23+
1924
if (tagVersion != null)
2025
{
21-
semanticVersionPreReleaseTag = tagVersion;
26+
semanticVersionPreReleaseTag = tagVersion.PreReleaseTag;
27+
if (latestTaggedCommit != context.CurrentCommit)
28+
{
29+
semanticVersionPreReleaseTag.Number++;
30+
}
2231
}
32+
2333
return new SemanticVersion
2434
{
2535
Major = shortVersion.Major,
2636
Minor = shortVersion.Minor,
2737
Patch = shortVersion.Patch,
2838
PreReleaseTag = semanticVersionPreReleaseTag,
29-
BuildMetaData = new SemanticVersionBuildMetaData(nbHotfixCommits, context.CurrentBranch.Name, context.CurrentCommit.Sha, context.CurrentCommit.When())
39+
BuildMetaData = new SemanticVersionBuildMetaData(numberOfCommitsSinceLastTagOrBranchPoint, context.CurrentBranch.Name, context.CurrentCommit.Sha, context.CurrentCommit.When())
3040
};
3141
}
3242

33-
void EnsureVersionIsValid(ShortVersion version, Branch branch)
43+
static SemanticVersion RetrieveMostRecentOptionalTagVersion(List<Tag> tagsInDescendingOrder)
44+
{
45+
return tagsInDescendingOrder.Select(tag => SemanticVersion.Parse(tag.Name)).FirstOrDefault();
46+
}
47+
48+
static int NumberOfCommitsSinceLastTagOrBranchPoint(GitVersionContext context, List<Tag> tagsInDescendingOrder, string baseBranchName)
49+
{
50+
if (!tagsInDescendingOrder.Any())
51+
{
52+
return BranchCommitDifferenceFinder.NumberOfCommitsInBranchNotKnownFromBaseBranch(context.Repository, context.CurrentBranch, BranchType.Release, baseBranchName);
53+
}
54+
55+
var mostRecentTag = tagsInDescendingOrder.First();
56+
var ancestor = mostRecentTag;
57+
if (mostRecentTag.Target == context.CurrentCommit)
58+
{
59+
var previousTag = tagsInDescendingOrder.Skip(1).FirstOrDefault();
60+
if (previousTag != null)
61+
{
62+
ancestor = previousTag;
63+
}
64+
else
65+
{
66+
return BranchCommitDifferenceFinder.NumberOfCommitsInBranchNotKnownFromBaseBranch(context.Repository, context.CurrentBranch, BranchType.Release, baseBranchName);
67+
}
68+
69+
}
70+
71+
var filter = new CommitFilter
72+
{
73+
Since = context.CurrentCommit,
74+
Until = ancestor.Target,
75+
SortBy = CommitSortStrategies.Topological | CommitSortStrategies.Time
76+
};
77+
78+
return context.Repository.Commits.QueryBy(filter).Count() - 1;
79+
}
80+
81+
static void EnsureVersionIsValid(ShortVersion version, Branch branch)
3482
{
3583
if (version.Patch != 0)
3684
{

GitVersionCore/LibGitExtensions.cs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,23 @@ public static IEnumerable<Tag> TagsByDate(this IRepository repository, Commit co
3939
});
4040
}
4141

42+
public static IEnumerable<Tag> SemVerTagsRelatedToVersion(this IRepository repository, ShortVersion version)
43+
{
44+
foreach (var tag in repository.Tags)
45+
{
46+
SemanticVersion tagVersion;
47+
if (SemanticVersion.TryParse(tag.Name, out tagVersion))
48+
{
49+
if (version.Major == tagVersion.Major &&
50+
version.Minor == tagVersion.Minor &&
51+
version.Patch == tagVersion.Patch)
52+
{
53+
yield return tag;
54+
}
55+
}
56+
}
57+
}
58+
4259
public static GitObject PeeledTarget(this Tag tag)
4360
{
4461
var target = tag.Target;

0 commit comments

Comments
 (0)