Skip to content

Commit 5c79c50

Browse files
committed
Two additional heuristics for choosing mainline
When there is more than one potential mainline branch, before falling back to the first branch in the list, choose 1) the current branch, if it is a possible mainline; or 2) the first potential mainline from which the current commit is reachable in a FirstParentOnly walk (i.e. is a direct commit on that branch). Additionally, don't discard potential mainlines with equal tip because it might reduce the effectiveness of the new heuristics. Fixes the test MainlineDevelopmentMode.VerifySupportForwardMerge vs the previous commit.
1 parent fd9a671 commit 5c79c50

File tree

1 file changed

+34
-13
lines changed

1 file changed

+34
-13
lines changed

src/GitVersionCore/VersionCalculation/MainlineVersionCalculator.cs

Lines changed: 34 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ public SemanticVersion FindMainlineModeVersion(BaseVersion baseVersion, GitVersi
3434
//
3535

3636
var mergeBase = baseVersion.BaseVersionSource;
37-
var mainline = GetMainline(context);
37+
var mainline = GetMainline(context, baseVersion.BaseVersionSource);
3838
var mainlineTip = mainline.Tip;
3939

4040
// when the current branch is not mainline, find the effective mainline tip for versioning the branch
@@ -101,25 +101,14 @@ SemanticVersion AggregateMergeCommitIncrement(GitVersionContext context, Commit
101101
return mainlineVersion;
102102
}
103103

104-
static Branch GetMainline(GitVersionContext context)
104+
static Branch GetMainline(GitVersionContext context, Commit baseVersionSource)
105105
{
106106
var mainlineBranchConfigs = context.FullConfiguration.Branches.Where(b => b.Value.IsMainline == true).ToList();
107-
var seenMainlineTips = new List<string>();
108107
var mainlineBranches = context.Repository.Branches
109108
.Where(b =>
110109
{
111110
return mainlineBranchConfigs.Any(c => Regex.IsMatch(b.FriendlyName, c.Value.Regex));
112111
})
113-
.Where(b =>
114-
{
115-
if (seenMainlineTips.Contains(b.Tip.Sha))
116-
{
117-
Logger.WriteInfo("Multiple possible mainlines pointing at the same commit, dropping " + b.FriendlyName);
118-
return false;
119-
}
120-
seenMainlineTips.Add(b.Tip.Sha);
121-
return true;
122-
})
123112
.Select(b => new
124113
{
125114
MergeBase = context.Repository.ObjectDatabase.FindMergeBase(b.Tip, context.CurrentCommit),
@@ -143,6 +132,38 @@ static Branch GetMainline(GitVersionContext context)
143132
return mainlineBranch;
144133
}
145134

135+
// prefer current branch, if it is a mainline branch
136+
if (possibleMainlineBranches.Any(context.CurrentBranch.IsSameBranch))
137+
{
138+
Logger.WriteInfo(string.Format("Choosing {0} as mainline because it is the current branch", context.CurrentBranch.FriendlyName));
139+
return context.CurrentBranch;
140+
}
141+
142+
// prefer a branch on which the merge base was a direct commit, if there is such a branch
143+
var firstMatchingCommitBranch = possibleMainlineBranches
144+
.FirstOrDefault(b =>
145+
{
146+
var filter = new CommitFilter
147+
{
148+
IncludeReachableFrom = b,
149+
ExcludeReachableFrom = baseVersionSource,
150+
FirstParentOnly = true,
151+
};
152+
var query = context.Repository.Commits.QueryBy(filter);
153+
154+
return query.Contains(firstMatchingCommit);
155+
});
156+
if (firstMatchingCommitBranch != null)
157+
{
158+
var message = string.Format(
159+
"Choosing {0} as mainline because {1}'s merge base was a direct commit to {0}",
160+
firstMatchingCommitBranch.FriendlyName,
161+
context.CurrentBranch.FriendlyName);
162+
Logger.WriteInfo(message);
163+
164+
return firstMatchingCommitBranch;
165+
}
166+
146167
var chosenMainline = possibleMainlineBranches[0];
147168
Logger.WriteInfo(string.Format(
148169
"Multiple mainlines ({0}) have the same merge base for the current branch, choosing {1} because we found that branch first...",

0 commit comments

Comments
 (0)