A utility for versioning using semver and CHANGELOG generation powered by Conventional Commits
Project description
commit-and-tag-version (Python)
A Python port of commit-and-tag-version — a utility for versioning using semver and CHANGELOG generation powered by Conventional Commits.
How It Works
- Follow the Conventional Commits Specification in your repository.
- When you're ready to release, run
commit-and-tag-version.
The tool will then:
- Retrieve the current version from
packageFiles, falling back to the last git tag. - Bump the version in
bumpFilesbased on your commits. - Generate a changelog based on your commits.
- Create a new commit including your
bumpFilesand updated CHANGELOG. - Create a new tag with the new version number.
Version Bumps
| Commit Type | Version Bump |
|---|---|
fix: |
Patch (1.0.0 -> 1.0.1) |
feat: |
Minor (1.0.0 -> 1.1.0) |
feat!: or BREAKING CHANGE |
Major (1.0.0 -> 2.0.0) |
Breaking changes before v1.0.0 bump minor instead of major.
Installing
pip install commit-and-tag-version
Or with a package manager:
# pipx (recommended for CLI tools)
pipx install commit-and-tag-version
# poetry
poetry add --group dev commit-and-tag-version
# uv
uv pip install commit-and-tag-version
CLI Usage
First Release
commit-and-tag-version --first-release
This will tag a release without bumping the version.
Cutting Releases
commit-and-tag-version
As long as your git commit messages are conventional and accurate, the version bump is automatic and you get CHANGELOG generation for free.
After you cut a release, push the new git tag:
git push --follow-tags origin main
Release as a Pre-Release
# unnamed prerelease: 1.0.1-0
commit-and-tag-version --prerelease
# named prerelease: 1.0.1-alpha.0
commit-and-tag-version --prerelease alpha
Prerelease tag collisions are automatically avoided by incrementing the numeric suffix.
Release as a Target Type
# force a minor release
commit-and-tag-version --release-as minor
# force a specific version
commit-and-tag-version --release-as 1.1.0
You can combine --release-as and --prerelease to generate a pre-release for a specific version type.
Dry Run Mode
commit-and-tag-version --dry-run
See what commands would be run, without committing to git or updating files.
Skipping Lifecycle Steps
commit-and-tag-version --skip-changelog
commit-and-tag-version --skip-bump --skip-tag
Or via config:
{
"skip": {
"changelog": true
}
}
Tag Prefix
Tags are prefixed with v by default. Customize with --tag-prefix:
commit-and-tag-version --tag-prefix "release/"
Signing Commits and Tags
commit-and-tag-version --sign
Prevent Git Hooks
commit-and-tag-version --no-verify
Committing Generated Artifacts
Use --commit-all to include all staged changes in the release commit:
commit-and-tag-version --commit-all
Tag Replacement
Use --tag-force to replace an existing tag (e.g., after amending a release):
commit-and-tag-version --skip-bump --tag-force
File Type Support
commit-and-tag-version has built-in updaters for reading and writing versions in:
| File | Updater |
|---|---|
package.json, bower.json, manifest.json |
JSON |
pom.xml |
Maven |
build.gradle, build.gradle.kts |
Gradle |
*.csproj |
.NET |
*.yaml, *.yml |
YAML |
openapi.yaml, openapi.yml |
OpenAPI |
pyproject.toml |
Python (Poetry) |
VERSION.txt, version.txt |
Plain text |
Point to your project's version file(s) via config:
{
"packageFiles": ["pyproject.toml"],
"bumpFiles": ["pyproject.toml"]
}
Configuration
Configure via any of these (highest to lowest precedence):
- CLI arguments
.versionrc/.versionrc.json(JSON)pyproject.tomlunder[tool.commit-and-tag-version]- Built-in defaults
Example .versionrc.json
{
"tagPrefix": "v",
"packageFiles": ["pyproject.toml"],
"bumpFiles": ["pyproject.toml"],
"types": [
{"type": "feat", "section": "Features"},
{"type": "fix", "section": "Bug Fixes"},
{"type": "refactor", "section": "Refactoring", "hidden": false}
],
"releaseCommitMessageFormat": "chore(release): {{currentTag}}"
}
Example pyproject.toml
[tool.commit-and-tag-version]
tag-prefix = "v"
package-files = ["pyproject.toml"]
bump-files = ["pyproject.toml"]
Lifecycle Scripts
Execute custom commands at each stage of the release process:
{
"scripts": {
"prerelease": "python -m pytest",
"prebump": "echo 9.9.9",
"postbump": "echo bumped!",
"prechangelog": "",
"postchangelog": "",
"precommit": "",
"postcommit": "",
"pretag": "",
"posttag": ""
}
}
prebump: If the script outputs a valid semver version, it overrides the calculated version.precommit: If the script outputs a string, it overrides the release commit message format.
Customizing CHANGELOG Generation
Customize which commit types appear in the changelog and under what heading:
{
"types": [
{"type": "feat", "section": "Features"},
{"type": "fix", "section": "Bug Fixes"},
{"type": "chore", "hidden": true},
{"type": "docs", "hidden": true},
{"type": "style", "hidden": true},
{"type": "refactor", "section": "Refactoring", "hidden": false},
{"type": "perf", "section": "Performance", "hidden": false},
{"type": "test", "hidden": true}
]
}
Code Usage
from commit_and_tag_version import commit_and_tag_version
from commit_and_tag_version.defaults import get_default_config
config = get_default_config()
config.package_files = ["pyproject.toml"]
config.bump_files = ["pyproject.toml"]
config.dry_run = True
commit_and_tag_version(config)
CLI Reference
Usage: commit-and-tag-version [OPTIONS]
Options:
-r, --release-as TEXT Specify release type or exact version
-p, --prerelease TEXT Make a prerelease with optional tag id
-f, --first-release Is this the first release?
-s, --sign GPG sign commits and tags
--signoff Add Signed-off-by trailer
-n, --no-verify Bypass git hooks
-a, --commit-all Commit all staged changes
--dry-run Simulate without making changes
--silent Suppress output
-t, --tag-prefix TEXT Tag prefix (default: v)
--tag-force Replace existing tag
-c, --config PATH Custom config file path
-i, --infile TEXT Changelog file path
--release-count INTEGER Number of releases in changelog
--header TEXT Custom changelog header
--release-commit-message-format TEXT
Commit message format
--commit-url-format TEXT Commit URL format template
--compare-url-format TEXT Compare URL format template
--issue-url-format TEXT Issue URL format template
--git-tag-fallback / --no-git-tag-fallback
Fallback to git tags for version
--path TEXT Only populate commits under this path
--skip-bump Skip version bump
--skip-changelog Skip changelog generation
--skip-commit Skip git commit
--skip-tag Skip git tag
--version Show the version and exit.
--help Show this message and exit.
FAQ
How is this different from python-semantic-release?
commit-and-tag-version is branch-agnostic and local-only:
- No per-branch version strategies or branch-specific config
- No automatic pushing or publishing
- Deterministic bumps based solely on commit messages
- Prerelease is explicit via
--prerelease, not inferred from branch names - You control when and where to push
This makes it predictable across any git workflow — feat: always means minor, regardless of which branch you're on.
Can I use this with non-Python projects?
Yes. Despite being written in Python, commit-and-tag-version supports version files for many ecosystems (Maven, Gradle, .NET, YAML, JSON, etc.). Install it as a global CLI tool and point it at your project's version file(s).
License
MIT
Project details
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file commit_and_tag_version-0.0.3.tar.gz.
File metadata
- Download URL: commit_and_tag_version-0.0.3.tar.gz
- Upload date:
- Size: 26.7 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
676df443f8b6ccedd0092e0da2720353fa2ee0d81840ba2f63027c75c5df8ccb
|
|
| MD5 |
5c9b25e1111c3331da6c83bbc4a44e17
|
|
| BLAKE2b-256 |
e98af906462a21ef84ba5ca3cf9a9aaf66b111a7c113debea956be39159e6509
|
File details
Details for the file commit_and_tag_version-0.0.3-py3-none-any.whl.
File metadata
- Download URL: commit_and_tag_version-0.0.3-py3-none-any.whl
- Upload date:
- Size: 24.7 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.13.7
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
301169d53eabb00f17c0f8e631b691bfa9df790806eb8a50879a30d9c89346fe
|
|
| MD5 |
97c34c2301d10b51c908b141f6577357
|
|
| BLAKE2b-256 |
94d4e8ec4abb5bb5601a26f94cf6869afa8351bbe0dfd0697784adc9d02aafb0
|