Skip to content

Commit a176d71

Browse files
authored
Merge pull request #3935 from HHobeck/feature/fix-calc-the-wrong-version
GitVersion calculates the wrong version after main is merged back to develop
2 parents 08980c6 + 475f65c commit a176d71

File tree

2 files changed

+129
-20
lines changed

2 files changed

+129
-20
lines changed

src/GitVersion.Core.Tests/IntegrationTests/OtherScenarios.cs

+83
Original file line numberDiff line numberDiff line change
@@ -1218,4 +1218,87 @@ public void EnsurePreventIncrementWhenCurrentCommitTaggedOnReleaseBranchAndIncre
12181218

12191219
fixture.AssertFullSemver(semVersion, configuration);
12201220
}
1221+
1222+
[Test]
1223+
public void EnsureVersionAfterMainIsMergedBackToDevelopIsCorrect()
1224+
{
1225+
using EmptyRepositoryFixture fixture = new("main");
1226+
1227+
fixture.MakeATaggedCommit("1.0.0");
1228+
fixture.BranchTo("develop");
1229+
fixture.MakeACommit("A");
1230+
1231+
// ✅ succeeds as expected
1232+
fixture.AssertFullSemver("1.1.0-alpha.1");
1233+
1234+
fixture.Checkout("main");
1235+
fixture.MakeACommit("B");
1236+
fixture.BranchTo("hotfix/just-a-hotfix");
1237+
fixture.MakeACommit("C +semver: major");
1238+
fixture.MergeTo("main", removeBranchAfterMerging: true);
1239+
fixture.Checkout("develop");
1240+
fixture.MakeACommit("D");
1241+
fixture.Checkout("main");
1242+
fixture.MakeACommit("E");
1243+
fixture.ApplyTag("1.0.1");
1244+
fixture.Checkout("develop");
1245+
fixture.MergeNoFF("main");
1246+
1247+
// ✅ succeeds as expected
1248+
fixture.AssertFullSemver("1.1.0-alpha.7");
1249+
}
1250+
1251+
[TestCase(false, "2.0.0-alpha.3")]
1252+
[TestCase(true, "2.0.0-alpha.2")]
1253+
public void EnsureVersionAfterMainIsMergedBackToDevelopIsCorrectForTrunkBased(bool applyTag, string semanticVersion)
1254+
{
1255+
var configuration = GitFlowConfigurationBuilder.New
1256+
.WithVersionStrategy(VersionStrategies.TrunkBased)
1257+
.Build();
1258+
1259+
using EmptyRepositoryFixture fixture = new("main");
1260+
1261+
fixture.MakeACommit("A");
1262+
fixture.ApplyTag("1.0.0");
1263+
fixture.BranchTo("develop");
1264+
fixture.MakeACommit("B +semver: major");
1265+
1266+
// ✅ succeeds as expected
1267+
fixture.AssertFullSemver("2.0.0-alpha.1", configuration);
1268+
1269+
fixture.Checkout("main");
1270+
fixture.MakeACommit("C");
1271+
if (applyTag) fixture.ApplyTag("1.0.1");
1272+
fixture.Checkout("develop");
1273+
fixture.MergeNoFF("main");
1274+
1275+
// ✅ succeeds as expected
1276+
fixture.AssertFullSemver(semanticVersion, configuration);
1277+
}
1278+
1279+
[TestCase(false, "2.0.0-alpha.3")]
1280+
[TestCase(true, "2.0.0-alpha.3")]
1281+
public void EnsureVersionAfterMainIsMergedBackToDevelopIsCorrectForGitFlow(bool applyTag, string semanticVersion)
1282+
{
1283+
var configuration = GitFlowConfigurationBuilder.New.Build();
1284+
1285+
using EmptyRepositoryFixture fixture = new("main");
1286+
1287+
fixture.MakeACommit("A");
1288+
fixture.ApplyTag("1.0.0");
1289+
fixture.BranchTo("develop");
1290+
fixture.MakeACommit("B +semver: major");
1291+
1292+
// ✅ succeeds as expected
1293+
fixture.AssertFullSemver("2.0.0-alpha.1", configuration);
1294+
1295+
fixture.Checkout("main");
1296+
fixture.MakeACommit("C");
1297+
if (applyTag) fixture.ApplyTag("1.0.1");
1298+
fixture.Checkout("develop");
1299+
fixture.MergeNoFF("main");
1300+
1301+
// ✅ succeeds as expected
1302+
fixture.AssertFullSemver(semanticVersion, configuration);
1303+
}
12211304
}

src/GitVersion.Core/VersionCalculation/IncrementStrategyFinder.cs

+46-20
Original file line numberDiff line numberDiff line change
@@ -75,26 +75,21 @@ public VersionField DetermineIncrementedField(
7575
}
7676

7777
private VersionField? FindCommitMessageIncrement(
78-
EffectiveConfiguration configuration, ICommit? baseCommit, ICommit? currentCommit, string? label)
78+
EffectiveConfiguration configuration, ICommit? baseVersionSource, ICommit currentCommit, string? label)
7979
{
8080
if (configuration.CommitMessageIncrementing == CommitMessageIncrementMode.Disabled)
8181
{
8282
return null;
8383
}
8484

85-
//get tags with valid version - depends on configuration (see #3757)
86-
var targetShas = new Lazy<IReadOnlySet<string>>(() =>
87-
this.taggedSemanticVersionRepository.GetTaggedSemanticVersions(configuration.TagPrefix, configuration.SemanticVersionFormat)
88-
.SelectMany(_ => _).Where(_ => _.Value.IsMatchForBranchSpecificLabel(label)).Select(_ => _.Tag.TargetSha).ToHashSet()
85+
IEnumerable<ICommit> commits = GetCommitHistory(
86+
tagPrefix: configuration.TagPrefix,
87+
semanticVersionFormat: configuration.SemanticVersionFormat,
88+
baseVersionSource: baseVersionSource,
89+
currentCommit: currentCommit,
90+
label: label
8991
);
9092

91-
var commits = GetIntermediateCommits(baseCommit, currentCommit);
92-
// consider commit messages since latest tag only (see #3071)
93-
commits = commits
94-
.Reverse()
95-
.TakeWhile(x => !targetShas.Value.Contains(x.Sha))
96-
.Reverse();
97-
9893
if (configuration.CommitMessageIncrementing == CommitMessageIncrementMode.MergeMessageOnly)
9994
{
10095
commits = commits.Where(c => c.Parents.Count() > 1);
@@ -114,6 +109,41 @@ private static Regex TryGetRegexOrDefault(string? messageRegex, Regex defaultReg
114109
? defaultRegex
115110
: CompiledRegexCache.GetOrAdd(messageRegex, pattern => new(pattern, RegexOptions.Compiled | RegexOptions.IgnoreCase));
116111

112+
private IReadOnlyCollection<ICommit> GetCommitHistory(
113+
string? tagPrefix, SemanticVersionFormat semanticVersionFormat, ICommit? baseVersionSource, ICommit currentCommit, string? label)
114+
{
115+
var targetShas = new Lazy<HashSet<string>>(() =>
116+
this.taggedSemanticVersionRepository.GetTaggedSemanticVersions(tagPrefix, semanticVersionFormat)
117+
.SelectMany(_ => _).Where(_ => _.Value.IsMatchForBranchSpecificLabel(label)).Select(_ => _.Tag.TargetSha).ToHashSet()
118+
);
119+
120+
var intermediateCommits = GetIntermediateCommits(baseVersionSource, currentCommit).ToArray();
121+
122+
var commitLog = intermediateCommits.ToDictionary(element => element.Id.Sha);
123+
124+
foreach (var intermediateCommit in intermediateCommits.Reverse())
125+
{
126+
if (targetShas.Value.Contains(intermediateCommit.Sha) && commitLog.Remove(intermediateCommit.Sha))
127+
{
128+
var parentCommits = intermediateCommit.Parents.ToList();
129+
while (parentCommits.Count != 0)
130+
{
131+
List<ICommit> temporaryList = new();
132+
foreach (var parentCommit in parentCommits)
133+
{
134+
if (commitLog.Remove(parentCommit.Sha))
135+
{
136+
temporaryList.AddRange(parentCommit.Parents);
137+
}
138+
}
139+
parentCommits = temporaryList;
140+
}
141+
}
142+
}
143+
144+
return commitLog.Values;
145+
}
146+
117147
/// <summary>
118148
/// Get the sequence of commits in a repository between a <paramref name="baseCommit"/> (exclusive)
119149
/// and a particular <paramref name="headCommit"/> (inclusive)
@@ -149,7 +179,7 @@ private Dictionary<string, int> GetHeadCommitsMap(ICommit? headCommit) =>
149179
/// </summary>
150180
private ICommit[] GetHeadCommits(ICommit? headCommit) =>
151181
this.headCommitsCache.GetOrAdd(headCommit?.Sha ?? "NULL", () =>
152-
GetCommitsReacheableFromHead(repository, headCommit).ToArray());
182+
GetCommitsReacheableFromHead(headCommit).ToArray());
153183

154184
private VersionField? GetIncrementFromCommit(ICommit commit, Regex majorRegex, Regex minorRegex, Regex patchRegex, Regex none) =>
155185
this.commitIncrementCache.GetOrAdd(commit.Sha, () =>
@@ -164,19 +194,15 @@ private ICommit[] GetHeadCommits(ICommit? headCommit) =>
164194
return null;
165195
}
166196

167-
/// <summary>
168-
/// Query a <paramref name="repo"/> for the sequence of commits from the beginning to a particular
169-
/// <paramref name="headCommit"/> (inclusive)
170-
/// </summary>
171-
private static IEnumerable<ICommit> GetCommitsReacheableFromHead(IGitRepository repo, ICommit? headCommit)
197+
private IEnumerable<ICommit> GetCommitsReacheableFromHead(ICommit? headCommit)
172198
{
173199
var filter = new CommitFilter
174200
{
175201
IncludeReachableFrom = headCommit,
176202
SortBy = CommitSortStrategies.Topological | CommitSortStrategies.Reverse
177203
};
178204

179-
return repo.Commits.QueryBy(filter);
205+
return repository.Commits.QueryBy(filter);
180206
}
181207

182208
public IEnumerable<ICommit> GetMergedCommits(ICommit mergeCommit, int index)
@@ -202,7 +228,7 @@ private static ICommit GetMergedHead(ICommit mergeCommit)
202228
{
203229
var parents = mergeCommit.Parents.Skip(1).ToList();
204230
if (parents.Count > 1)
205-
throw new NotSupportedException("Mainline development does not support more than one merge source in a single commit yet");
231+
throw new NotSupportedException("GitVersion does not support more than one merge source in a single commit yet");
206232
return parents.Single();
207233
}
208234

0 commit comments

Comments
 (0)