Skip to main content

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.

CI PyPI version Python Conventional Commits

How It Works

  1. Follow the Conventional Commits Specification in your repository.
  2. When you're ready to release, run commit-and-tag-version.

The tool will then:

  1. Retrieve the current version from packageFiles, falling back to the last git tag.
  2. Bump the version in bumpFiles based on your commits.
  3. Generate a changelog based on your commits.
  4. Create a new commit including your bumpFiles and updated CHANGELOG.
  5. 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):

  1. CLI arguments
  2. .versionrc / .versionrc.json (JSON)
  3. pyproject.toml under [tool.commit-and-tag-version]
  4. 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

commit_and_tag_version-1.0.0.tar.gz (26.7 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

commit_and_tag_version-1.0.0-py3-none-any.whl (24.7 kB view details)

Uploaded Python 3

File details

Details for the file commit_and_tag_version-1.0.0.tar.gz.

File metadata

  • Download URL: commit_and_tag_version-1.0.0.tar.gz
  • Upload date:
  • Size: 26.7 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.12

File hashes

Hashes for commit_and_tag_version-1.0.0.tar.gz
Algorithm Hash digest
SHA256 5a6155b7c15b608c2f3802baa6014aefb42bbb10f107264e42a27de680b6071f
MD5 f45d8b07a21b92ee988bb183d30d46a1
BLAKE2b-256 5ae5052fe6720b34b1b6534f93c170a6498377d29023b78b1d2ceff40f4adf9b

See more details on using hashes here.

File details

Details for the file commit_and_tag_version-1.0.0-py3-none-any.whl.

File metadata

File hashes

Hashes for commit_and_tag_version-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 c6c6eb40399a6770e3df9cc0ff69d41ded532e77e00428023bde8199fea3cfbc
MD5 905e2084c90037501c21108d669c2653
BLAKE2b-256 ca64492aacafc8beafa00a32ec78c88133d66571968e1e3875ffd74666b08553

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page