diff --git a/docs/input/docs/reference/requirements.md b/docs/input/docs/reference/requirements.md index 5a66dcb721..91a2785b80 100644 --- a/docs/input/docs/reference/requirements.md +++ b/docs/input/docs/reference/requirements.md @@ -28,11 +28,6 @@ The repository needs to have an existing local `master` or `main` branch. For some branch strategies (such as [Git Flow][gitflow]), a local `develop` branch needs to exist. -### Switched branch - -The repository should be [switched][git-switch] to a named, existing branch -pointing to the commit being built (i.e. no detached `HEAD`). - ### Configuration If using a `GitVersion.yml` [configuration][configuration] file, that file diff --git a/docs/input/docs/reference/version-increments.md b/docs/input/docs/reference/version-increments.md index 3dac968bd4..f6e31f3cf2 100644 --- a/docs/input/docs/reference/version-increments.md +++ b/docs/input/docs/reference/version-increments.md @@ -115,6 +115,11 @@ If you create a branch with the version number in the branch name, such as from the branch name as a source. However, GitVersion can't use the [branch name as a version source for _other branches_][faq-branch-name-source]. +### Detached HEAD +If HEAD is in detached state tag will be `-no-branch-`. + +Example: `0.1.0--no-branch-.1+4` + ### Tagging commit By tagging a commit, GitVersion will use that tag for the version of that diff --git a/src/GitVersion.Core.Tests/IntegrationTests/RemoteRepositoryScenarios.cs b/src/GitVersion.Core.Tests/IntegrationTests/RemoteRepositoryScenarios.cs index b85daea32e..cafed1dfcc 100644 --- a/src/GitVersion.Core.Tests/IntegrationTests/RemoteRepositoryScenarios.cs +++ b/src/GitVersion.Core.Tests/IntegrationTests/RemoteRepositoryScenarios.cs @@ -5,7 +5,6 @@ using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.Options; using NUnit.Framework; -using Shouldly; namespace GitVersion.Core.Tests.IntegrationTests; @@ -87,15 +86,14 @@ public void GivenARemoteGitRepositoryAheadOfLocalRepositoryThenChangesShouldPull } [Test] - public void GivenARemoteGitRepositoryWhenCheckingOutDetachedHeadUsingExistingImplementationThrowsException() + public void GivenARemoteGitRepositoryWhenCheckingOutDetachedHeadUsingExistingImplementationHandleDetachedBranch() { using var fixture = new RemoteRepositoryFixture(); Commands.Checkout( fixture.LocalRepositoryFixture.Repository, fixture.LocalRepositoryFixture.Repository.Head.Tip); - Should.Throw(() => fixture.AssertFullSemver("0.1.0+4", repository: fixture.LocalRepositoryFixture.Repository, onlyTrackedBranches: false), - $"It looks like the branch being examined is a detached Head pointing to commit '{fixture.LocalRepositoryFixture.Repository.Head.Tip.Id.ToString(7)}'. Without a proper branch name GitVersion cannot determine the build version."); + fixture.AssertFullSemver("0.1.0--no-branch-.1+4", repository: fixture.LocalRepositoryFixture.Repository, onlyTrackedBranches: false); } [Test] diff --git a/src/GitVersion.Core/Core/Abstractions/IRepositoryStore.cs b/src/GitVersion.Core/Core/Abstractions/IRepositoryStore.cs index 5b0b969fba..3644ba26b9 100644 --- a/src/GitVersion.Core/Core/Abstractions/IRepositoryStore.cs +++ b/src/GitVersion.Core/Core/Abstractions/IRepositoryStore.cs @@ -33,7 +33,7 @@ public interface IRepositoryStore /// BranchCommit FindCommitBranchWasBranchedFrom(IBranch? branch, Config configuration, params IBranch[] excludedBranches); - SemanticVersion GetCurrentCommitTaggedVersion(ICommit? commit, string? tagPrefix); + SemanticVersion GetCurrentCommitTaggedVersion(ICommit? commit, string? tagPrefix, bool handleDetachedBranch); IEnumerable GetVersionTagsOnBranch(IBranch branch, string? tagPrefixRegex); IEnumerable<(ITag Tag, SemanticVersion Semver, ICommit Commit)> GetValidVersionTags(string? tagPrefixRegex, DateTimeOffset? olderThan = null); diff --git a/src/GitVersion.Core/Core/GitVersionContextFactory.cs b/src/GitVersion.Core/Core/GitVersionContextFactory.cs index 0343656554..2f8ed80193 100644 --- a/src/GitVersion.Core/Core/GitVersionContextFactory.cs +++ b/src/GitVersion.Core/Core/GitVersionContextFactory.cs @@ -33,7 +33,7 @@ public GitVersionContext Create(GitVersionOptions gitVersionOptions) currentBranch = branchForCommit ?? currentBranch; } - var currentCommitTaggedVersion = this.repositoryStore.GetCurrentCommitTaggedVersion(currentCommit, configuration.TagPrefix); + var currentCommitTaggedVersion = this.repositoryStore.GetCurrentCommitTaggedVersion(currentCommit, configuration.TagPrefix, handleDetachedBranch: currentBranch.IsDetachedHead); var numberOfUncommittedChanges = this.repositoryStore.GetNumberOfUncommittedChanges(); return new GitVersionContext(currentBranch, currentCommit, configuration, currentCommitTaggedVersion, numberOfUncommittedChanges); diff --git a/src/GitVersion.Core/Core/RepositoryStore.cs b/src/GitVersion.Core/Core/RepositoryStore.cs index 2ae5ed42a8..d8ac4706dd 100644 --- a/src/GitVersion.Core/Core/RepositoryStore.cs +++ b/src/GitVersion.Core/Core/RepositoryStore.cs @@ -210,9 +210,9 @@ public BranchCommit FindCommitBranchWasBranchedFrom(IBranch? branch, Config conf } } - public SemanticVersion GetCurrentCommitTaggedVersion(ICommit? commit, string? tagPrefix) + public SemanticVersion GetCurrentCommitTaggedVersion(ICommit? commit, string? tagPrefix, bool handleDetachedBranch) => this.repository.Tags - .SelectMany(t => GetCurrentCommitSemanticVersions(commit, tagPrefix, t)) + .SelectMany(t => GetCurrentCommitSemanticVersions(commit, tagPrefix, t, handleDetachedBranch)) .Max(); public IEnumerable GetVersionTagsOnBranch(IBranch branch, string? tagPrefixRegex) @@ -281,12 +281,20 @@ public bool IsCommitOnBranch(ICommit? baseVersionSource, IBranch branch, ICommit private static bool IsReleaseBranch(INamedReference branch, IEnumerable> releaseBranchConfig) => releaseBranchConfig.Any(c => c.Value?.Regex != null && Regex.IsMatch(branch.Name.Friendly, c.Value.Regex)); - private static IEnumerable GetCurrentCommitSemanticVersions(ICommit? commit, string? tagPrefix, ITag tag) + private IEnumerable GetCurrentCommitSemanticVersions(ICommit? commit, string? tagPrefix, ITag tag, bool handleDetachedBranch) { + if (commit == null) + return Array.Empty(); + var targetCommit = tag.PeeledTargetCommit(); + if (targetCommit == null) + return Array.Empty(); + + var commitToCompare = handleDetachedBranch ? FindMergeBase(commit, targetCommit) : commit; + var tagName = tag.Name.Friendly; - return targetCommit != null && Equals(targetCommit, commit) && SemanticVersion.TryParse(tagName, tagPrefix, out var version) + return Equals(targetCommit, commitToCompare) && SemanticVersion.TryParse(tagName, tagPrefix, out var version) ? new[] { version } : Array.Empty(); } diff --git a/src/GitVersion.Core/PublicAPI.Shipped.txt b/src/GitVersion.Core/PublicAPI.Shipped.txt index a6814b5b0d..bd3d85d7a2 100644 --- a/src/GitVersion.Core/PublicAPI.Shipped.txt +++ b/src/GitVersion.Core/PublicAPI.Shipped.txt @@ -157,7 +157,7 @@ GitVersion.Common.IRepositoryStore.GetBranchesForCommit(GitVersion.ICommit! comm GitVersion.Common.IRepositoryStore.GetChosenBranch(GitVersion.Model.Configuration.Config! configuration) -> GitVersion.IBranch? GitVersion.Common.IRepositoryStore.GetCommitLog(GitVersion.ICommit? baseVersionSource, GitVersion.ICommit? currentCommit) -> System.Collections.Generic.IEnumerable! GitVersion.Common.IRepositoryStore.GetCurrentCommit(GitVersion.IBranch! currentBranch, string? commitId) -> GitVersion.ICommit? -GitVersion.Common.IRepositoryStore.GetCurrentCommitTaggedVersion(GitVersion.ICommit? commit, string? tagPrefix) -> GitVersion.SemanticVersion! +GitVersion.Common.IRepositoryStore.GetCurrentCommitTaggedVersion(GitVersion.ICommit? commit, string? tagPrefix, bool handleDetachedBranch) -> GitVersion.SemanticVersion! GitVersion.Common.IRepositoryStore.GetExcludedInheritBranches(GitVersion.Model.Configuration.Config! configuration) -> System.Collections.Generic.IEnumerable! GitVersion.Common.IRepositoryStore.GetMainlineBranches(GitVersion.ICommit! commit, GitVersion.Model.Configuration.Config! configuration, System.Collections.Generic.IEnumerable>? mainlineBranchConfigs) -> System.Collections.Generic.IDictionary!>! GitVersion.Common.IRepositoryStore.GetMainlineCommitLog(GitVersion.ICommit? baseVersionSource, GitVersion.ICommit? mainlineTip) -> System.Collections.Generic.IEnumerable! @@ -859,7 +859,7 @@ GitVersion.RepositoryStore.GetBranchesForCommit(GitVersion.ICommit! commit) -> S GitVersion.RepositoryStore.GetChosenBranch(GitVersion.Model.Configuration.Config! configuration) -> GitVersion.IBranch? GitVersion.RepositoryStore.GetCommitLog(GitVersion.ICommit? baseVersionSource, GitVersion.ICommit? currentCommit) -> System.Collections.Generic.IEnumerable! GitVersion.RepositoryStore.GetCurrentCommit(GitVersion.IBranch! currentBranch, string? commitId) -> GitVersion.ICommit? -GitVersion.RepositoryStore.GetCurrentCommitTaggedVersion(GitVersion.ICommit? commit, string? tagPrefix) -> GitVersion.SemanticVersion! +GitVersion.RepositoryStore.GetCurrentCommitTaggedVersion(GitVersion.ICommit? commit, string? tagPrefix, bool handleDetachedBranch) -> GitVersion.SemanticVersion! GitVersion.RepositoryStore.GetExcludedInheritBranches(GitVersion.Model.Configuration.Config! configuration) -> System.Collections.Generic.IEnumerable! GitVersion.RepositoryStore.GetMainlineBranches(GitVersion.ICommit! commit, GitVersion.Model.Configuration.Config! configuration, System.Collections.Generic.IEnumerable>? mainlineBranchConfigs) -> System.Collections.Generic.IDictionary!>! GitVersion.RepositoryStore.GetMainlineCommitLog(GitVersion.ICommit? baseVersionSource, GitVersion.ICommit? mainlineTip) -> System.Collections.Generic.IEnumerable! diff --git a/src/GitVersion.Core/VersionCalculation/IncrementStrategyFinder.cs b/src/GitVersion.Core/VersionCalculation/IncrementStrategyFinder.cs index 66d53e85ed..35c04cb59c 100644 --- a/src/GitVersion.Core/VersionCalculation/IncrementStrategyFinder.cs +++ b/src/GitVersion.Core/VersionCalculation/IncrementStrategyFinder.cs @@ -53,7 +53,7 @@ public VersionField DetermineIncrementedField(GitVersionContext context, BaseVer return defaultIncrement; } - return commitMessageIncrement ?? VersionField.None; + return commitMessageIncrement.Value; } public VersionField? GetIncrementForCommits(Config configuration, IEnumerable commits) diff --git a/src/GitVersion.Core/VersionCalculation/NextVersionCalculator.cs b/src/GitVersion.Core/VersionCalculation/NextVersionCalculator.cs index 93d38e3799..5aa62d2572 100644 --- a/src/GitVersion.Core/VersionCalculation/NextVersionCalculator.cs +++ b/src/GitVersion.Core/VersionCalculation/NextVersionCalculator.cs @@ -40,10 +40,6 @@ public NextVersion FindVersion() { this.log.Info($"Current commit is tagged with version {Context.CurrentCommitTaggedVersion}, " + "version calculation is for metadata only."); } - else - { - EnsureHeadIsNotDetached(Context); - } SemanticVersion? taggedSemanticVersion = null;