Skip to content

Finalizing the configuration of GitFlow and GitHubFlow workflow and align with the Mainline version strategy #4020

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions BREAKING_CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,12 @@
* The initialization wizard has been removed.
* On the `develop`, `release` and `hotfix` branch the introduced branch related property `prevent-increment.when-current-commit-tagged` has been set to `false` to get the incremented instead of the tagged semantic version.
* When setting the "ignore commits before" parameter to a future value, an exception will occur if no commits are found on the current branch. This behavior mimics that of an empty repository.
* On the `GitFlow` workflow the increment property has been changed:
* in branch `release` from `None` to `Minor` and
* in branch `hotfix` from `None` to `Patch`
* On the `GitHubFlow` workflow the increment property has been changed in branch `release` from `None` to `Patch`.
* When creating a branch with name `hotfix/next` (by using the `GitFlow` workflow) or `release/next` (by the `GitHubFlow` workflow) the resulting version will yield to a patched version per default.
* If you have a tag `1.0.0` on `main` and branch from `main` to `release/1.0.1` then the next version number will be `1.1.0` when using the `GitFlow` workflow. This behavior is expected (but different compared to the `GitHubFlow` workflow) because on the `GitFlow` workflow you have an addition branch configuration with name hotfix where `is-release-branch` is set to `true`. That means if you want `1.0.1` as a next version you need to branch to `hotfix/1.0.1` or `hotfix/next`. On the other hand if you use the `GitHubFlow` workflow the next version number will be `1.0.1` because the increment on the `release` branch is set to `Patch`.

## v5.0.0

Expand Down
2 changes: 1 addition & 1 deletion GitVersion.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
assembly-versioning-scheme: MajorMinorPatch
workflow: GitFlow/v1
branches:
main:
label: beta
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -616,29 +616,13 @@ public void EnsureFeatureDevelopmentWithDevelopBranchFast(bool useTrunkBased)

fixture.BranchTo("feature/foo");

if (useTrunkBased)
{
// ❔ expected: "0.1.0-foo.1+0"
fixture.AssertFullSemver("0.0.2-foo.1+0", configuration);
}
else
{
// ✅ succeeds as expected
fixture.AssertFullSemver("0.1.0-foo.1+0", configuration);
}
// ✅ succeeds as expected
fixture.AssertFullSemver("0.1.0-foo.1+0", configuration);

fixture.MakeACommit("B");

if (useTrunkBased)
{
// ❔ expected: "0.1.0-foo.1+1"
fixture.AssertFullSemver("0.0.2-foo.1+1", configuration);
}
else
{
// ✅ succeeds as expected
fixture.AssertFullSemver("0.1.0-foo.1+1", configuration);
}
// ✅ succeeds as expected
fixture.AssertFullSemver("0.1.0-foo.1+1", configuration);

fixture.ApplyTag("0.1.0-foo.1");

Expand Down Expand Up @@ -946,31 +930,15 @@ public void EnsureBugFixWithDevelopBranchFast(bool useTrunkBased)
fixture.BranchTo("pull/2/merge");
fixture.MergeNoFF("hotfix/foo");

if (useTrunkBased)
{
// ❔ expected: "0.1.0-PullRequest2.4"
fixture.AssertFullSemver("0.0.2-PullRequest2.4", configuration);
}
else
{
// ✅ succeeds as expected
fixture.AssertFullSemver("0.1.0-PullRequest2.4", configuration);
}
// ✅ succeeds as expected
fixture.AssertFullSemver("0.1.0-PullRequest2.4", configuration);

fixture.Checkout("main");
fixture.BranchTo("pull/3/merge");
fixture.MergeNoFF("hotfix/foo");

if (useTrunkBased)
{
// ✅ succeeds as expected
fixture.AssertFullSemver("0.0.2-PullRequest3.4", configuration);
}
else
{
// ❔ expected: "0.0.2-PullRequest3.4"
fixture.AssertFullSemver("0.1.0-PullRequest3.4", configuration);
}
// ❔ expected: "0.0.2-PullRequest3.4"
fixture.AssertFullSemver("0.1.0-PullRequest3.4", configuration);

fixture.Checkout("hotfix/foo");
fixture.MergeTo("main", removeBranchAfterMerging: true);
Expand All @@ -985,26 +953,6 @@ public void EnsureBugFixWithDevelopBranchFast(bool useTrunkBased)
fixture.AssertFullSemver("0.0.3-1", configuration);
}

[Test]
public void JustATest()
{
var configuration = configurationBuilder.WithVersionStrategy(VersionStrategies.TrunkBased).Build();

using var fixture = new EmptyRepositoryFixture("main");

fixture.MakeACommit("A");

// ✅ succeeds as expected
fixture.AssertFullSemver("0.0.1-1", configuration);

fixture.ApplyTag("0.1.0");

for (int i = 0; i < 10; i++) fixture.MakeACommit();

// ✅ succeeds as expected
fixture.AssertFullSemver("0.1.10-1", configuration);
}

[TestCase(false)]
[TestCase(true)]
public void EnsureFeatureDevelopmentWithReleaseNextBranch(bool useTrunkBased)
Expand Down
38 changes: 38 additions & 0 deletions src/GitVersion.Core.Tests/IntegrationTests/OtherScenarios.cs
Original file line number Diff line number Diff line change
Expand Up @@ -1364,4 +1364,42 @@ public void UnversionedHotfix()

fixture.AssertFullSemver("1.2.1-3", configuration);
}

[Test]
public void AlternativeSemanticVersionsShouldBeConsidered()
{
var configuration = GitFlowConfigurationBuilder.New.Build();

using EmptyRepositoryFixture fixture = new("main");

fixture.MakeACommit("A");
fixture.MakeATaggedCommit("4.0.0-beta.14");
fixture.MakeACommit("B");

fixture.AssertFullSemver("4.0.0-3", configuration);
}

[TestCase(null, "6.0.0-beta.6")]
[TestCase("beta", "6.0.0-beta.21")]
public void AlternativeSemanticVersionsShouldBeConsidered(string? labelOnMain, string version)
{
var configuration = GitFlowConfigurationBuilder.New
.WithLabel(null)
.WithBranch("main", _ => _.WithLabel(labelOnMain))
.Build();

using EmptyRepositoryFixture fixture = new("main");

fixture.MakeATaggedCommit("1.0.0");
fixture.MakeATaggedCommit("4.0.0-beta.14");
fixture.MakeACommit("A");
fixture.MakeATaggedCommit("6.0.0-alpha.1");
fixture.MakeATaggedCommit("6.0.0-alpha.2");
fixture.MakeATaggedCommit("6.0.0-alpha.3");
fixture.MakeACommit("B");
fixture.MakeATaggedCommit("6.0.0-beta.5");
fixture.MakeACommit("C");

fixture.AssertFullSemver(version, configuration);
}
}
11 changes: 10 additions & 1 deletion src/GitVersion.Core/Git/ReferenceName.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ public static bool TryParse([NotNullWhen(true)] out ReferenceName? value, string
value = new(canonicalName);
}

return value != null;
return value is not null;
}

public static ReferenceName FromBranchName(string branchName)
Expand All @@ -77,6 +77,15 @@ public static ReferenceName FromBranchName(string branchName)
public override int GetHashCode() => equalityHelper.GetHashCode(this);
public override string ToString() => Friendly;

public static bool operator ==(ReferenceName? left, ReferenceName? right)
{
if (ReferenceEquals(left, right)) return true;
if (left is null || right is null) return false;
return left.Equals(right);
}

public static bool operator !=(ReferenceName? left, ReferenceName? right) => !(left == right);

public bool TryGetSemanticVersion([NotNullWhen(true)] out (SemanticVersion Value, string? Name) result,
Regex versionPatternRegex,
string? tagPrefix,
Expand Down
2 changes: 1 addition & 1 deletion src/GitVersion.Core/MergeMessage.cs
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@ public static bool TryParse(
mergeMessage = null;

var mergedBranch = new MergeMessage(mergeCommit.Message, configuration).MergedBranch;
var isReleaseBranch = mergedBranch != null && configuration.IsReleaseBranch(mergedBranch);
var isReleaseBranch = mergedBranch is not null && configuration.IsReleaseBranch(mergedBranch);
var isValidMergeCommit = mergeCommit.IsMergeCommit() || isReleaseBranch;

if (isValidMergeCommit)
Expand Down
2 changes: 2 additions & 0 deletions src/GitVersion.Core/PublicAPI.Unshipped.txt
Original file line number Diff line number Diff line change
Expand Up @@ -769,6 +769,8 @@ static GitVersion.Git.BranchCommit.operator !=(GitVersion.Git.BranchCommit left,
static GitVersion.Git.BranchCommit.operator ==(GitVersion.Git.BranchCommit left, GitVersion.Git.BranchCommit right) -> bool
static GitVersion.Git.CommitExtensions.IsMergeCommit(this GitVersion.Git.ICommit! source) -> bool
static GitVersion.Git.ReferenceName.FromBranchName(string! branchName) -> GitVersion.Git.ReferenceName!
static GitVersion.Git.ReferenceName.operator !=(GitVersion.Git.ReferenceName? left, GitVersion.Git.ReferenceName? right) -> bool
static GitVersion.Git.ReferenceName.operator ==(GitVersion.Git.ReferenceName? left, GitVersion.Git.ReferenceName? right) -> bool
static GitVersion.Git.ReferenceName.Parse(string! canonicalName) -> GitVersion.Git.ReferenceName!
static GitVersion.Git.ReferenceName.TryParse(out GitVersion.Git.ReferenceName? value, string! canonicalName) -> bool
static GitVersion.Helpers.Disposable.Create(System.Action! disposer) -> System.IDisposable!
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,9 @@ public void Enrich(TrunkBasedIteration iteration, TrunkBasedCommit commit, Trunk
{
var effectiveConfiguration = commit.GetEffectiveConfiguration(context.Configuration);
var incrementForcedByBranch = effectiveConfiguration.Increment.ToVersionField();
var incrementForcedByCommit = GetIncrementForcedByCommit(context, commit.Value, effectiveConfiguration);
var incrementForcedByCommit = commit.IsDummy
? VersionField.None
: GetIncrementForcedByCommit(context, commit.Value, effectiveConfiguration);
commit.Increment = incrementForcedByCommit;
context.Increment = context.Increment.Consolidate(incrementForcedByBranch, incrementForcedByCommit);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public bool MatchPrecondition(TrunkBasedIteration iteration, TrunkBasedCommit co
&& commit.GetEffectiveConfiguration(context.Configuration).IsReleaseBranch
&& context.SemanticVersion is null
&& (commit.Predecessor is null
|| commit.Predecessor?.BranchName != commit.BranchName);
|| commit.BranchName != commit.Predecessor?.BranchName);

public IEnumerable<IBaseVersionIncrement> GetIncrements(
TrunkBasedIteration iteration, TrunkBasedCommit commit, TrunkBasedContext context)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ namespace GitVersion.VersionCalculation.TrunkBased;
"HasSuccessor = {" + nameof(HasSuccessor) + "}, HasPredecessor = {" + nameof(HasPredecessor) + "}, " +
"HasChildIteration = {" + nameof(HasChildIteration) + "}, Message = {" + nameof(Message) + @"} \}"
)]
internal record TrunkBasedCommit(TrunkBasedIteration Iteration, ICommit Value, ReferenceName BranchName, IBranchConfiguration Configuration)
internal record TrunkBasedCommit(TrunkBasedIteration Iteration, ICommit? value, ReferenceName BranchName, IBranchConfiguration Configuration)
{
public bool IsPredecessorTheLastCommitOnTrunk(IGitVersionConfiguration configuration)
=> !GetEffectiveConfiguration(configuration).IsMainBranch && Predecessor?.GetEffectiveConfiguration(configuration).IsMainBranch == true;
Expand All @@ -31,9 +31,12 @@ public bool IsPredecessorTheLastCommitOnTrunk(IGitVersionConfiguration configura

public TrunkBasedCommit? Predecessor { get; private set; }

public ICommit Value { get; } = Value.NotNull();
public ICommit Value => IsDummy ? (Successor?.Value)! : value!;

public string Message => Value.Message;
[MemberNotNullWhen(false, nameof(Value))]
public bool IsDummy => value is null;

public string Message => IsDummy ? "<<DUMMY>>" : Value.Message;

public TrunkBasedIteration? ChildIteration { get; private set; }

Expand Down Expand Up @@ -101,7 +104,7 @@ public void AddSemanticVersions(IEnumerable<SemanticVersion> values)
public void AddChildIteration(TrunkBasedIteration iteration) => ChildIteration = iteration.NotNull();

public TrunkBasedCommit Append(
ICommit value, ReferenceName branchName, IBranchConfiguration configuration)
ICommit? value, ReferenceName branchName, IBranchConfiguration configuration)
{
if (HasPredecessor) throw new InvalidOperationException();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -63,17 +63,21 @@ public TrunkBasedIteration(string id, ReferenceName branchName, IBranchConfigura
}

public TrunkBasedCommit CreateCommit(
ICommit value, ReferenceName branchName, IBranchConfiguration configuration)
ICommit? value, ReferenceName branchName, IBranchConfiguration configuration)
{
TrunkBasedCommit commit;
if (commits.Count != 0)
commit = commits.Peek().Append(value, branchName, configuration); //, increment);
commit = commits.Peek().Append(value, branchName, configuration);
else
{
commit = new TrunkBasedCommit(this, value, branchName, configuration); //, increment);
commit = new TrunkBasedCommit(this, value, branchName, configuration);
}
commits.Push(commit);
commitLookup.Add(value, commit);

if (value is not null)
{
commitLookup.Add(value, commit);
}

return commit;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -162,19 +162,22 @@ private NextVersion CalculateNextVersion(IBranch branch, IGitVersionConfiguratio

var maxVersion = nextVersions.Max()
?? throw new GitVersionException("No base versions determined on the current branch.");
var matchingVersionsOnceIncremented = nextVersions
.Where(v => v.BaseVersion.BaseVersionSource != null && v.IncrementedVersion == maxVersion.IncrementedVersion)
.ToList();

ICommit? latestBaseVersionSource;

if (matchingVersionsOnceIncremented.Count != 0)
var matchingVersionsOnceIncremented = nextVersions
.Where(
element => element.BaseVersion.BaseVersionSource != null
&& element.IncrementedVersion == maxVersion.IncrementedVersion
).ToArray();
if (matchingVersionsOnceIncremented.Length > 1)
{
var latestVersion = matchingVersionsOnceIncremented.Aggregate(CompareVersions);
latestBaseVersionSource = latestVersion.BaseVersion.BaseVersionSource;
maxVersion = latestVersion;
log.Info(
$"Found multiple base versions which will produce the same SemVer ({maxVersion.IncrementedVersion}), " +
$"taking oldest source for commit counting ({latestVersion.BaseVersion.Source})");
$"taking latest source for commit counting ({latestVersion.BaseVersion.Source})");
}
else
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,16 @@ private IEnumerable<BaseVersion> GetBaseVersionsInternal(EffectiveBranchConfigur
).SelectMany(elements => elements).Distinct().ToArray();

var label = configuration.Value.GetBranchSpecificLabel(Context.CurrentBranch.Name, null);
var maxTaggedSemanticVersion = taggedSemanticVersions
.Where(element => !element.Value.IsMatchForBranchSpecificLabel(label))
.Max();

var semanticVersionsWithTag = taggedSemanticVersions.Where(element => element.Value.IsMatchForBranchSpecificLabel(label));
foreach (var semanticVersionWithTag in semanticVersionsWithTag)
List<SemanticVersionWithTag> alternativeSemanticVersionsWithTag = new();
foreach (var semanticVersionWithTag in taggedSemanticVersions)
{
if (!semanticVersionWithTag.Value.IsMatchForBranchSpecificLabel(label))
{
alternativeSemanticVersionsWithTag.Add(semanticVersionWithTag);
continue;
}

var baseVersionSource = semanticVersionWithTag.Tag.Commit;
var increment = incrementStrategyFinder.DetermineIncrementedField(
currentCommit: Context.CurrentCommit,
Expand All @@ -55,6 +58,7 @@ private IEnumerable<BaseVersion> GetBaseVersionsInternal(EffectiveBranchConfigur
configuration: configuration.Value,
label: label
);

yield return new BaseVersion(
$"Git tag '{semanticVersionWithTag.Tag.Name.Friendly}'", semanticVersionWithTag.Value, baseVersionSource)
{
Expand All @@ -63,9 +67,10 @@ private IEnumerable<BaseVersion> GetBaseVersionsInternal(EffectiveBranchConfigur
Increment = increment,
ForceIncrement = false,
Label = label,
AlternativeSemanticVersion = maxTaggedSemanticVersion?.Value
AlternativeSemanticVersion = alternativeSemanticVersionsWithTag.Max()?.Value
}
};
alternativeSemanticVersionsWithTag.Clear();
}
}
}
Loading
Loading