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.
Installs into .claude/skills of the current project.
Are you the author of 1600 Hatch Vcs Plugin Bfa7ad60?
Add the live security badge to your README. It updates with every re-scan.
[](https://www.skillsdirectory.com/skills/tools-only-1600-hatch-vcs-plugin-bfa7ad60)
---
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:
1. **Version source** - Reads version from VCS tags (Git, Mercurial)
2. **Build hook** - Auto-generates version file during builds
3. **Metadata hook** - Injects VCS metadata into package information
## Installation
```toml
[build-system]
requires = ["hatchling", "hatch-vcs"]
build-backend = "hatchling.build"
```
## Quick Start
### Basic Configuration
```toml
[tool.hatch.version]
source = "vcs"
[tool.hatch.build.hooks.vcs]
version-file = "src/mypackage/_version.py"
```
### Build and Check Version
```bash
# Show version from VCS tags
hatch version
# Build with auto-generated version
hatch build
# Build only hooks (generate version file without distribution)
hatch build --hooks-only
```
## Version Source Plugin
### Configuration
```toml
[tool.hatch.version]
source = "vcs"
[tool.hatch.version.raw-options]
# Options passed to setuptools-scm
```
### Options
#### tag-pattern
Regex pattern to extract version from VCS tags.
```toml
[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:
```text
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):
```toml
[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`):
```toml
[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
```toml
[tool.hatch.build.hooks.vcs]
version-file = "src/mypackage/_version.py"
[tool.hatch.build.targets.wheel.hooks.vcs]
# Hook configuration specific to wheel target
```
### Options
#### version-file
Path to auto-generated version file (relative to project root).
```toml
[tool.hatch.build.hooks.vcs]
version-file = "src/mypackage/_version.py"
```
The hook generates:
```python
# Auto-generated by hatchling from version control
__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:
```python
# Generated by hatch-vcs
__version__ = version = '1.2.3'
__version_tuple__ = version_tuple = (1, 2, 3)
```
Parse the version in your package:
```python
from mypackage._version import __version__
print(__version__) # Output: 1.2.3
```
Or use importlib.metadata:
```python
from importlib.metadata import version
print(version('mypackage')) # Output: 1.2.3
```
## Metadata Hook Plugin
### Configuration
```toml
[tool.hatch.metadata.hooks.vcs]
# Metadata hook configuration (Git-only)
```
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:
```bash
# Override version for builds
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:
```bash
git init
git tag v1.0.0
hatch version # Output: 1.0.0
# Add new tag
git tag v1.1.0
hatch version # Output: 1.1.0
```
### Mercurial (hg)
Requires Mercurial repository with tags:
```bash
hg init
hg tag v1.0.0
hatch version # Output: 1.0.0
```
## Configuration Examples
### Standard Setup with Version File
```toml
[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
```toml
[tool.hatch.version]
source = "vcs"
tag-pattern = "release-v(?P<version>.*)"
fallback-version = "0.1.0.dev0"
```
### Multiple Build Targets
```toml
[tool.hatch.build.hooks.vcs]
version-file = "src/myproject/_version.py"
[tool.hatch.build.targets.wheel.hooks.vcs]
# Wheel-specific config (if needed)
[tool.hatch.build.targets.sdist.hooks.vcs]
# Sdist-specific config (if needed)
```
### With Version Scheme
```toml
[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
```bash
# Show current version from VCS
hatch version
# Update version (creates new tag)
hatch version patch # Increment patch
hatch version minor # Increment minor
hatch version major # Increment major
```
### Building with VCS Versioning
```bash
# Normal build (includes auto-generated version file)
hatch build
# Build only version file (useful for testing)
hatch build --hooks-only
# Clean and rebuild
hatch build -c
# Build specific target
hatch build -t wheel
```
### Editable Install
```bash
# Editable install (version file NOT generated)
pip install -e .
# Must rebuild to get version file
hatch build
pip install -e .
```
### CI/CD Integration
```bash
# GitHub Actions
- name: Build
env:
SETUPTOOLS_SCM_PRETEND_VERSION: ${{ github.ref_name }}
run: hatch build
# GitLab CI
build:
variables:
SETUPTOOLS_SCM_PRETEND_VERSION: $CI_COMMIT_TAG
script:
- hatch build
```
## Migration from setuptools
If migrating from setuptools with setuptools-scm:
### Before (setuptools)
```python
# setup.py
from setuptools import setup
setup(
version='1.0.0',
use_scm_version=True,
)
```
### After (Hatchling)
```toml
# pyproject.toml
[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
```bash
# Show version (equivalent to old: python setup.py --version)
hatch version
# Display version without modification
hatch version --no-set
# Write version file without building
hatch build --hooks-only
```
## Troubleshooting
### "No tags found" Error
**Issue**: hatch-vcs cannot find any VCS tags.
**Solution**: Create initial tag:
```bash
git tag v0.1.0
hatch version # Should now output: 0.1.0
```
### Version Shows "0+unknown"
**Issue**: Not in a VCS repository or setuptools-scm cannot detect version.
**Solution**:
1. Ensure project is in Git/Mercurial repo
2. Create tags: `git tag v1.0.0`
3. Set fallback version:
```toml
[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:
```bash
pip install -e .
hatch build --hooks-only
pip install -e .
```
Or use `importlib.metadata` at runtime:
```python
from importlib.metadata import version
__version__ = version('myproject')
```
## Best Practices
1. **Always Create Tags**: Ensure initial tag exists for version detection
2. **Use Semantic Versioning**: Tags like `v1.2.3` for clarity
3. **Test Version File**: Verify generated version file after builds
4. **Use importlib.metadata**: Prefer runtime version detection
5. **CI/CD Override**: Set SETUPTOOLS_SCM_PRETEND_VERSION in CI pipelines
6. **Document Setup**: Include version detection setup in contributing docs
7. **Use Fallback**: Provide fallback version for edge cases
## See Also
- [hatch-vcs GitHub Repository](https://github.com/ofek/hatch-vcs)
- [Version Source Plugins](./version-source-plugins.md)
- [Build Hook Plugins](./build-hook-plugins.md)
- [setuptools-scm Documentation](https://github.com/pypa/setuptools_scm)
- [Hatchling Version Documentation](https://hatch.pypa.io/latest/plugins/version-source/)
- [Hatch Version Command](https://hatch.pypa.io/latest/cli/reference/#hatch-version)