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-0.0.4.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-0.0.4-py3-none-any.whl (24.7 kB view details)

Uploaded Python 3

File details

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

File metadata

  • Download URL: commit_and_tag_version-0.0.4.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-0.0.4.tar.gz
Algorithm Hash digest
SHA256 ec4432300e01a50ee3e64286064b72cff66c752a20ac89cffc376202718408e9
MD5 2555dac5de5c9ba88fe5c2573a592bd8
BLAKE2b-256 f2107b2ae54f5722b688edeacfa5d89738c776c5d9e8c4c66f363bd50ef0057c

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for commit_and_tag_version-0.0.4-py3-none-any.whl
Algorithm Hash digest
SHA256 1a338e1aa7653fda27c380092d7e2c696da2638a430ba2a8c71afdc43e46ac33
MD5 bfb288ef24678d51aedc3ecdc519e7b6
BLAKE2b-256 2c410f055db5eae1b3f5ce4f6a83a9d5610d00629233e9aba3ebae5ecdca2892

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