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

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.1

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.1
File Size Uploaded
pezin-0.9.1.tar.gz 54.6 kB Details

Built distribution (wheel)

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

Total release size: 114.8 kB

Release files / pezin-0.9.1.tar.gz

Download URL pezin-0.9.1.tar.gz
Size 54.6 kB
Tags Source
SHA-256 checksum
How to use checksums
aa5c1bcf33a73a11eca1cba551181ad2134da34123a016433d49b74a2188c0c0
BLAKE2b-256 checksum
How to use checksums
5547e0284aa890b9d6103b3f5f95012efc4691fc3770347d7f4718e4c670dfff
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 26, 2026.

Transparency log

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

Download URL pezin-0.9.1-py3-none-any.whl
Size 60.2 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b87361db5e8b7a3b1a62e8356942f4ad1f0cacc7a1f878d3b60c4a6c61313133
BLAKE2b-256 checksum
How to use checksums
281ded4d42e77ad45d8bb6b765802d46ac8cd17720d1d4739469abe17368a0ea
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 26, 2026.

Transparency log

Release history Release notifications | RSS feed

This release

0.9.1 This release

2 release files

0.9.0

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