Skip to main content

🌱 Pezin

CI PyPI version Python 3.12+ License: MIT Downloads

A tool that handles versioning with care — it can be used manually or integrated as a pre-commit hook to automate version bumps and changelog generation based on conventional commits.

Features

  • 🔄 Automatic version bumping based on conventional commits
  • 🌍 Universal language support - Python, Node.js, C/C++, Rust, PHP, Go, Java, .NET, and any custom patterns
  • 📁 Multi-file version management - Update multiple version files simultaneously
  • 🎨 Advanced pattern system - Component-level version control with rich template formatting
  • 📝 Automated changelog generation with comparison links
  • 🎣 Git pre-commit hook integration with reliable amend detection
  • ⚡ CLI tool for manual version management
  • 🏷️ Pre-release version support (alpha, beta, rc)
  • 🔧 Flexible version formats - Support any prefix/suffix pattern (v1.2.3, 1.2.3v, release-1.2.3)

Quick Start

Installation

Install from PyPI:

pip install pezin

Or install the latest development version:

pip install git+https://github.com/tatus9/pezin.git

Setup Git Hook

Add to your .pre-commit-config.yaml:

repos:
  - repo: https://github.com/tatus9/pezin
    rev: v0.8.2  # Use the latest version
    hooks:
      - id: pezin-prepare
      - id: pezin-post

Install the hooks:

pip install pre-commit pezin
pre-commit install --hook-type prepare-commit-msg --hook-type post-commit

Both hooks are required: pezin-prepare detects amends/rebases and cooperates with the data-loss guard; pezin-post performs the bump, changelog write and tagging.

Direct git hooks (without the pre-commit framework)
pezin install-hooks        # also: pezin hooks-status / pezin uninstall-hooks

Since v0.9.0 the generated hooks are pinned to the interpreter that ran pezin install-hooks, so they work from pipx/uv/virtualenv installs without the venv on PATH. If the hook ever cannot import pezin it warns and lets the commit through instead of blocking it — re-run pezin install-hooks from the right environment to fix. Upgrading from ≤ 0.8.2? Re-run pezin install-hooks once to refresh the shebangs.

Start Using

Just commit with conventional commit format:

git commit -m "feat: add user authentication"    # 1.0.0 → 1.1.0
git commit -m "fix: resolve login bug"           # 1.1.0 → 1.1.1
git commit -m "feat!: redesign API"              # 1.1.1 → 2.0.0

Your version files will be automatically updated!

Changelog Automation

Since v0.8.0 the post-commit hook also writes CHANGELOG.md on every bump. It adds a new dated [<version>] section listing the triggering commit under the matching category (Features, Bug Fixes, …) and creates the file with a Keep-a-Changelog header if missing. Since v0.9.0 the file follows Keep-a-Changelog ordering: ## [Unreleased] stays directly below the header, entries accumulated under it are promoted into the new version section, and your existing header text is preserved. No config required — it's on by default.

Opt out or customise via [tool.pezin.changelog]:

[tool.pezin.changelog]
enabled = true                  # set false to skip the write
path = "CHANGELOG.md"           # relative to the repo or service root
unreleased_label = "Unreleased"

If CHANGELOG.md does not exist, pezin creates it with a Keep-a-Changelog header before writing the new section. A failure while writing the changelog is logged as a warning and the version bump still lands — the changelog is best-effort, never blocking.

In monorepo mode each service can override the same keys in that service's [[tool.pezin.services]] entry; per-service entries are resolved relative to that service's root:

[[tool.pezin.services]]
name = "api"
version_files = [{ path = "api/package.json", file_type = "json" }]
[tool.pezin.services.changelog]
path = "api/CHANGELOG.md"

Upgrading from < 0.8.0

Projects upgrading from versions before 0.8.0 will see CHANGELOG.md edited automatically on the first conventional commit after upgrade. If you maintain the changelog by hand, set enabled = false to keep the previous behaviour.

Unstaged Changes and the pre-commit Data-Loss Guard

Under the pre-commit framework, any unstaged changes are "parked" in a patch file while hooks run, then re-applied afterwards. If a hook rewrites one of those files, the re-apply can fail and the unstaged work disappears from the worktree (it survives only in ~/.cache/pre-commit/patch*).

Since v0.8.1 pezin guards against this:

  • Skips the bump when pre-commit has parked unstaged changes to a file pezin would rewrite (version files or CHANGELOG.md). The hook prints a message explaining the skip; stash or commit those changes, then commit again or run pezin bump to bump manually.
  • Atomic rollback: if pezin's own write/amend path fails halfway, the worktree, index and HEAD are restored to their pre-hook state - no half-applied bumps, no leftover files.

Unstaged changes to other files never block the bump; the parked patch restores cleanly around it.

The guard relies on pezin-prepare (installed above) marking the start of each commit. Without it — e.g. only pezin-post installed — the guard falls back to a 60-second recency window, and a parked patch older than that (slow hook environments being built, slow sibling hooks) can slip past it. Install both hooks.

If you were hit by this bug before v0.8.1, your "lost" work is still in the patch file pre-commit logged (~/.cache/pre-commit/pre-commit.log names it). Recover with:

git apply --exclude=<conflicting-file> --whitespace=nowarn <patch-file>

Note for local-repo consumers (repo: <path>, rev: HEAD or a branch): pre-commit keys hook environments on the rev string, so a moved HEAD does not refresh them - pre-commit install-hooks alone keeps running the old code. Pin the rev to a released tag (edit it manually or run pre-commit autoupdate); the changed rev forces the environment rebuild. Verify with pre-commit run pezin-post --all-files -v after upgrading.

Conventional Commits

Type Version Bump Example
feat: Minor (1.0.0 → 1.1.0) feat: add user dashboard
fix: Patch (1.0.0 → 1.0.1) fix: resolve login issue
feat!: Major (1.0.0 → 2.0.0) feat!: redesign API
docs:, chore:, etc. No bump docs: update readme

Special tokens:

  • [skip-bump] - Skip version bump
  • [force-major] - Force major bump
  • [pre-release=beta] - Add pre-release label

CLI Usage

# Check versions
pezin -v                       # Shows current project + pezin versions
pezin version                  # Same as above

# Manual version bumping
pezin minor                    # Bump minor version
pezin patch --dry-run          # Preview changes
pezin major --pre-release rc   # Pre-release version

# Custom configuration
pezin patch --config package.json
pezin minor --skip-changelog

# Multi-language project example
# Updates pyproject.toml, package.json, version.h simultaneously
git commit -m "feat: add multi-platform support"

Python API

from pezin import Version, ConventionalCommit, ChangelogManager

# Parse and bump version
version = Version.parse("1.2.3")
new_version = version.bump("minor")
print(str(new_version))  # "1.3.0"

# Parse commit message
commit = ConventionalCommit.parse(
    "feat(api)!: add new endpoint\n\nBREAKING CHANGE: new auth"
)
print(commit.breaking)  # True

# Update changelog
config = ChangelogConfig(repo_url="https://github.com/tatus9/pezin.git")
manager = ChangelogManager(config)
manager.update_changelog(
    Path("CHANGELOG.md"),
    str(new_version),
    [commit]
)

Conventional Commits Guide

Pezin follows the Conventional Commits specification:

Basic Format

<type>[optional scope]: <description>

[optional body]

[optional footer(s)]

Version Bump Rules

  • feat: Minor version bump (1.0.0 → 1.1.0) - New features
  • fix: Patch version bump (1.0.0 → 1.0.1) - Bug fixes
  • ! or BREAKING CHANGE: Major version bump (1.0.0 → 2.0.0) - Breaking changes

Other Commit Types (no version bump)

  • docs: Documentation changes
  • style: Code style/formatting changes
  • refactor: Code refactoring without functional changes
  • perf: Performance improvements
  • test: Adding or updating tests
  • chore: Maintenance tasks, dependency updates
  • ci: CI/CD configuration changes
  • build: Build system changes

Special Footer Tokens

Control version bumping behavior with footer tokens:

# Skip version bump entirely
git commit -m "feat: new feature

[skip-bump]"

# Force specific bump type
git commit -m "docs: update readme

[force-patch]"

# Add pre-release label
git commit -m "feat: beta feature

[pre-release=beta]"

Available tokens:

  • [skip-bump]: Skip version bump
  • [force-major]: Force major bump (1.0.0 → 2.0.0)
  • [force-minor]: Force minor bump (1.0.0 → 1.1.0)
  • [force-patch]: Force patch bump (1.0.0 → 1.0.1)
  • [pre-release=label]: Add pre-release label (alpha, beta, rc)

Documentation

Examples

Contributing

We welcome contributions!

License

MIT License - feel free to use this project for any purpose.

Release files for pezin 0.9.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for pezin 0.9.0
File Size Uploaded
pezin-0.9.0.tar.gz 53.5 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for pezin 0.9.0
File Interpreter ABI Platform
pezin-0.9.0-py3-none-any.whl Python 3 none any Details

Total release size: 112.8 kB

Release files / pezin-0.9.0.tar.gz

Download URL pezin-0.9.0.tar.gz
Size 53.5 kB
Tags Source
SHA-256 checksum
How to use checksums
7a2bf2f90539e1ffc0dec763c7f9a6496ce59064da0dd361fee19298bb9ecaa1
BLAKE2b-256 checksum
How to use checksums
2eea37ecdd6e099d23907e3742029eeb2cfce73f24223bb29c3c6e902bebeb62
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 5, 2026.

Transparency log

Release files / pezin-0.9.0-py3-none-any.whl

Download URL pezin-0.9.0-py3-none-any.whl
Size 59.3 kB
Tags Python 3
SHA-256 checksum
How to use checksums
57298f073b0ec3aa9733d62dd7dc6513838e073392e41cd0d6ff7c324c07a76f
BLAKE2b-256 checksum
How to use checksums
4bbe4d23a5d407cf6b33935097f0d2aa6b69f38238aa1d4259d755485d96c120
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
Yes
Uploaded via twine/7.0.0 CPython/3.13.14

Provenance

Provenance describes where a file came from. On PyPI, provenance is shared via attestations, which provide a verifiable record of the build or publishing details. View details, limitations and caveats.

PyPI Publish Attestation

PyPI verified that this artifact, at this checksum, originated from the publisher listed below.

Signed by GitHub Actions, verified by PyPI on Sep 5, 2026.

Transparency log

Release history Release notifications | RSS feed

0.9.1

2 release files

This release

0.9.0 This release

2 release files

0.3.1

2 release files

0.2.1

2 release files

0.0.3

2 release files

0.0.2

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page