Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion commitizen/project_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@


def is_pre_commit_installed() -> bool:
return bool(shutil.which("pre-commit"))
return any(shutil.which(tool) for tool in ("pre-commit", "prek"))


def get_default_version_provider() -> Literal[
Expand Down
8 changes: 4 additions & 4 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
[![Conda Version](https://img.shields.io/conda/vn/conda-forge/commitizen?style=flat-square)](https://anaconda.org/conda-forge/commitizen)
[![homebrew](https://img.shields.io/homebrew/v/commitizen?color=teal&style=flat-square)](https://formulae.brew.sh/formula/commitizen)
[![Codecov](https://img.shields.io/codecov/c/github/commitizen-tools/commitizen.svg?style=flat-square)](https://codecov.io/gh/commitizen-tools/commitizen)
[![pre-commit](https://img.shields.io/badge/pre--commit-enabled-brightgreen?style=flat-square&logo=pre-commit&logoColor=white)](https://github.com/pre-commit/pre-commit)
[![prek](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/j178/prek/master/docs/assets/badge-v0.json&style=flat-square&color=brightgreen)](https://github.com/j178/prek)

![Using Commitizen cli](images/demo.gif)

Expand Down Expand Up @@ -182,7 +182,7 @@ This command is particularly useful for automation scripts and CI/CD pipelines.

For example, you can use the output of the command `cz changelog --dry-run "$(cz version -p)"` to notify your team about a new release in Slack.

#### Pre-commit Integration
#### Prek and Pre-commit Integration

Commitizen can automatically validate your commit messages using pre-commit hooks.

Expand All @@ -200,7 +200,7 @@ repos:

2. Install the hooks:
```sh
pre-commit install --hook-type commit-msg --hook-type pre-push
prek install --hook-type commit-msg --hook-type pre-push
```

| Hook | Recommended Stage |
Expand All @@ -210,7 +210,7 @@ pre-commit install --hook-type commit-msg --hook-type pre-push

> **Note**: Replace `master` with the [latest tag](https://github.com/commitizen-tools/commitizen/tags) to avoid warnings. You can automatically update this with:
> ```sh
> pre-commit autoupdate
> prek autoupdate
> ```

For more details about commit validation, see the [check command documentation](https://commitizen-tools.github.io/commitizen/commands/check/).
Expand Down
40 changes: 27 additions & 13 deletions docs/tutorials/auto_check.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,35 @@

## About

To automatically check a commit message prior to committing, you can use a [Git hook](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks). This ensures that all commit messages follow your project's commitizen format before they are accepted into the repository.
To automatically check a commit message before committing, use a [Git hook](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks). This ensures all commit messages match your project's commitizen format before they are accepted into the repository.

When a commit message fails validation, Git will reject the commit and display an error message explaining what went wrong. You'll need to amend your commit message to follow the required format before the commit can proceed.
When a commit message fails validation, Git rejects the commit and displays an error explaining what went wrong. Update the message to the required format before trying again.

## How to

There are two common methods for installing the hooks:

### Method 1: Using [pre-commit](https://pre-commit.com/) (Recommended)
### Method 1: Using pre-commit hook frameworks (Recommended)

[pre-commit](https://pre-commit.com/) is a framework for managing and maintaining multi-language pre-commit hooks. It's the recommended approach as it handles hook installation, updates, and execution automatically.
Using pre-commit hook frameworks is the recommended approach because hook installation, updates, and execution are handled automatically.
Two common frameworks are:

#### Step 1: Install pre-commit
1. [prek](https://prek.j178.dev) (faster)
2. [pre-commit](https://pre-commit.com/)


In the steps below, we'll use `prek`.


!!! tip "Using pre-commit framework"
Replace `prek` with `pre-commit` in the steps below if you prefer that tool. The configuration format is similar.



#### Step 1: Install prek

```sh
python -m pip install pre-commit
python -m pip install prek
```

#### Step 2: Create `.pre-commit-config.yaml`
Expand All @@ -42,14 +55,14 @@ repos:
Install the configuration into Git's hook system:

```bash
pre-commit install --hook-type commit-msg
prek install --hook-type commit-msg
```

The hook is now active! Every time you create a commit, commitizen will automatically validate your commit message.

### Method 2: Manual Git hook installation

If you prefer not to use pre-commit, you can manually create a Git hook. This gives you full control over the hook script but requires manual maintenance.
If you prefer not to use a pre-commit framework, you can manually create a Git hook. This gives you full control over the hook script but requires manual maintenance.

#### Step 1: Create the commit-msg hook

Expand Down Expand Up @@ -90,7 +103,7 @@ git commit -m "invalid commit message"
git commit -m "feat: add new feature"
```

If the hook is working correctly, invalid commit messages will be rejected with an error message explaining what's wrong.
If the hook is working correctly, invalid commit messages are rejected with an error explaining what's wrong.

## What happens when validation fails?

Expand Down Expand Up @@ -123,12 +136,12 @@ pattern: ^(feat|fix|docs|style|refactor|perf|test|build|ci|chore|revert)(\(.+\))
- **Verify commitizen is installed**: Run `cz --version` to confirm commitizen is available in your PATH
- **Check Git version**: Ensure you're using a recent version of Git that supports hooks

### Pre-commit hook not working
### Prek hook not working

- **Verify installation**: Run `pre-commit --version` to confirm pre-commit is installed
- **Reinstall the hook**: Try running `pre-commit install --hook-type commit-msg` again
- **Verify installation**: Run `prek --version` to confirm pre-commit is installed
- **Reinstall the hook**: Try running `prek install --hook-type commit-msg` again
- **Check configuration**: Verify your `.pre-commit-config.yaml` file is valid YAML and in the project root
- **Update hooks**: Run `pre-commit autoupdate` to update to the latest versions
- **Update hooks**: Run `prek autoupdate` to update to the latest versions

### Bypassing the hook (when needed)

Expand All @@ -145,4 +158,5 @@ git commit --no-verify -m "your message"

- Learn more about [Git hooks](https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks)
- See the [check command documentation](../commands/check.md) for more validation options
- Check out [prek documentation](https://prek.j178.dev/) for advanced hook management
- Check out [pre-commit documentation](https://pre-commit.com/) for advanced hook management
7 changes: 4 additions & 3 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -107,17 +107,18 @@ test = [
"pytest-freezer>=0.4.6",
"pytest-xdist>=3.1.0",
"pytest-gitconfig>=0.9.0",
"pre-commit>=4.5.1",
]

linters = [
"ruff>=0.11.5",
"pre-commit>=3.2.0",
"mypy>=1.16.0",
"types-deprecated>=1.2.9.2",
"types-python-dateutil>=2.8.19.13",
"types-PyYAML>=5.4.3",
"types-termcolor>=0.1.1",
"types-colorama>=0.4.15.20240311",
"prek>=0.2.28",
]

documentation = ["mkdocs>=1.4.2", "mkdocs-material>=9.1.6"]
Expand Down Expand Up @@ -303,8 +304,8 @@ doc.help = "Live documentation server"
doc.cmd = "mkdocs serve"

ci.help = "Run all tasks in CI"
ci.sequence = ["check-commit", { cmd = "pre-commit run --all-files" }, "cover"]
ci.sequence = ["check-commit", { cmd = "prek run --all-files" }, "cover"]
ci.env = { SKIP = "no-commit-to-branch" }

setup-pre-commit.help = "Install pre-commit hooks"
setup-pre-commit.cmd = "pre-commit install"
setup-pre-commit.cmd = "prek install"
10 changes: 6 additions & 4 deletions tests/test_bump_create_commit_message.py
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ def test_create_tag(test_input, expected):
assert new_tag == expected


@pytest.mark.parametrize("hook_runner", ("pre-commit", "prek"))
@pytest.mark.parametrize(
"retry",
(
Expand All @@ -38,7 +39,7 @@ def test_create_tag(test_input, expected):
),
)
@pytest.mark.usefixtures("tmp_commitizen_project")
def test_bump_pre_commit_changelog(util: UtilFixture, retry):
def test_bump_pre_commit_changelog(util: UtilFixture, retry, hook_runner):
util.freezer.move_to("2022-04-01")
bump_args = ["bump", "--changelog", "--yes"]
if retry:
Expand Down Expand Up @@ -69,7 +70,7 @@ def test_bump_pre_commit_changelog(util: UtilFixture, retry):
)
cmd.run("git add -A")
cmd.run('git commit -m "fix: _test"')
cmd.run("pre-commit install")
cmd.run(f"{hook_runner} install")
util.run_cli(*bump_args)
# Pre-commit fixed last line adding extra indent and "\" char
assert Path("CHANGELOG.md").read_text() == dedent(
Expand All @@ -83,9 +84,10 @@ def test_bump_pre_commit_changelog(util: UtilFixture, retry):
)


@pytest.mark.parametrize("hook_runner", ("pre-commit", "prek"))
@pytest.mark.parametrize("retry", (True, False))
@pytest.mark.usefixtures("tmp_commitizen_project")
def test_bump_pre_commit_changelog_fails_always(util: UtilFixture, retry):
def test_bump_pre_commit_changelog_fails_always(util: UtilFixture, retry, hook_runner):
util.freezer.move_to("2022-04-01")
bump_args = ["bump", "--changelog", "--yes"]
if retry:
Expand All @@ -106,7 +108,7 @@ def test_bump_pre_commit_changelog_fails_always(util: UtilFixture, retry):
)
cmd.run("git add -A")
cmd.run('git commit -m "feat: forbid changelogs"')
cmd.run("pre-commit install")
cmd.run(f"{hook_runner} install")
with pytest.raises(exceptions.BumpCommitFailedError):
util.run_cli(*bump_args)

Expand Down
1 change: 1 addition & 0 deletions tests/test_project_info.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ def _create_project_files(files: dict[str, str | None]) -> None:
"which_return, expected",
[
("/usr/local/bin/pre-commit", True),
("/usr/local/bin/prek", True),
(None, False),
("", False),
],
Expand Down
46 changes: 37 additions & 9 deletions uv.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.