NewYour coding agent can read the release notes before it upgrades.Set up the MCP server →
PyPI · #315 most downloaded on PyPI
the blessed package to manage your versions by vcs metadata
Last release 12 days ago
23 Sep 2026
Ships unpredictably
gaps range from 8 days to 3.1 years
Nearly every release is documented
notes for 19 of 20 stable releases
Nothing withdrawn
no release was ever pulled
4 years old
20 releases · first in 2023
One column per quarter.
Add discover_file_workdir() , which finds the checkout a project sits in for the purpose of listing files. discover_workdir() answers which checkout d
discover_file_workdir(), which finds the checkout a project sits in fordiscover_workdir() answers which checkoutroot and search_parent_directories; whichtool keyword in _version_missing() again. setuptools-scm 10.1.0vcs-versioning<3; since 2.4.1 removed it,TypeError: _version_missing() got an unexpected keyword argument 'tool'LookupError that says how to set a version. The keyword isThe error raised when a .jj/ directory is found but jj is not installed now names the environment variables that actually disable jj discovery ( SETUP
The error raised when a .jj/ directory is found but jj is not installed now names the environment variables that actually disable jj discovery (SETUPTOOLS_SCM_DISABLE_JJ=1 / VCS_VERSIONING_DISABLE_JJ=1) instead of an unprefixed DISABLE_JJ=1, which was never read. (#1537)
The "unable to detect version" error now names the environment variables the
running integration actually reads. It previously suggested
SETUPTOOLS_SCM_PRETEND_VERSION_FOR_${NORMALIZED_DIST_NAME} unconditionally,
which is not read by vcs-versioning on its own (or by any other integrator),
and it named setuptools-scm as the failing tool regardless of which one ran.
When the distribution name is known the suggested variable is spelled out in
full. When it is not, the generic variables are suggested instead, with a note
that the per-distribution ..._FOR_<DIST> form needs a dist name to match --
the previous message offered a ${NORMALIZED_DIST_NAME} template that could
never be filled in. (#1539)
Warn when file discovery is suppressed while a VCS marker sits in the
project directory. scm_search_known_failed() means an integrator already
looked and found no checkout, so a .git, .hg or .jj right there
contradicts it and the artifact is about to lose every tracked file. That
combination was the signature of the pretend-version regression and stayed
invisible for three releases. Parent directories are not searched, since an
unpacked sdist inside an unrelated checkout is the case the suppression
exists for, and roots listed in IGNORE_VCS_ROOTS are skipped. (#1540)
Environment variable names are now built in one place (env_var_name /
EnvReader.candidate_names), shared by the lookup in EnvReader.read and by
every error message that suggests a variable, so a message cannot name a
variable the lookup would not honour.
The "repository found in a parent directory" error no longer offers a
get_version(relative_to=...) call to integrators that do not ship one; the
remaining options are renumbered instead. (#1539)
Add scm.git.distance_scope and scm.git.distance_count , restricting the distance count to the commits that touch a monorepo project (and optionally fu
scm.git.distance_scope and scm.git.distance_count, restricting the distance count to the commits that touch a monorepo project (and optionally further shared directories) instead of every commit in the repository. Counting uses --full-history by default, or --first-parent; git's default history simplification is not offered because it can make the distance shrink across a merge. Git only. (#1056)Select file finders by the VCS marker their entry point is named for (.git, .hg, .jj) instead of running every backend's command in turn. A tree with no VCS marker -- an unpacked sdist, say -- now spawns no subprocess at all, so a slow hg on PATH can no longer fail an unrelated build.
The finders also survive a subprocess timeout: subprocess.TimeoutExpired was uncaught and aborted the build, and is now treated like any other failed probe. (#1212)
Prefer the fallback metadata nearest the project directory. A .git_archival.txt or PKG-INFO at the VCS root no longer shadows a monorepo project's own, which silently produced the root project's version. (#1522)
Ensure the vcs-versioning testsuite passes without setuptools-scm installed; the egg-info vs PKG-INFO discovery priority test moved to the setuptools-
Register the pkginfo workdir discovery factory in vcs-versioning itself. PKG-INFO is standard sdist metadata, not a setuptools artifact, but its facto
Register the pkginfo workdir discovery factory in vcs-versioning itself. PKG-INFO is standard sdist metadata, not a setuptools artifact, but its factory was only registered by setuptools-scm -- so a standalone vcs-versioning install could not infer a version from an sdist. This broke sdist builds for non-setuptools backends, e.g. meson-python calling python -m vcs_versioning from project().
Fallback workdir candidates are now ordered by how much metadata they carry (egg-info, then archival, then PKG-INFO) instead of by entry point iteration order, so a setuptools built sdist keeps using its scm_version.json now that the two factories ship from different distributions. (#1507)
uv.lock in the sdist. It could not be generated correctly whenever setuptools-scm required an unreleased vcs-versioning, which broke the release proposal workflow. (#1509)Fix a FileNotFoundError crash in the git file finder when a submodule is tracked in the index but its working tree directory does not exist - such git
FileNotFoundError crash in the git file finder when a submodule is tracked in the index but its working tree directory does not exist - such gitlinks are now skipped like not checked out submodules. (#1500)Add a vcs_versioning.dynamic_metadata provider for the dynamic-metadata system.
vcs_versioning.dynamic_metadata provider for the dynamic-metadata system. (#1465)Make the tag.strict and scm.git.describe_command diagnostics actionable and non-conflicting.
The tag.strict future-default notice is now reported by the git backend rather than at configuration time, and only when the future default would actually select a different tag for the repository -- the message names both the current and the future version string. Projects the change cannot affect are silent, and setting an explicit describe_command no longer triggers it at all, so the two warnings can no longer contradict each other.
The describe_command notice is likewise limited to the case where it and an explicit tag.strict really disagree, and no longer claims that tag.prefix has no effect -- prefix stripping applies regardless of how the tag was selected.
Both are logged at warning level instead of raised as warnings, so SETUPTOOLS_SCM_DEBUG=ERROR silences them. (#1429)
Honour export-ignore on directories and submodules again in the git file finder.
The switch from git archive to git ls-files --recurse-submodules lost two parts of the archive semantics: --recurse-submodules listed every submodule regardless of export-ignore, and the :(exclude,attr:export-ignore) pathspec only matches files, so an export-ignore on a directory no longer excluded the files below it. Projects that kept vendored submodules in an export-ignored directory suddenly shipped them in their sdists.
The finder now lists a repository without recursion, checks export-ignore for directories via git check-attr (which is what git archive effectively does when it skips a tree), and only then descends into the submodules that survived. Submodule contents are still listed - with their own .gitattributes applied - so export-ignore in the parent repository now controls exactly which submodules get packaged. Submodules that are not checked out are skipped instead of failing the listing. (#1469)
Honour tag.strict on Mercurial changesets that carry tags of their own, and report the coming strict default for Mercurial repositories.
tag.strict was only applied when looking for the latest tag, so a checked-out changeset tagged event-2024 still produced version 2024 even with tag.strict = true, while git rejected the same tag. Strict matching now applies to the tags on the changeset too: a changeset carrying only event-style tags is treated as untagged and versioning continues from the last real version tag, matching git describe --match. When several tags sit on one changeset, the version-shaped one is now selected instead of whichever Mercurial happened to list first.
The tag.strict divergence diagnostic added in #1429 now covers Mercurial as well, naming the current and future version whenever the coming default would change them. Both backends share the message, and the git-only helpers moved to _backends/_scm_workdir.py.
Note that the Mercurial backend required a dot in version tags before setuptools-scm 9, so for Mercurial projects the coming strict default restores the historical behavior. (#1495)
Speed up jujutsu version inference in large repositories.
Speed up jujutsu version inference in large repositories.
The jj backend filtered whole-ancestry revsets with empty(), which makes
jj diff every commit in the history and took minutes on large repos. The
scan for the newest real commit is now bounded to the most recent
generations, distances are counted without the filter, and the working copy
is snapshotted only once per run (later queries pass
--ignore-working-copy).
As a side effect distances now match git describe --long: merge commits
count even though jj considers them empty. (#1477)
Improve reproducibility of scm_file_list.json (#1488)
Route the hg-git tag mismatch warning through the module logger instead of the root logger. (#1489)
Fix ValueError when parsing .git_archival.txt of a tagged commit whose tag contains more than one dash (e.g. llvmorg-23.1.0-rc2 ) - the git describe s
ValueError when parsing .git_archival.txt of a tagged commit whose tag contains more than one dash (e.g. llvmorg-23.1.0-rc2) - the git describe suffix is now matched precisely instead of splitting on the last two dashes. (#1481)Add missing pytest-timeout to vcs-versioning test dependencies.
Fix crash in _warn_if_tracked when the version file target is a relative path by resolving it against the project root before comparison. Also warn (i
_warn_if_tracked when the version file target is a relative pathRestore Python 3.8 and 3.9 support, re-enabling use as a build dependency for projects like scikit-build that still support these versions.
Fix MetadataWorkdir crash when using custom tag_regex — stored tags are already parsed version strings and no longer re-parsed through the tag regex.
tag_regex — stored tags are already parsed version strings and no longer re-parsed through the tag regex. (#1439)tag_regex — stored tags are already parsed version strings and no longer re-parsed through the tag regex. (#1439)list_tracked_files to project_root in monorepo setups so that sdists no longer include files from sibling projects when root=".." is configured. (#1440)Fix spurious DeprecationWarning for tag_regex when using default value via get_version().
DeprecationWarning for tag_regex when using default value via get_version(). (#1434)Fix DeprecationWarning leak in pretend API by ensuring all public APIs attach VcsEnvironment to Configuration before accessing env-dependent propertie…
VcsEnvironment.build_config_from_pyproject, build_config_from_data, and pyproject_tool_names methods for canonical env-first configuration creation. (#1424)Update CI to use PyPy 3.11 as cryptography has no PyPy 3.10 build available
Add MANIFEST.in to ensure sdist includes testing_vcs/ when the VCS file finder is unavailable.
Add fail-on-uncommitted-changes as a composable local scheme: raise when the working tree is dirty, otherwise defer to the next local scheme in the li
fail-on-uncommitted-changes as a composable local scheme: raise when the working tree is dirty, otherwise defer to the next local scheme in the list so any version_scheme can be used. (#1205)HEAD is exactly on a tag (git describe --exact-match), shallow Git worktrees no longer trigger warn_on_shallow, fail_on_shallow, or fetch_on_shallow—shallow clones are enough for tagged release builds and avoid unnecessary unshallow fetches. (#1241)vcs-versioning with setuptools instead of hatchling to avoid a bootstrap cycle (hatchling → pluggy → setuptools-scm → vcs-versioning) for downstream packagers. (#1302)Simplify release tag creation to use a single createRelease API call instead of separate createTag/createRef/createRelease calls, avoiding dangling ta
createRelease API call instead of separate createTag/createRef/createRelease calls, avoiding dangling tag objects on partial failures. (#release-pipeline)Nothing published for this version
Your coding agent can read these notes before it upgrades. Set up the MCP server →