diff --git a/src/GitVersion.Core/Configuration/ConfigurationConstants.cs b/src/GitVersion.Core/Configuration/ConfigurationConstants.cs
index 017990354d..3f18e73c14 100644
--- a/src/GitVersion.Core/Configuration/ConfigurationConstants.cs
+++ b/src/GitVersion.Core/Configuration/ConfigurationConstants.cs
@@ -19,7 +19,8 @@ internal static class ConfigurationConstants
VersionStrategies.MergeMessage,
VersionStrategies.TaggedCommit,
VersionStrategies.TrackReleaseBranches,
- VersionStrategies.VersionInBranchName
+ VersionStrategies.VersionInBranchName,
+ VersionStrategies.MergeCommit
];
public const string DefaultAssemblyInformationalFormat = "{InformationalVersion}";
public const string DefaultCommitDateFormat = "yyyy-MM-dd";
diff --git a/src/GitVersion.Core/PublicAPI.Shipped.txt b/src/GitVersion.Core/PublicAPI.Shipped.txt
index 2b3133a9e8..28bfc6f33f 100644
--- a/src/GitVersion.Core/PublicAPI.Shipped.txt
+++ b/src/GitVersion.Core/PublicAPI.Shipped.txt
@@ -680,6 +680,7 @@ GitVersion.VersionCalculation.VersionStrategies
GitVersion.VersionCalculation.VersionStrategies.ConfiguredNextVersion = 2 -> GitVersion.VersionCalculation.VersionStrategies
GitVersion.VersionCalculation.VersionStrategies.Fallback = 1 -> GitVersion.VersionCalculation.VersionStrategies
GitVersion.VersionCalculation.VersionStrategies.Mainline = 64 -> GitVersion.VersionCalculation.VersionStrategies
+GitVersion.VersionCalculation.VersionStrategies.MergeCommit = 128 -> GitVersion.VersionCalculation.VersionStrategies
GitVersion.VersionCalculation.VersionStrategies.MergeMessage = 4 -> GitVersion.VersionCalculation.VersionStrategies
GitVersion.VersionCalculation.VersionStrategies.None = 0 -> GitVersion.VersionCalculation.VersionStrategies
GitVersion.VersionCalculation.VersionStrategies.TaggedCommit = 8 -> GitVersion.VersionCalculation.VersionStrategies
diff --git a/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/MergeCommitVersionStrategy.cs b/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/MergeCommitVersionStrategy.cs
new file mode 100644
index 0000000000..180f92b619
--- /dev/null
+++ b/src/GitVersion.Core/VersionCalculation/VersionSearchStrategies/MergeCommitVersionStrategy.cs
@@ -0,0 +1,97 @@
+using GitVersion.Common;
+using GitVersion.Configuration;
+using GitVersion.Core;
+using GitVersion.Extensions;
+using GitVersion.Git;
+using GitVersion.Logging;
+
+namespace GitVersion.VersionCalculation;
+
+///
+/// Version is extracted from older merge commits.
+/// BaseVersionSource is the commit where the message was found.
+///
+internal sealed class MergeCommitVersionStrategy(ILog log, Lazy contextLazy,
+ IRepositoryStore repositoryStore, IIncrementStrategyFinder incrementStrategyFinder, IEffectiveBranchConfigurationFinder effectiveBranchConfigurationFinder,
+ ITaggedSemanticVersionRepository taggedSemanticVersionRepository
+ )
+ : IVersionStrategy
+{
+ private readonly ILog log = log.NotNull();
+ private readonly Lazy contextLazy = contextLazy.NotNull();
+ private readonly IRepositoryStore repositoryStore = repositoryStore.NotNull();
+ private readonly IIncrementStrategyFinder incrementStrategyFinder = incrementStrategyFinder.NotNull();
+ private readonly IEffectiveBranchConfigurationFinder effectiveBranchConfigurationFinder = effectiveBranchConfigurationFinder.NotNull();
+ private readonly ITaggedSemanticVersionRepository taggedSemanticVersionRepository = taggedSemanticVersionRepository.NotNull();
+
+ private GitVersionContext Context => contextLazy.Value;
+
+ public IEnumerable GetBaseVersions(EffectiveBranchConfiguration configuration)
+ {
+ configuration.NotNull();
+
+ if (!Context.Configuration.VersionStrategy.HasFlag(VersionStrategies.MergeCommit))
+ {
+ yield break;
+ }
+
+ var taggedCommits = this.taggedSemanticVersionRepository.GetTaggedSemanticVersions(
+ tagPrefix: Context.Configuration.TagPrefixPattern,
+ format: Context.Configuration.SemanticVersionFormat,
+ ignore: Context.Configuration.Ignore
+ );
+ var previousVersion = new SemanticVersion(0, 0, 0);
+
+ // Must Loop In Reverse To Ensure Correct Version Calculation
+ foreach (var commit in configuration.Value.Ignore.Filter(Context.CurrentBranchCommits.ToArray()).Reverse())
+ {
+ if (taggedCommits.Contains(commit))
+ {
+ this.log.Debug($"Found tagged commit {commit}, adjusting previous version.");
+ previousVersion = taggedCommits[commit].First().Value;
+ }
+ if (!commit.IsMergeCommit())
+ {
+ continue;
+ }
+
+ // Using Merge Message Since The Formats Are Identical
+ if (!MergeMessage.TryParse(commit, Context.Configuration, out var mergeMessage))
+ {
+ continue;
+ }
+
+ this.log.Info($"Found commit [{commit}] matching merge message format: {mergeMessage.FormatName}");
+
+ var currentBranch = this.repositoryStore.GetTargetBranch(mergeMessage.MergedBranch!.Friendly);
+ var branchConfiguration = this.effectiveBranchConfigurationFinder.GetConfigurations(currentBranch, Context.Configuration).First();
+ var baseVersionSource = this.repositoryStore.FindMergeBase(commit.Parents[0], commit.Parents[1]);
+
+ var label = branchConfiguration.Value.GetBranchSpecificLabel(mergeMessage.MergedBranch!.Friendly, "");
+ var increment = this.incrementStrategyFinder.DetermineIncrementedField(
+ currentCommit: commit,
+ baseVersionSource: baseVersionSource,
+ shouldIncrement: true,
+ configuration: branchConfiguration.Value,
+ label: label
+ );
+
+ yield return new BaseVersion($"Merge Commit From '{mergeMessage.MergedBranch?.Friendly}'", previousVersion
+ )
+ {
+ Operator = new()
+ {
+ Increment = increment,
+ ForceIncrement = false,
+ Label = label
+ }
+ };
+
+ previousVersion = previousVersion.Increment(
+ increment,
+ label,
+ true
+ );
+ }
+ }
+}
diff --git a/src/GitVersion.Core/VersionCalculation/VersionStrategies.cs b/src/GitVersion.Core/VersionCalculation/VersionStrategies.cs
index 4fe020c87a..fd5621c9af 100644
--- a/src/GitVersion.Core/VersionCalculation/VersionStrategies.cs
+++ b/src/GitVersion.Core/VersionCalculation/VersionStrategies.cs
@@ -10,5 +10,6 @@ public enum VersionStrategies
TaggedCommit = 8,
TrackReleaseBranches = 16,
VersionInBranchName = 32,
- Mainline = 64
+ Mainline = 64,
+ MergeCommit = 128
}