adamralph/minver

Multiple projects in a single repo - Add commit filter based on path in addition to tag prefix

Closed this issue · 6 comments

Use case(s)

We manage multiple services in a mono repository and would like to have an individual version for each service. In addition to a service specific tag prefix, we would like to count only those commits which contain changes in the service's directory. In other words, if commits happened on the repo but are not related to the service, the service version should not change.

Description

Add a path filter attribute (GLOB pattern, maybe two parameters for includes and excludes) to the tooling. If the path filter is set, the resulting commits are filtered to only return the ones which match the path filter parameter value for the associated changed files.

Hi @marc-mueller, thanks for raising this.

This idea has been raised before in #500 and #519 and in both cases, it was decided not to take it further and to use the workarounds mentioned in those threads instead.

However, after looking into it further, what I would be prepared to do is allow the passing through of specific paths to the git log command which used by MinVer to retrieve the commit history. Currently, MinVer runs git log --pretty=format:"%H %P" to retrieve the commit history for the entire repo. We could introduce something like:

<MinVerCommitHistoryPaths>path1 path2</MinVerCommitHistoryPaths>

which translates to:

git log --pretty=format:"%H %P" -- path1 path2

Would that be enough for your needs?

Hi @adamralph

Thanks for the fast feedback. Yes, this should do the trick if you put the path definition down to git log. So you will end up with a filtered commit list which is then used for the version calculation. This looks like a good and easy solution.

I assume this parameter will be added to the CLI as well (we will use the cli and set the tag prefix and path commithistorypath accordingly on the cli call)

@marc-mueller yes, this should be added to the command line as well. Given that the value of the option will be used verbatim as the value of the git log paths (--) option, I think it's probably better to name it MinVerGitLogPaths/-glp|--git-log-paths.

@adamralph yes, you are right. So it is clear to the user that is is a log path and this also clarifies which syntax to use.

@marc-mueller after giving this more thought, I'm not convinced this is a practical solution.

Consider that build output may be influenced in several ways by artifacts which exist outside the project folder. For example, Directory.Build.props or Directory.Build.targets in a containing folder, or linked files from some other folder.

Also consider project references. For example, project A references project B. A change is made in project B's folder, so its version increases. Project A now references the new version of project B, but the version of project A doesn't change because no change has been made in project A's folder.

Also consider that non-functional changes may be made to a project folder which do not affect the version. For example, you may have a messy csproj, so you tidy it up and reformat it. Oops—the version has increased.

So in general, while the model of only increasing the version number of a project when a change is made to its folder may hold in the very simplest case, I feel it's likely to break down early in most scenarios. I grant that you could diligently add the path of every single artifact which may influence the build output to the new property proposed here. I also grant that you could diligently withhold all changes to a projects folder until a time when you make a change which does affect the version. But I have to ask—is this simpler than abandoning MinVer and versioning manually instead (using the <Version> property, etc.)? I'm struggling to see that it is. It feels elaborate and error prone, and it seems simpler to revert to manual versioning.

Another idea I had is to allow "locking" of specific projects to the last tag with their prefix. For example:

<MinVerTagPrefix>foo</MinVerTagPrefix>
<MinVerLockToLastTag>true</MinVerLockToLastTag>

But with this, the main benefit of MinVer (versioning without having to commit) is lost. Again, I'm struggling to see much benefit over manual versioning with the <Version> property, etc.

Stepping back, I guess what I'm saying is that automatic versioning based on Git history isn't really practical for repos which contain multiple projects which are not released in lock-step. It seems that manual versioning using <Version>, etc. is a simpler and less error prone solution.

@marc-mueller I'm closing this based on my last comment. Please feel free to re-open if you have further input.