Skip to content

Commit 00c26d4

Browse files
authored
Merge pull request #1225 from JakeGinnivan/feature/pick-better-merge-base
Pick better merge base
2 parents a99f256 + de2d3f2 commit 00c26d4

17 files changed

+305
-52
lines changed

BREAKING CHANGES.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ v4.0.0
88
- The default keys are: master, develop, feature, release, pull-request, hotfix, support
99
- Just run GitVersion.exe in your project directory and it will tell you what to change your config keys to
1010
- For example, `dev(elop)?(ment)?$` is now just `develop`, we suggest not overring regex's unless you really want to use a different convention.
11+
- source-branches added as a configuration option for branches, it helps GitVersion pick the correct source branch
1112

1213
v3.0.0
1314
- NextVersion.txt has been deprecated, only GitVersionConfig.yaml is supported

docs/configuration.md

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,70 @@ values, but here they are if you need to:
243243
### regex
244244
This is the regex which is used to match the current branch to the correct branch configuration.
245245

246+
### source-branches
247+
Because git commits only refer to parent commits (not branches) GitVersion sometimes cannot tell which branch the current branch was branched from.
248+
249+
Take this commit graph
250+
251+
```
252+
* release/1.0.0 * feature/foo
253+
| ________________/
254+
|/
255+
*
256+
*
257+
* (master)
258+
```
259+
260+
By looking at this graph, you cannot tell which of these scenarios happened:
261+
262+
1. feature/foo branches off release/1.0.0
263+
- Branch release/1.0.0 from master
264+
- Branch feature/foo from release/1.0.0
265+
- Add a commit to both release/1.0.0 and feature/foo
266+
- release/1.0.0 is the base for feature/foo
267+
268+
2. release/1.0.0 branches off feature/foo
269+
- Branch feature/foo from master
270+
- Branch release/1.0.0 from feature/foo
271+
- Add a commit to both release/1.0.0 and feature/foo
272+
- feature/foo is the base for release/1.0.0
273+
274+
Or put more simply, you cannot tell which branch was created first, `release/1.0.0` or `feature/foo`.
275+
276+
To resolve this issue, we give GitVersion a hint about our branching workflows by telling it what types of branches a branch can be created from. For example, feature branches are, by default, configured to have the following source branches:
277+
278+
`source-branches: ['master', 'develop', 'feature', 'hotfix', 'support']`
279+
280+
This means that we will never bother to evaluate pull request branches as merge base options and being explicit in this way also improves the performance of GitVersion.
281+
282+
### is-source-branch-for
283+
The reverse of `source-branches`. This property was introduced to keep it easy to extend GitVersion's config.
284+
285+
It exists to make it easier to extend GitVersion's configuration. If only `source-branches` exists and you add a new branch type, for instance `unstable/`, you then need to re-define the `source-branches` configuration value for existing branches (like feature/) to now include the new unstable branch.
286+
287+
A complete example:
288+
289+
```
290+
branches:
291+
unstable:
292+
regex: ...
293+
is-source-branch-for: ['master', 'develop', 'feature', 'hotfix', 'support']
294+
```
295+
296+
Without this configuration value you would have to do:
297+
298+
299+
```
300+
branches:
301+
unstable:
302+
regex: ...
303+
feature:
304+
source-branches: ['unstable', 'develop', 'feature', 'hotfix', 'support']
305+
release:
306+
source-branches: ['unstable', 'develop']
307+
etc...
308+
```
309+
246310
### branches
247311
The header for all the individual branch configuration.
248312

src/GitVersionCore.Tests/ConfigProviderTests.CanWriteOutEffectiveConfiguration.approved.txt

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,27 @@ build-metadata-padding: 4
1212
commits-since-version-source-padding: 4
1313
commit-message-incrementing: Enabled
1414
branches:
15+
develop:
16+
mode: ContinuousDeployment
17+
tag: alpha
18+
increment: Minor
19+
prevent-increment-of-merged-branch-version: false
20+
track-merge-target: true
21+
regex: dev(elop)?(ment)?$
22+
source-branches: []
23+
tracks-release-branches: true
24+
is-release-branch: false
25+
is-mainline: false
1526
master:
1627
mode: ContinuousDelivery
1728
tag: ''
1829
increment: Patch
1930
prevent-increment-of-merged-branch-version: true
2031
track-merge-target: false
2132
regex: master
33+
source-branches:
34+
- develop
35+
- release
2236
tracks-release-branches: false
2337
is-release-branch: false
2438
is-mainline: true
@@ -29,6 +43,11 @@ branches:
2943
prevent-increment-of-merged-branch-version: true
3044
track-merge-target: false
3145
regex: releases?[/-]
46+
source-branches:
47+
- develop
48+
- master
49+
- support
50+
- release
3251
tracks-release-branches: false
3352
is-release-branch: true
3453
is-mainline: false
@@ -39,6 +58,13 @@ branches:
3958
prevent-increment-of-merged-branch-version: false
4059
track-merge-target: false
4160
regex: features?[/-]
61+
source-branches:
62+
- develop
63+
- master
64+
- release
65+
- feature
66+
- support
67+
- hotfix
4268
tracks-release-branches: false
4369
is-release-branch: false
4470
is-mainline: false
@@ -50,6 +76,13 @@ branches:
5076
tag-number-pattern: '[/-](?<number>\d+)'
5177
track-merge-target: false
5278
regex: (pull|pull\-requests|pr)[/-]
79+
source-branches:
80+
- develop
81+
- master
82+
- release
83+
- feature
84+
- support
85+
- hotfix
5386
tracks-release-branches: false
5487
is-release-branch: false
5588
is-mainline: false
@@ -60,6 +93,10 @@ branches:
6093
prevent-increment-of-merged-branch-version: false
6194
track-merge-target: false
6295
regex: hotfix(es)?[/-]
96+
source-branches:
97+
- develop
98+
- master
99+
- support
63100
tracks-release-branches: false
64101
is-release-branch: false
65102
is-mainline: false
@@ -70,18 +107,10 @@ branches:
70107
prevent-increment-of-merged-branch-version: true
71108
track-merge-target: false
72109
regex: support[/-]
110+
source-branches:
111+
- master
73112
tracks-release-branches: false
74113
is-release-branch: false
75114
is-mainline: true
76-
develop:
77-
mode: ContinuousDeployment
78-
tag: alpha
79-
increment: Minor
80-
prevent-increment-of-merged-branch-version: false
81-
track-merge-target: true
82-
regex: dev(elop)?(ment)?$
83-
tracks-release-branches: true
84-
is-release-branch: false
85-
is-mainline: false
86115
ignore:
87116
sha: []

src/GitVersionCore.Tests/ConfigProviderTests.cs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -100,11 +100,12 @@ public void RegexIsRequired()
100100
tag: bugfix";
101101
SetupConfigFileContent(text);
102102
var ex = Should.Throw<GitVersionConfigurationException>(() => ConfigurationProvider.Provide(repoPath, fileSystem));
103-
ex.Message.ShouldBe("Branch configuration 'bug' is missing required configuration 'regex'");
103+
ex.Message.ShouldBe("Branch configuration 'bug' is missing required configuration 'regex'\n\n" +
104+
"See http://gitversion.readthedocs.io/en/latest/configuration/ for more info");
104105
}
105106

106107
[Test]
107-
public void CanProvideConfigForNewBranch()
108+
public void SourceBranchIsRequired()
108109
{
109110
const string text = @"
110111
next-version: 2.0.0
@@ -113,6 +114,22 @@ public void CanProvideConfigForNewBranch()
113114
regex: 'bug[/-]'
114115
tag: bugfix";
115116
SetupConfigFileContent(text);
117+
var ex = Should.Throw<GitVersionConfigurationException>(() => ConfigurationProvider.Provide(repoPath, fileSystem));
118+
ex.Message.ShouldBe("Branch configuration 'bug' is missing required configuration 'source-branches'\n\n" +
119+
"See http://gitversion.readthedocs.io/en/latest/configuration/ for more info");
120+
}
121+
122+
[Test]
123+
public void CanProvideConfigForNewBranch()
124+
{
125+
const string text = @"
126+
next-version: 2.0.0
127+
branches:
128+
bug:
129+
regex: 'bug[/-]'
130+
tag: bugfix
131+
source-branches: []";
132+
SetupConfigFileContent(text);
116133
var config = ConfigurationProvider.Provide(repoPath, fileSystem);
117134

118135
config.Branches["bug"].Regex.ShouldBe("bug[/-]");

src/GitVersionCore.Tests/GitRepoMetadataProviderTests.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -52,10 +52,10 @@ public void FindsCorrectMergeBaseForForwardMerge()
5252

5353
var develop = fixture.Repository.FindBranch("develop");
5454
var release = fixture.Repository.FindBranch("release-2.0.0");
55-
var releaseBranchMergeBase = new GitRepoMetadataProvider(fixture.Repository)
55+
var releaseBranchMergeBase = new GitRepoMetadataProvider(fixture.Repository, new Config())
5656
.FindMergeBase(release, develop);
5757

58-
var developMergeBase = new GitRepoMetadataProvider(fixture.Repository)
58+
var developMergeBase = new GitRepoMetadataProvider(fixture.Repository, new Config())
5959
.FindMergeBase(develop, release);
6060

6161
fixture.Repository.DumpGraph(Console.WriteLine);
@@ -109,10 +109,10 @@ public void FindsCorrectMergeBaseForForwardMergeMovesOn()
109109

110110
var develop = fixture.Repository.FindBranch("develop");
111111
var release = fixture.Repository.FindBranch("release-2.0.0");
112-
var releaseBranchMergeBase = new GitRepoMetadataProvider(fixture.Repository)
112+
var releaseBranchMergeBase = new GitRepoMetadataProvider(fixture.Repository, new Config())
113113
.FindMergeBase(release, develop);
114114

115-
var developMergeBase = new GitRepoMetadataProvider(fixture.Repository)
115+
var developMergeBase = new GitRepoMetadataProvider(fixture.Repository, new Config())
116116
.FindMergeBase(develop, release);
117117

118118
fixture.Repository.DumpGraph(Console.WriteLine);
@@ -184,10 +184,10 @@ public void FindsCorrectMergeBaseForMultipleForwardMerges()
184184

185185
var develop = fixture.Repository.FindBranch("develop");
186186
var release = fixture.Repository.FindBranch("release-2.0.0");
187-
var releaseBranchMergeBase = new GitRepoMetadataProvider(fixture.Repository)
187+
var releaseBranchMergeBase = new GitRepoMetadataProvider(fixture.Repository, new Config())
188188
.FindMergeBase(release, develop);
189189

190-
var developMergeBase = new GitRepoMetadataProvider(fixture.Repository)
190+
var developMergeBase = new GitRepoMetadataProvider(fixture.Repository, new Config())
191191
.FindMergeBase(develop, release);
192192

193193
fixture.Repository.DumpGraph(Console.WriteLine);

src/GitVersionCore.Tests/GitVersionContextTests.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using LibGit2Sharp;
66
using NUnit.Framework;
77
using Shouldly;
8+
using System.Collections.Generic;
89

910
public class GitVersionContextTests
1011
{
@@ -98,8 +99,8 @@ public void UsesFirstBranchConfigWhenMultipleMatch()
9899
VersioningMode = VersioningMode.ContinuousDelivery,
99100
Branches =
100101
{
101-
{ "release/latest", new BranchConfig { Increment = IncrementStrategy.None, Regex = "release/latest" } },
102-
{ "release", new BranchConfig { Increment = IncrementStrategy.Patch, Regex = "releases?[/-]" } }
102+
{ "release/latest", new BranchConfig { Increment = IncrementStrategy.None, Regex = "release/latest", SourceBranches = new List<string>() } },
103+
{ "release", new BranchConfig { Increment = IncrementStrategy.Patch, Regex = "releases?[/-]", SourceBranches = new List<string>() } }
103104
}
104105
}.ApplyDefaults();
105106

src/GitVersionCore.Tests/IntegrationTests/DevelopScenarios.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
using GitVersionCore.Tests;
44
using LibGit2Sharp;
55
using NUnit.Framework;
6+
using System.Collections.Generic;
67

78
[TestFixture]
89
public class DevelopScenarios
@@ -64,7 +65,8 @@ public void CanChangeDevelopTagViaConfig()
6465
{
6566
"develop", new BranchConfig
6667
{
67-
Tag = "alpha"
68+
Tag = "alpha",
69+
SourceBranches = new List<string>()
6870
}
6971
}
7072
}

src/GitVersionCore.Tests/IntegrationTests/FeatureBranchScenarios.cs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,16 @@ public void BranchCreatedAfterFastForwardMergeShouldInheritCorrectly()
4242
{
4343
Branches =
4444
{
45-
{ "unstable", new BranchConfig { Increment = IncrementStrategy.Minor, Regex = "unstable"} }
45+
{
46+
"unstable",
47+
new BranchConfig
48+
{
49+
Increment = IncrementStrategy.Minor,
50+
Regex = "unstable",
51+
SourceBranches = new List<string>(),
52+
IsSourceBranchFor = new [] { "feature" }
53+
}
54+
}
4655
}
4756
};
4857

src/GitVersionCore.Tests/IntegrationTests/OtherScenarios.cs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using GitVersion;
66
using LibGit2Sharp;
77
using NUnit.Framework;
8+
using System.Collections.Generic;
89

910
[TestFixture]
1011
public class OtherScenarios
@@ -56,7 +57,8 @@ public void AllowHavingMainInsteadOfMaster()
5657
Tag = "useBranchName",
5758
Increment = IncrementStrategy.Patch,
5859
PreventIncrementOfMergedBranchVersion = true,
59-
TrackMergeTarget = false
60+
TrackMergeTarget = false,
61+
SourceBranches = new List<string>()
6062
});
6163

6264
using (var fixture = new EmptyRepositoryFixture())

src/GitVersionCore.Tests/IntegrationTests/ReleaseBranchScenarios.cs

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -418,7 +418,7 @@ public void CommitOnDevelop_AfterReleaseBranchMergeToDevelop_ShouldNotResetCount
418418
fixture.AssertFullSemver(config, "2.0.0-beta.5");
419419
}
420420
}
421-
421+
422422
public void ReleaseBranchShouldUseBranchNameVersionDespiteBumpInPreviousCommit()
423423
{
424424
using (var fixture = new EmptyRepositoryFixture())
@@ -463,4 +463,53 @@ public void ReleaseBranchedAtCommitWithSemverMessageShouldUseBranchNameVersion()
463463
fixture.AssertFullSemver("2.0.0-beta.1+1");
464464
}
465465
}
466+
467+
[Test]
468+
public void FeatureFromReleaseBranch_ShouldNotResetCount()
469+
{
470+
var config = new Config
471+
{
472+
VersioningMode = VersioningMode.ContinuousDeployment
473+
};
474+
475+
using (var fixture = new EmptyRepositoryFixture())
476+
{
477+
fixture.Repository.MakeACommit("initial");
478+
fixture.Repository.CreateBranch("develop");
479+
Commands.Checkout(fixture.Repository, "develop");
480+
fixture.Repository.CreateBranch("release-2.0.0");
481+
Commands.Checkout(fixture.Repository, "release-2.0.0");
482+
fixture.AssertFullSemver(config, "2.0.0-beta.0");
483+
484+
// Make some commits on release
485+
fixture.Repository.MakeCommits(10);
486+
fixture.AssertFullSemver(config, "2.0.0-beta.10");
487+
488+
// Create feature from release
489+
fixture.BranchTo("feature/xxx");
490+
fixture.Repository.MakeACommit("feature 1");
491+
fixture.Repository.MakeACommit("feature 2");
492+
493+
// Check version on release
494+
Commands.Checkout(fixture.Repository, "release-2.0.0");
495+
fixture.AssertFullSemver(config, "2.0.0-beta.10");
496+
fixture.Repository.MakeACommit("release 11");
497+
fixture.AssertFullSemver(config, "2.0.0-beta.11");
498+
499+
// Make new commit on feature
500+
Commands.Checkout(fixture.Repository, "feature/xxx");
501+
fixture.Repository.MakeACommit("feature 3");
502+
503+
// Checkout to release (no new commits)
504+
Commands.Checkout(fixture.Repository, "release-2.0.0");
505+
fixture.AssertFullSemver(config, "2.0.0-beta.11");
506+
507+
// Merge feature to release
508+
fixture.Repository.MergeNoFF("feature/xxx", Generate.SignatureNow());
509+
fixture.AssertFullSemver(config, "2.0.0-beta.15");
510+
511+
fixture.Repository.MakeACommit("release 13 - after feature merge");
512+
fixture.AssertFullSemver(config, "2.0.0-beta.16");
513+
}
514+
}
466515
}

0 commit comments

Comments
 (0)