| name | hatch-vcs Plugin Guide |
| description | Complete guide to the hatch-vcs plugin for Hatchling, covering VCS-based versioning (Git/Mercurial), version file generation, build hook configuration, and migration patterns from setuptools. |
hatch-vcs Plugin
hatch-vcs is an official Hatchling plugin that determines project version from version control system (VCS) tags, enabling automated version management without manual version file updates.
Overview
hatch-vcs integrates three plugin types:
- Version source - Reads version from VCS tags (Git, Mercurial)
- Build hook - Auto-generates version file during builds
- Metadata hook - Injects VCS metadata into package information
Installation
[build-system]
requires = ["hatchling", "hatch-vcs"]
build-backend = "hatchling.build"
Quick Start
Basic Configuration
[tool.hatch.version]
source = "vcs"
[tool.hatch.build.hooks.vcs]
version-file = "src/mypackage/_version.py"
Build and Check Version
hatch version
hatch build
hatch build --hooks-only
Version Source Plugin
Configuration
[tool.hatch.version]
source = "vcs"
[tool.hatch.version.raw-options]
Options
tag-pattern
Regex pattern to extract version from VCS tags.
[tool.hatch.version]
source = "vcs"
tag-pattern = "release-(?P<version>.*)"
The pattern must contain:
- Exactly one unnamed capture group:
(.*)
- OR a named group:
(?P<version>.*)
Examples:
Tag: v1.2.3
Pattern: v(.*)
Match: 1.2.3
Tag: release-1.2.3
Pattern: release-(.*)
Match: 1.2.3
Tag: project-v1.2.3
Pattern: project-v(?P<version>.*)
Match: 1.2.3
fallback-version
Default version if VCS detection fails (no tags found, not a VCS repository):
[tool.hatch.version]
source = "vcs"
fallback-version = "0.1.0"
Without fallback, missing VCS data raises an error.
raw-options
Dictionary of options passed directly to setuptools-scm (except write_to and write_to_template):
[tool.hatch.version.raw-options]
local-scheme = "no-local-version"
relative-to = "src"
root = "."
Common options:
local-scheme - How to format local version (e.g., node-and-date)
relative-to - Relative path for version detection
root - Repository root for detection
Build Hook Plugin
Configuration
[tool.hatch.build.hooks.vcs]
version-file = "src/mypackage/_version.py"
[tool.hatch.build.targets.wheel.hooks.vcs]
Options
version-file
Path to auto-generated version file (relative to project root).
[tool.hatch.build.hooks.vcs]
version-file = "src/mypackage/_version.py"
The hook generates:
__version__ = version = '1.2.3'
__version_tuple__ = version_tuple = (1, 2, 3)
File is only created during builds, not during editable installs.
Generated Version File Contents
For tag v1.2.3, the generated file contains:
__version__ = version = '1.2.3'
__version_tuple__ = version_tuple = (1, 2, 3)
Parse the version in your package:
from mypackage._version import __version__
print(__version__)
Or use importlib.metadata:
from importlib.metadata import version
print(version('mypackage'))
Metadata Hook Plugin
Configuration
[tool.hatch.metadata.hooks.vcs]
The metadata hook injects VCS data (commit hash) into package metadata via context-formatted URLs, enabling dynamic archive links.
Environment Variable: SETUPTOOLS_SCM_PRETEND_VERSION
hatch-vcs respects the setuptools-scm environment variable for overriding version detection:
export SETUPTOOLS_SCM_PRETEND_VERSION=1.2.3
hatch build
This is useful in CI/CD pipelines where you want to set version explicitly.
VCS Support
Git
Requires Git repository with tags:
git init
git tag v1.0.0
hatch version
git tag v1.1.0
hatch version
Mercurial (hg)
Requires Mercurial repository with tags:
hg init
hg tag v1.0.0
hatch version
Configuration Examples
Standard Setup with Version File
[project]
name = "myproject"
dynamic = ["version"]
[build-system]
requires = ["hatchling", "hatch-vcs"]
build-backend = "hatchling.build"
[tool.hatch.version]
source = "vcs"
[tool.hatch.build.hooks.vcs]
version-file = "src/myproject/_version.py"
Custom Tag Pattern
[tool.hatch.version]
source = "vcs"
tag-pattern = "release-v(?P<version>.*)"
fallback-version = "0.1.0.dev0"
Multiple Build Targets
[tool.hatch.build.hooks.vcs]
version-file = "src/myproject/_version.py"
[tool.hatch.build.targets.wheel.hooks.vcs]
[tool.hatch.build.targets.sdist.hooks.vcs]
With Version Scheme
[tool.hatch.version]
source = "vcs"
scheme = "standard"
[tool.hatch.build.hooks.vcs]
version-file = "src/myproject/__version__.py"
[tool.hatch.version.raw-options]
local-scheme = "no-local-version"
Usage Patterns
Version Display
hatch version
hatch version patch
hatch version minor
hatch version major
Building with VCS Versioning
hatch build
hatch build --hooks-only
hatch build -c
hatch build -t wheel
Editable Install
pip install -e .
hatch build
pip install -e .
CI/CD Integration
- name: Build
env:
SETUPTOOLS_SCM_PRETEND_VERSION: ${{ github.ref_name }}
run: hatch build
build:
variables:
SETUPTOOLS_SCM_PRETEND_VERSION: $CI_COMMIT_TAG
script:
- hatch build
Migration from setuptools
If migrating from setuptools with setuptools-scm:
Before (setuptools)
from setuptools import setup
setup(
version='1.0.0',
use_scm_version=True,
)
After (Hatchling)
[build-system]
requires = ["hatchling", "hatch-vcs"]
build-backend = "hatchling.build"
[project]
dynamic = ["version"]
[tool.hatch.version]
source = "vcs"
[tool.hatch.build.hooks.vcs]
version-file = "src/myproject/_version.py"
Commands
hatch version
hatch version --no-set
hatch build --hooks-only
Troubleshooting
"No tags found" Error
Issue: hatch-vcs cannot find any VCS tags.
Solution: Create initial tag:
git tag v0.1.0
hatch version
Version Shows "0+unknown"
Issue: Not in a VCS repository or setuptools-scm cannot detect version.
Solution:
- Ensure project is in Git/Mercurial repo
- Create tags:
git tag v1.0.0
- Set fallback version:
[tool.hatch.version]
source = "vcs"
fallback-version = "0.1.0"
Editable Install Has No Version
Issue: Version file not generated for editable installs.
Solution: Always run hatch build --hooks-only after editable install:
pip install -e .
hatch build --hooks-only
pip install -e .
Or use importlib.metadata at runtime:
from importlib.metadata import version
__version__ = version('myproject')
Best Practices
- Always Create Tags: Ensure initial tag exists for version detection
- Use Semantic Versioning: Tags like
v1.2.3 for clarity
- Test Version File: Verify generated version file after builds
- Use importlib.metadata: Prefer runtime version detection
- CI/CD Override: Set SETUPTOOLS_SCM_PRETEND_VERSION in CI pipelines
- Document Setup: Include version detection setup in contributing docs
- Use Fallback: Provide fallback version for edge cases
See Also