CLI tool
dotnet/Nerdbank.GitVersioning avatar
dotnet/Nerdbank.GitVersioning

Nerdbank.GitVersioning ignores tags and branch names on purpose, which is what makes builds reproducible

Stamp your assemblies, packages and more with a unique version generated from a single, simple version.json file and include git commit IDs for non-official builds.

1,597 stars184 forksC#MIT

At a glance

What is it?
Nerdbank.GitVersioning computes a semantic version for every git commit from an author-defined base in version.json plus a git height, so two clones of the same commit produce the same version regardless of tags or branch. A separate Rust implementation provides an nbgv command line tool built on libgit2.
Who is it for?
Nerdbank.GitVersioning fits a.NET repository that needs a unique, reproducible version on every commit without anyone maintaining a version property by hand, and it does not fit a team that wants release numbers to follow marketing decisions at tag time, since the base version only moves when you edit version.json.
Can I use it commercially?
Yes. MIT is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository received new commits within the last day.
What is it written in?
Mainly C#, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 23, 2026, and from our analysis. They are not legal advice.

Editorial analysis

Three claims about tags, branches and height

The README sets out what distinguishes this project from other git based versioning tools, and the list is worth reading as a design manifesto rather than as a feature list.

The first claim is absolute build reproducibility: every single commit can be built and produce a unique version. The second is no dependency on tags, with two reasons given. Tags can be added to existing commits at any time, and clones may not fetch tags, so a tag based scheme produces different versions from two clones of the same commit. The third claim extends that to branch names: branches come and go, a commit may belong to any number of them, and the build should be identical regardless of which branch HEAD is attached to.

That is the core idea. The version is a function of commit history alone, so a build server, a developer's laptop and a release engineer all compute the same number without coordinating.

The last two entries in the list describe the version's shape: an author-defined major.minor version plus an optional unstable tag, plus a shortened git commit ID. And the project is supported by the .NET Foundation, which is a governance statement rather than a technical one but does affect how an enterprise team might adopt it.

version.json is the only file a human edits

The repository contains a version.json at the root, and that is the entire human-authored input. The README describes what it gives you control over: the base version number, the placement for the git height incrementing integer, and the prerelease label identifiers.

That third item is the subtle one. A conventional scheme puts the build number at the end, so 1.4.9 becomes 1.4.10. Nerdbank.GitVersioning lets you say where the git height goes, which is how you can make it a patch number, a fourth component, or something else entirely, and get a different increment order for nightly builds versus official ones.

The surrounding repository files show what the tool generates and consumes. Directory.Build.props, Directory.Build.targets and Directory.Build.rsp are the MSBuild files that carry the computed version into every project, and Directory.Packages.props is where central package version management meets it. strongname.snk at the root is a strong naming key file, which relates to the ThisAssembly class the README mentions: the generated class provides runtime access to version information and to strong name keys, so an assembly can report its own version without a lookup table.

docfx/ holds documentation tooling, global.json pins the SDK, and rust-toolchain.toml sits beside it for the Rust half of the project.

The MSBuild and npm surface, and the CLI that backtracks

The package stamps every assembly, VSIX, NuGet and NPM package, and it does so through build system integration rather than a wrapper script. The README's explanation of why that works broadly is that the tool simply uses git itself and integrates naturally in MSBuild, gulp and other build scripts, which is also why it implicitly supports every cloud build service and CI server.

Two integrations are named specifically. MSBuild integration includes the ThisAssembly class generation described earlier. The npm side is a separate published package, nerdbank-gitversioning, which carries the badge in the README alongside the NuGet one.

The CLI is the feature that distinguishes this from a purely declarative scheme. The README describes an optional command line tool that calculates versions and backtracks from a computed version to its source git commit. That is the reverse lookup: given a version string from a crash report or a bug, find the commit that produced it. Without it, finding the commit from a version string may require parsing the shortened ID.

The README also claims the tool updates cloud build names with the version number so a build can be correlated with a release, which helps identify the relevant build.

A Rust CLI with a deliberate list of things it does not do

The project now ships a second implementation in Rust, which is unusual for a versioning tool and is the most interesting engineering decision in the repository.

The Rust workspace provides the nerdbank-gitversioning library and a native nbgv command line tool, tested with current stable Rust on Windows, Linux and macOS. Installing it is a cargo install from the workspace path:

bash
cargo install --path src/nerdbank-gitversioning-rs/nbgv
nbgv get-version

The commands are get-version, set-version, tag, get-commits, cloud and prepare-release. Normal git operations run in process through libgit2, so no git executable is required on the machine, with one documented exception: when commit.gpgSign is enabled, prepare-release falls back to the git executable on PATH in order to create signed commits and merge commits.

The exclusion list is as informative as the feature list. The Rust CLI deliberately excludes the .NET CLI's install and path-filters commands, and provides no MSBuild props, targets or tasks, no generated assembly metadata and no package installation. The README's instruction is to use the .NET packages and CLI for those features. So the two implementations are complementary rather than interchangeable, and picking the wrong one gives you a tool that cannot stamp an assembly.

A prerelease channel in active use

The release history is worth reading before choosing a dependency version, because the beta suffix is not decorative.

The three most recent releases are v3.10.94 on 2026-08-28, then v3.11.128-beta the same day, and v3.11.202-beta on 2026-10-05. Two of the three are prerelease builds on the 3.11 track, while the stable release is on 3.10. The last push to the repository was on 2026-10-15, ten days after the newest tag.

That pattern suggests the project ships betas on the 3.11 track alongside stable 3.10, which is a reasonable approach for a build-time dependency: adopting the beta gets you the current track, and the documentation points at a recommended versioning workflow for releases and servicing, which is where the distinction is meant to be resolved.

Licensing is MIT with a LICENSE file at the root, and the repository also carries a NOTICE.md and 3rdPartyNotices.txt, which is the standard form for a project that vendors dependencies. SECURITY.md, CONTRIBUTING.md, CODE-OF-CONDUCT.md and an AGENTS.md sit alongside them, and the project has adopted the Contributor Covenant code of conduct.

Editorial conclusion

Nerdbank.GitVersioning fits a.NET repository that needs a unique, reproducible version on every commit without anyone maintaining a version property by hand, and it does not fit a team that wants release numbers to follow marketing decisions at tag time, since the base version only moves when you edit version.json. Before adopting it, read the recommended versioning workflow in the documentation, because its recent history includes prerelease builds and the beta versus stable choice matters for a build pipeline.

Frequently asked questions

How does Nerdbank.GitVersioning compute a version?

From an author-defined base version in version.json plus the git height and a shortened git commit ID. You control the base, where the height increment is placed, and the prerelease label identifiers.

Why does Nerdbank.GitVersioning not use git tags?

The README gives two reasons: tags can be added to existing commits at any time, and clones may not fetch tags. Avoiding tag and branch dependence is what makes the version reproducible from any clone.

What is the nbgv command line tool?

It is the native CLI from the project's Rust workspace, installable with cargo install from src/nerdbank-gitversioning-rs/nbgv. It offers get-version, set-version, tag, get-commits, cloud and prepare-release, and runs git operations in process through libgit2.

Can I use the Rust CLI instead of the .NET packages?

Not as a replacement. The README states the Rust CLI excludes the install and path-filters commands and provides no MSBuild props, targets, tasks, generated assembly metadata or package installation, so you need the .NET packages for those.

What license is Nerdbank.GitVersioning released under?

MIT, with the licence file at the repository root, alongside a NOTICE.md and 3rdPartyNotices.txt for vendored dependencies.

Official sources

  1. dotnet/Nerdbank.GitVersioning on GitHub
  2. License: MIT
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/dotnet-nerdbank-gitversioning.svg)](https://hysenlabs.com/projects/dotnet-nerdbank-gitversioning)

Was this useful?