# MinVer
![MinVer](https://raw.githubusercontent.com/adamralph/minver/28ce6ec69c4489c034f7eea78665a0cc9980eb81/assets/minver.svg)
_[![MinVer NuGet version](https://img.shields.io/nuget/v/MinVer.svg?style=flat&label=nuget%3A%20MinVer)](https://www.nuget.org/packages/MinVer)_
_[![minver-cli NuGet version](https://img.shields.io/nuget/v/minver-cli.svg?style=flat&label=nuget%3A%20minver-cli)](https://www.nuget.org/packages/minver-cli)_
_[![Build status](https://github.com/adamralph/minver/actions/workflows/ci.yml/badge.svg?branch=main)](https://github.com/adamralph/minver/actions/workflows/ci.yml)_
_[![CodeQL analysis](https://github.com/adamralph/minver/actions/workflows/codeql-analysis.yml/badge.svg?branch=main)](https://github.com/adamralph/minver/actions/workflows/codeql-analysis.yml)_
_[![lint](https://github.com/adamralph/minver/actions/workflows/lint.yml/badge.svg?branch=main)](https://github.com/adamralph/minver/actions/workflows/lint.yml)_
_[![Spell check](https://github.com/adamralph/minver/actions/workflows/spell-check.yml/badge.svg?branch=main)](https://github.com/adamralph/minver/actions/workflows/spell-check.yml)_
A minimalist [.NET package](https://www.nuget.org/packages/MinVer) for versioning .NET SDK-style projects using Git tags.
Platform support: all platforms supported by .NET SDK-style projects.
Also available as a [command-line tool](#can-i-use-minver-to-version-software-which-is-not-built-using-a-net-sdk-style-project) for use in any Git repository.
- [Prerequisites](#prerequisites)
- [Quick start](#quick-start)
- [Usage](#usage)
- [How it works](#how-it-works)
- [Version numbers](#version-numbers)
- [Options](#options)
- [FAQ](#faq)
## Prerequisites
- [.NET SDK 6.0 or later](https://www.microsoft.com/net/download)
- [Git](https://git-scm.com/)
## Quick start
- Install [MinVer](https://www.nuget.org/packages/MinVer).
- Build your project.
Your project will be versioned according to the latest tag found in the commit history.
**To build with GitHub Actions, [set the fetch depth appropriately](#why-is-the-default-version-sometimes-used-in-github-actions-azure-pipelines-and-travis-ci-when-a-version-tag-exists-in-the-history).**
## Usage
When you want to release a version of your software, whether it's a pre-release, RTM, patch, or anything else, simply create a tag on the commit you want to release with a name which is a valid [SemVer 2.x](https://semver.org/spec/v2.0.0.html) version. For example:
```shell
git tag 1.2.3
git push --tags
```
When you build your software from the commit with that tag, MinVer will apply the version to the assemblies and packages. (If you like to prefix your tag names, see the [FAQ](#can-i-prefix-my-tag-names).)
Bear in mind that MinVer is unaware of the branches which contain the commit, nor your release process, so [it is compatible with any branching or release strategy you choose](#can-i-use-my-own-branching-strategy).
_NOTE: The MinVer package reference should normally include `PrivateAssets="All"`. See [NuGet docs](https://docs.microsoft.com/en-us/nuget/consume-packages/package-references-in-project-files#controlling-dependency-assets) for more info. If you install MinVer using an IDE or tool, this should be done for you automatically._
## How it works
- If the current commit has a version tag:
- The version is used as-is.
- If the current commit _does not_ have a version tag:
- The commit history is searched for the latest commit with a version tag.
- If a commit with a version tag is found:
- If the version is a [pre-release](https://semver.org/spec/v2.0.0.html#spec-item-9):
- The version is used as-is, with [height](#height) added.
- If the version is RTM (not pre-release):
- The patch number is incremented, but this [can be customised](#can-i-auto-increment-the-minor-or-major-version-after-an-rtm-tag-instead-of-the-patch-version).
- Default pre-release identifiers are added. The default identifiers are `alpha.0`, but this [can be customised](#can-i-change-the-default-pre-release-identifiers-from-alpha0-to-something-else).
- For example, if the latest version tag is `1.0.0`, the current version is `1.0.1-alpha.0`.
- [Height](#height) is added.
- If no commit with a version tag is found:
- The default version `0.0.0-alpha.0` is used, with [height](#height) added.
### Height
If the current commit does not have a version tag, another number is added to the pre-release identifiers. This is the number of commits since the latest commit with a version tag or, if no commits have a version tag, since the root commit. This is known as "height". For example, if the latest version tag found is `1.0.0-beta.1`, at a height of 42 commits, the calculated version is `1.0.0-beta.1.42`.
This behaviour can be [disabled](#can-i-ignore-the-height-of-the-latest-tag-or-root-commit).
## Version numbers
MinVer sets the following custom properties:
- `MinVerVersion`
- `MinVerMajor`
- `MinVerMinor`
- `MinVerPatch`
- `MinVerPreRelease`
- `MinVerBuildMetadata`
Those properties are used to set the following .NET SDK properties, satisfying the official [open-source library guidance for version numbers](https://docs.microsoft.com/en-ca/dotnet/standard/library-guidance/versioning#version-numbers):
| Property | Value |
|------------------------|-----------------------------------------------------------------------------------------------------------------|
| `AssemblyVersion` | `{MinVerMajor}.0.0.0` |
| `FileVersion` | `{MinVerMajor}.{MinVerMinor}.{MinVerPatch}.0` |
| `InformationalVersion` | `{MinVerVersion}` |
| `PackageVersion` | `{MinVerMajor}.{MinVerMinor}.{MinVerPatch}` (or `{MinVerMajor}.{MinVerMinor}.{MinVerPatch}-{MinVerPreRelease}`) |
| `Version` | `{MinVerMajor}.{MinVerMinor}.{MinVerPatch}` (or `{MinVerMajor}.{MinVerMinor}.{MinVerPatch}-{MinVerPreRelease}`) |
This behaviour can be [customised](#can-i-use-the-version-calculated-by-minver-for-other-purposes).
## Options
Options may be specified as either MSBuild properties (for the [MinVer](https://www.nuget.org/packages/MinVer) package), command-line options (for the [minver-cli](https://www.nuget.org/packages/minver-cli) package), or environment variables (for both the [MinVer](https://www.nuget.org/packages/MinVer) and [minver-cli](https://www.nuget.org/packages/minver-cli) packages).
| MSBuild property or environment variable | Command-line option |
| ----------------------------------------------------------------------------------------------------------------------- | -------------------------------------------------------------------------------------------------------------------------- |
| [`MinVerAutoIncrement`](#can-i-auto-increment-the-minor-or-major-version-after-an-rtm-tag-instead-of-the-patch-version) | [`-a\|--auto-increment`](#can-i-auto-increment-the-minor-or-major-version-after-an-rtm-tag-instead-of-the-patch-version) |
| [`MinVerBuildMetadata`](#can-i-include-build-metadata-in-the-version) | [`-b\|--build-metadata`](#can-i-include-build-metadata-in-the-version) |
| [`MinVerDefaultPreReleaseIdentifiers`](#can-i-change-the-default-pre-release-identifiers-from-alpha0-to-something-else) | [`-p\|--default-pre-release-identifiers`](#can-i-change-the-default-pre-release-identifiers-from-alpha0-to-something-else) |
| [`MinVerIgnoreHeight`](#can-i-ignore-the-height-of-the-latest-tag-or-root-commit) | [`-i\|--ignore-height`](#can-i-ignore-the-height-of-the-latest-tag-or-root-commit) |
| [`MinVerMinimumMajorMinor`](#can-i-bump-the-major-or-minor-version) | [`-m\|--minimum-major-minor`](#can-i-bump-the-major-or-minor-version) |
| [`MinVerSkip`](#can-i-disable-minver) | n/a (environment variable _not_ supported) |
| [`MinVerTagPrefix`](#can-i-prefix-my-tag-names) | [`-t\|--tag-prefix`](#can-i-prefix-my-tag-names) |
| [`MinVerVerbosity`](#can-i-get-log-output-to-see-how-minver-calculates-the-version) | [`-v\|--verbosity`](#can-i-get-log-output-to-see-how-minver-calculates-the-version) |
| [`MinVerVersionOverride`](#can-i-use-minver-to-version-software-which-is-not-built-using-a-net-sdk-style-project) | n/a (environment variable supported) |
Note that the names of the MSBuild properties and environment variables are case-insensitive.
## FAQ
(With TL;DR answers inline.)
- [Why not use GitVersion, Nerdbank.GitVersioning, or some other tool?](#why-not-use-gitversion-nerdbankgitversioning-or-some-other-tool) _(simplicity)_
- [Can I bump the major or minor version?](#can-i-bump-the-major-or-minor-version) _(yes)_
- [Can I use my own pre-release versioning scheme?](#can-i-use-my-own-pre-release-versioning-scheme) _(yes)_
- [Can I prefix my tag names?](#can-i-prefix-my-tag-names) _(yes)_
- [Can I use my own branching strategy?](#can-i-use-my-own-branching-strategy) _(yes)_
- [Can I include build metadata in the version?](#can-i-include-build-metadata-in-the-version) _(yes)_
- [Can I auto-increment the minor or major version after an RTM tag instead of the patch version?](#can-i-auto-increment-the-minor-or-major-version-after-an-rtm-tag-instead-of-the-patch-version) _(yes)_
- [Can I change the default pre-release identifiers from `alpha.0` to something else?](#can-i-change-the-default-pre-release-identifiers-from-alpha0-to-something-else) _(yes)_
- [Can I use the version calculated by MinVer for other purposes?](#can-i-use-the-version-calculated-by-minver-for-other-purposes) _(yes)_
- [Can I version multiple projects in a single repository independently?](#can-i-version-multiple-projects-in-a-single-repository-independently) _(yes)_
- [Can I ignore the height of the latest tag or root commit?](#can-i-ignore-the-height-of-the-latest-tag-or-root-commit) _(yes)_
- [Can I get log output to see how MinVer calculates the version?](#can-i-get-log-output-to-see-how-minver-calculates-the-version) _(yes)_
- [Can I use MinVer to version software which is not built using a .NET SDK style project?](#can-i-use-minver-to-version-software-which-is-not-built-using-a-net-sdk-style-project) _(yes)_
- [Can I disable MinVer?](#can-i-disable-minver) _(yes)_
- [What if the history diverges, and more than one tag or root commit is found?](#what-if-the-history-diverges-and-more-than-one-tag-or-root-commit-is-found) _(nothing bad)_
- [What if the history diverges, and then converges again, before the latest tag (or root commit) is found?](#what-if-the-history-diverges-and-then-converges-again-before-the-latest-tag-or-root-commit-is-found) _(nothing bad)_
- [Why is the default version sometimes used in GitHub Actions, Azure Pipelines, and Travis CI when a version tag exists in the history?](#why-is-the-default-version-sometimes-used-in-github-actions-azure-pipelines-and-travis-ci-when-a-version-tag-exists-in-the-history) _(shallow clones)_
- [Why is my version tag ignored?](#why-is-my-version-tag-ignored) _(MinVer is not running, the tag is misplaced, the version is superseded, the prefix is wrong, or the version is not valid SemVer 2.0)_
### Why not use GitVersion, Nerdbank.GitVersioning, or some other tool?
Before starting MinVer, [Adam Ralph](https://github.com/adamralph) evaluated both [GitVersion](https://github.com/GitTools/GitVersion) and [Nerdbank.GitVersioning](https://github.com/AArnott/Nerdbank.GitVersioning), but neither of them worked in the way he wanted for his projects.
The TL;DR is that MinVer is simpler. ["How it works"](#how-it-works) pretty much captures everything.
#### Comparison with GitVersion
To some degree, MinVer is a subset of what GitVersion is. It's much simpler and doesn't do nearly as much. Some of the differences:
- No dependency on a specific branching pattern.
- No inference of version from branch names.
- No inference of version from YAML config.
- No inference of version from commit messages.
- No inference of version from CI build server environment variables.
- No creation of metadata code artifacts.
- No automatic fetching of tags, etc. from the repository.
- One package instead of a series of packages.
- No support for `AssemblyInfo.cs`.
#### Comparison with Nerdbank.GitVersioning
MinVer is a different approach and, again, simpler. Some of the differences are already listed under the comparison with GitVersion above.
Essentially, Nerdbank.GitVersioning encapsulates the injection of the version into the build process from a config file. That means versions are controlled by commits to that config file. MinVer works purely on tags. That means MinVer doesn't need some of the types of things that come with Nerdbank.GitVersioning such as the config file bootstrapper, and it means the version is controlled independently of the commits. For example, you can tag a commit as a release candidate, build it, and release it. After some time, if the release candidate has no bugs, you can tag the _same commit_ as RTM, build it, and release it.
Also, Nerdbank.GitVersioning uses the Git height for the patch version, which is undesirable. Either _every_ patch commit has to be released, or there will be gaps in the patch versions released.
### Can I bump the major or minor version?
Yes! You probably want to do this because at a point in time, on a given branch, you are working on a specific `MAJOR.MINOR` range, e.g. `1.0`, `1.1`, or `2.0`. The branch could be `main`, `develop`, a special release branch, a support branch, or anything else.
Before you create the first version tag on your branch, interim builds will use the latest version tag found in the commit history, which may not match the `MAJOR.MINOR` range you are working on. Or if no version tag is found in the commit history, interim builds will have the default version `0.0.0-alpha.0`. If you prefer those interim builds to have a version in the range you are working on, you have two options:
#### Tag a commit
Tag a commit in your branch with a version matching your `MAJOR.MINOR` range, using your [preferred default pre-release identifiers](#can-i-change-the-default-pre-release-identifiers-from-alpha0-to-something-else). For example:
```shell
git tag 1.0.0-alpha.0
```
This is not a version you will release, since the first "alpha" version will be `1.0.0-alpha.1`. The only purpose of this tag is to force MinVer to start versioning commits in your branch in the `1.0` range.
If you begin to release versions in the `1.0` range from another branch (e.g. a special release branch), tag a commit in your branch with `1.1.0-alpha.0`, `2.0.0-alpha.0`, or whatever `MAJOR.MINOR` range your branch now represents.
#### Set MinVerMinimumMajorMinor
Specify your range with [`MinVerMinimumMajorMinor`](#options). For example:
```xml