# GitVersion: deriving SemVer from your git history

> GitVersion reads a repository's commit graph and branch names and produces a Semantic Version for the commit being built. It is aimed at teams whose release version is currently decided by hand, and it fits best where branching follows a convention you are willing to keep.

**GitTools/GitVersion** — From git log to SemVer in no time

- Repository: https://github.com/GitTools/GitVersion
- Website: https://gitversion.net/docs/
- Stars: 3,148 · Forks: 665
- Language: C#
- License: MIT
- Published: 2026-09-24 · Updated: 2026-09-24 · Language: en
- Canonical page: https://hysenlabs.com/projects/gittools-gitversion

## The problem GitVersion addresses

Most projects that ship from git end up with a version number that lives in two places: a file someone edits before tagging, and a tag that someone creates afterwards. The two drift. A build from a feature branch reports the same version as the last release, so two artifacts with different contents carry the same identifier. GitVersion's premise is that the commit graph already contains the information needed to distinguish them, and that the version can therefore be computed rather than declared. The README states the goal plainly: "GitVersion looks at your git history and works out the Semantic Version of the commit being built." The audience is build and release engineers, mostly on .NET projects, who need every build to carry a unique and ordered version so that package feeds, deployment records and bug reports can be reconciled. It is not a versioning library for application code, and it does not replace git tags; it reads them.

## How GitVersion derives a version from commits and branches

The mechanism is a two-stage calculation. First, GitVersion walks the history from the current commit and finds the nearest version source: an annotated tag that parses as a version, or, where configuration allows, a branch name such as release-1.0.0. That gives a base version. Second, it counts the commits between that base and the current commit and uses the branch's role to decide how the count is expressed. On main, the count typically increments the patch component. On a release branch, it produces a pre-release label. On a pull request branch, the README's own example shows the result as a pre-release build, and it notes a branch called release-1.0.0 producing beta v1 packages. The output is not one number but a set of variables (the SemVer string, the major, minor and patch components, and pre-release metadata), which the build tooling consumes. Configuration lives in a .gitversion.yml file at the repository root, and the repository does contain one, so the defaults used by the project itself are visible in the tree. The docs site at gitversion.net/docs/ is where the schema and the mode descriptions live; the README only points at it, which is a fair reflection of how much behaviour is configurable.

## Installing GitVersion and running it on a repository

GitVersion ships as several artifacts rather than one. The README lists a GitHub release, GitVersion.Portable on Chocolatey, GitVersion.Tool on NuGet, GitVersion.MsBuild on NuGet, Homebrew, Winget, a Docker image at gittools/gitversion, an Azure Pipeline task and a GitHub Action. The README does not reproduce install commands or a CLI flag list; it points at the documentation at gitversion.net/docs/ and at per-artifact pages such as the usage page linked for GitVersion.MsBuild. The one thing the repository does show at the root is the configuration file the project uses for itself, .gitversion.yml, which is the file you would add to your own repository. For build integration, GitVersion.MsBuild is the package that supplies the computed version to an MSBuild build, and the Azure Pipeline task and GitHub Action wrap the same binary for CI. What you should expect from any of these paths is a set of named version variables for the current commit, not a single number written into a file. If the output looks wrong, the first thing to check is whether the repository has an annotated tag GitVersion can use as a base, because without one the calculation falls back to configuration defaults and the result will not match your expectations.

## Where GitVersion gets it wrong, and when to pick something else

The design assumes a branching convention. Mainline mode exists precisely because the default mode, which tracks release branches and merge commits, produces pre-release numbers that some teams find surprising when they merge frequently. That is a real fork in the road: the same repository can yield different versions depending on which mode is configured, and the README does not explain the trade-off, it links to the docs. The second limitation is that the version is a function of history. Rewriting history, squashing a merge, or rebasing a release branch changes the commit count and therefore the version. A project that rebases shared branches will find GitVersion's output unstable in a way that a manually bumped version file is not. Third, the tool is .NET-centric in its packaging. The core binary runs on Windows, Linux and Mac, but the integration points that make it pleasant (GitVersion.MsBuild, the Azure Pipeline task) are aimed at .NET and Azure Pipelines. A Go or Rust project can call the CLI in a script, but it gets none of the property plumbing. If your release process is a person editing a version file and tagging, and nobody has complained, GitVersion adds a configuration file and a mode decision in exchange for removing that edit. That is a reasonable trade for a team shipping many pre-release builds, and a poor one for a project with two releases a year.

## GitVersion compared with a plain version file plus tags

The obvious alternative is not another tool but the absence of one: keep a version in a file, tag releases, and let the build read the tag. The difference in approach is where the truth lives. With a version file, the version is an input that a human controls and that can be set to anything, including something that does not correspond to any commit. With GitVersion, the version is derived, and the only human inputs are the tag and the branch name. The derived approach removes the possibility of a build whose version does not match its history, and it removes the ability to ship a version that the history does not support. A second alternative is to compute the version in the CI script with a few git commands. That works for the simple case of counting commits since the last tag, but it does not handle pre-release labels, branch roles, or the distinction between a merge into main and a commit on main. GitVersion's value is that this logic is written down once, in a schema, instead of being reimplemented per pipeline. The cost is the same: you now depend on that schema's behaviour being what you expect, and you have to read the mode documentation to know which it is.

## Maintenance, licensing and the cost of upgrading

The repository is not archived, and the last push was on 2026-09-22, two days before this writing, so the project is being worked on. Recent releases are 6.8.0 on 2026-06-30, 6.8.1 on 2026-07-03 and 6.8.2 on 2026-07-10, which is a steady patch cadence on the 6.8 line. The licence is MIT, which permits commercial use, modification and redistribution provided the copyright notice and permission notice are retained; that is a permissive licence and imposes no copyleft obligation on your build scripts or your application. It says nothing about the versions GitVersion computes, and nothing about the Docker image's base layers, which carry their own licences. The upgrade cost is the part worth planning. The repository carries a BREAKING_CHANGES.md file at the root, which is the document to read before moving between major versions, and the presence of a new-cli/ directory alongside src/ suggests CLI work that may land in a later release. A versioning tool sits underneath every build, so an upgrade that changes the computed version will change your package versions, and a changed package version is a changed deployment artifact. Pin the tool version in CI and treat an upgrade as a change to the release process, not as a dependency bump.

## Conclusion

Adopt GitVersion if your team already branches in a recognisable pattern (main, release branches, pull requests) and you want the version number computed at build time rather than typed into a file. Do not adopt it if your branching is ad hoc, if you need a version that survives a rebase untouched, or if the release process is owned by people who will not read the configuration schema. Before rolling it out, run it once against a clone of the real repository and check the computed version on a merge commit, on a release branch, and on a pull request, because those three cases are where the default configuration and your habits are most likely to disagree.

## FAQ

### What is GitVersion?

GitVersion is a tool that looks at a git repository's history and works out the Semantic Version of the commit being built, as the README puts it. It reads tags and branch names rather than requiring a version to be written into a file.

### How do I install GitVersion?

The README lists several distribution channels: a GitHub release, GitVersion.Portable on Chocolatey, GitVersion.Tool and GitVersion.MsBuild on NuGet, Homebrew, Winget, and a Docker image at gittools/gitversion. It does not print install commands, so the documentation site is the place to look for them.

### How do I use GitVersion in Azure DevOps?

The README lists an Azure Pipeline Task among the supported artifacts, published on the Visual Studio Marketplace under the gittools publisher. The task wraps the same binary; the README links to the documentation rather than showing task inputs inline.

### How do I use GitVersion with MSBuild?

GitVersion.MsBuild is the NuGet package for that integration, and the README links a usage page for it. The package supplies the computed version to MSBuild, so the property names and wiring are documented there rather than in the README.

### What is gitversion.yml?

It is the configuration file GitVersion reads from the repository root; the GitVersion repository itself contains a .gitversion.yml. Settings such as the versioning mode and version sources are defined there, and the schema is documented on the project's documentation site.

## Sources

- [GitTools/GitVersion on GitHub](https://github.com/GitTools/GitVersion)
- [License: MIT](https://github.com/GitTools/GitVersion/blob/main/LICENSE)
- [Project website](https://gitversion.net/docs/)
- [README](https://github.com/GitTools/GitVersion/blob/main/README.md)
- [Releases](https://github.com/GitTools/GitVersion/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/gittools-gitversion
