From 05e90917d46e4d22f9818d8414360a3066530cc4 Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 7 Oct 2026 18:20:15 +0000 Subject: [PATCH 1/2] docs: bring the site in step with v2.18.3 2.18.3 is out, so the pins, the changelog and the pages describe it. - The four pre-commit pins move from v2.18.2 to v2.18.3, and the changelog gains the v2.18.3 entry (2026-10-07) with a Highlights row, since the release adds user-visible behaviour. - GitLab CI, Bitbucket and Azure Pipelines: commit-check --branch now reads each CI's own variables, so the jobs call it as is instead of piping the branch name in. A note keeps the piped form for 2.18.2 and older. - Command-line recipes: a section on --fix, and how --branch names the branch on a detached checkout. - Pre-commit hook: args: [--fix] on check-message. - Configuration: the warning for a setting nothing reads. The sample output is what 2.18.3 printed. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_013rE6bouKaJvsRyKA4tjqCb --- docs/changelog.md | 35 +++++++++++++++++++++++++++++++++++ docs/configuration.md | 24 +++++++++++++++++++++++- docs/example.md | 33 +++++++++++++++++++++++++++++++-- docs/guides/other-ci.md | 34 +++++++++++++++++++++++----------- docs/guides/pre-commit.md | 24 ++++++++++++++++++++++-- 5 files changed, 134 insertions(+), 16 deletions(-) diff --git a/docs/changelog.md b/docs/changelog.md index 2bcf339..7facb1c 100644 --- a/docs/changelog.md +++ b/docs/changelog.md @@ -11,6 +11,7 @@ below and to the page that documents the feature properly. | Version | What changed | Documented in | |---|---|---| +| [2.18.3](#v2183) | `--fix` corrects a message in place; `--branch` reads GitLab, Bitbucket, Azure and Jenkins variables | [Fixing a message in place](example.md#fixing-a-message-in-place) · [Other CI](guides/other-ci.md) | | [2.18.0](#v2180) | AI disclosure policy: three rules, and the correction written for you | [Policy guides](guides/policies.md#asking-for-disclosure-instead) · [CC014](rules.md#cc014) | | [2.17.0](#v2170) | Concrete corrections for mechanical slips; a `warn` level per rule | [Reading the JSON](example.md#reading-the-json) · [Report without enforcing](configuration.md#report-a-rule-without-enforcing-it) | | [2.16.0](#v2160) | Tag name validation, and file size, path and pattern policies | [CC401](rules.md#cc401) · [CC302–CC304](rules.md#push-rules) | @@ -29,6 +30,40 @@ below and to the page that documents the feature properly. | [2.5.0](#v250) | Organization-wide config with `inherit_from` | [Across an organization](guides/organization.md) | | [2.0.0](#v200) | Configuration moved from YAML to TOML — breaking | [Migrating from v1](migration.md) | +## v2.18.3 (2026-10-07) { #v2183 } + +### Added + +* **`--fix` corrects a commit message in place** — when every message check + the commit failed has a mechanical fix, the ones `--format json` reports in + `fix`, the message file is rewritten and the check passes, so + `Fix: add streaming support` is recorded as `fix: add streaming support`. + Anything that takes a judgment, such as a subject with no type at all, + leaves the file as it was and is rejected as before. It needs a message + file, so stdin and `--rev` are a usage error, and `--dry-run` rewrites + nothing. With pre-commit it is `args: [--fix]` on `check-message`. + See PR [#594](https://github.com/commit-check/commit-check/pull/594) and + [Fixing a message in place](example.md#fixing-a-message-in-place). + +* **`--branch` reads the branch from GitLab, Bitbucket, Azure and Jenkins** — + on a detached checkout git names no branch, and only GitHub's variables + were read, so elsewhere the name became `HEAD`, which is always allowed, and + every branch passed. Each CI's own variables are now read, a merge or pull + request's source branch first, and Jenkins' only inside a Jenkins build that + is not a tag build. A pipeline that runs `--branch` on a long-lived branch + such as `develop` now has that name judged; `allow_branch_names` can allow + it. + See PR [#600](https://github.com/commit-check/commit-check/pull/600) and + [GitLab CI, Bitbucket and Azure Pipelines](guides/other-ci.md). + +* **A setting nothing reads is named** — a misspelt key in `cchk.toml` was + ignored in silence, and its rule stayed at the default. Each one is now + reported on stderr with the closest real name, as in `⚠ unknown setting + [commit] subject_max_lenght is ignored; did you mean subject_max_length?`. + The exit code and the JSON do not change. + See PR [#593](https://github.com/commit-check/commit-check/pull/593) and + [Settings nothing reads](configuration.md#settings-nothing-reads). + ## v2.18.2 (2026-09-28) { #v2182 } ### Fixed diff --git a/docs/configuration.md b/docs/configuration.md index decda1d..8c10a40 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -65,6 +65,28 @@ $ commit-check --config path/to/cchk.toml --message PyCharm and IntelliJ offer completion, validation and inline documentation for `cchk.toml` with nothing to configure. +### Settings nothing reads + +A key that no check reads, usually a misspelling, leaves its rule at the +default. Commit Check names each one on stderr, with the closest real name: + +```toml title="cchk.toml" +[commit] +subject_max_lenght = 50 +``` + +```console +$ echo "feat: add streaming support" | commit-check -m +⚠ unknown setting [commit] subject_max_lenght is ignored; did you mean subject_max_length? +``` + +It is a warning, not an error: the exit code and the JSON on stdout do not +change. The top-level `warn` list and the GitHub App's +[`[jira]`](guides/github-app.md#jira-ticket-references) and +[`[pull_request]`](#pull-requests-every-commit-or-the-squash-message) sections +are read elsewhere and are not reported. The Python API and the MCP server +load the file themselves and do not report it either. + ## Inheriting a shared config An organization can keep one base policy and have every repository build on it. @@ -239,7 +261,7 @@ Used from a hook definition, with no config file anywhere in the repository: ```yaml title=".pre-commit-config.yaml" repos: - repo: https://github.com/commit-check/commit-check - rev: v2.18.2 + rev: v2.18.3 hooks: - id: check-message args: diff --git a/docs/example.md b/docs/example.md index ec50921..dd582f0 100644 --- a/docs/example.md +++ b/docs/example.md @@ -81,6 +81,27 @@ EOF $ commit-check -m /tmp/msg.txt ``` +### Fixing a message in place + +`--fix` corrects the message instead of only rejecting it. When every check +the message failed has a mechanical fix, the corrections that +[`--format json` reports in `fix`](#reading-the-json), it rewrites the message +file and the check passes: + +```console +$ printf 'Fix: add streaming support\n' > msg.txt +$ commit-check -m --fix msg.txt +✎ fixed the commit message: CC001 message +$ cat msg.txt +fix: add streaming support +``` + +A failure that takes a judgment, such as `updated the parser`, which has no +type at all, leaves the file as it was and fails as before. `--fix` needs a +message file to rewrite, so with stdin or `--rev` it is a usage error, and +`--dry-run` rewrites nothing. In the `commit-msg` hook it is one argument: +see [Fixing the message instead of rejecting it](guides/pre-commit.md#fixing-the-message-instead-of-rejecting-it). + ## Checking the branch ```console @@ -97,6 +118,13 @@ feature/role-caching release/v1.2.0 ``` +On a detached HEAD, which is how most CI systems check out a commit, git has +no branch to report, so the name comes from the CI's own variables: GitHub +Actions, GitLab CI, Bitbucket Pipelines, Azure Pipelines, and Jenkins +multibranch inside a Jenkins build. A merge or pull request's source branch is +read first. With none of these set, the name is `HEAD`. The variables other +than GitHub's are read from 2.18.3 on. + ## Checking the committer ```console @@ -131,7 +159,7 @@ pushed: ```yaml title=".pre-commit-config.yaml" repos: - repo: https://github.com/commit-check/commit-check - rev: v2.18.2 + rev: v2.18.3 hooks: - id: check-no-force-push stages: [pre-push] @@ -302,7 +330,8 @@ $ echo "Fix: add streaming support" | commit-check -m --format json | jq '.check `fix` is empty whenever the correction takes a judgment — a subject with no type at all, one over the length limit, a verb that is not imperative — and `suggest` then keeps the rule's general advice. A tool can apply a non-empty -`fix` as it stands; a person only ever needs `suggest`. +`fix` as it stands, and [`--fix`](#fixing-a-message-in-place) does that to a +message file; a person only ever needs `suggest`. A rule listed under [`warn`](configuration.md#report-a-rule-without-enforcing-it) reports with `"status": "warn"` instead of `"fail"`. The top-level `status` is diff --git a/docs/guides/other-ci.md b/docs/guides/other-ci.md index 9138b47..d95a917 100644 --- a/docs/guides/other-ci.md +++ b/docs/guides/other-ci.md @@ -9,11 +9,10 @@ hook and the Action. Two things are different from running it on your own machine, and each example below handles both: -- **The checkout is a detached HEAD.** git has no branch to report, so - `commit-check --branch` would judge `HEAD`, which is always allowed, and - pass whatever the branch is called. Pipe the branch name in from the CI's - own variable instead: a value piped into `--branch` on its own is the name - it checks. +- **The checkout can be a detached HEAD**, as it is on GitLab and Azure, and + then git has no branch to report. `commit-check --branch` reads the name + from the CI's own variables instead, the merge or pull request's source + branch first, so the jobs call it as is. - **A merge request has more than one commit.** `--rev` checks one commit, so the job loops over the commits the merge request adds, as in [Checking a range of commits](../example.md#checking-a-range-of-commits). @@ -25,6 +24,19 @@ Each job runs on merge or pull requests only, because the variables it reads exist only there. Add `--author-name --author-email` to the `commit-check` call in the loop to check each commit's author as well. +!!! note "On 2.18.2 or older" + + Releases before 2.18.3 read only GitHub's variables, so on a detached + checkout `--branch` judges `HEAD`, which is always allowed, and passes + whatever the branch is called. Pipe the name in instead: a value piped + into `--branch` on its own is the name it checks. + + ```console + $ echo "$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME" | commit-check --branch # GitLab + $ echo "$BITBUCKET_BRANCH" | commit-check --branch # Bitbucket + $ echo "${SYSTEM_PULLREQUEST_SOURCEBRANCH#refs/heads/}" | commit-check --branch # Azure + ``` + ## GitLab CI ```yaml title=".gitlab-ci.yml" @@ -36,7 +48,7 @@ commit-check: - if: $CI_PIPELINE_SOURCE == "merge_request_event" script: - pip install commit-check - - echo "$CI_MERGE_REQUEST_SOURCE_BRANCH_NAME" | commit-check --branch + - commit-check --branch - | head="${CI_MERGE_REQUEST_SOURCE_BRANCH_SHA:-$CI_COMMIT_SHA}" shas=$(git rev-list "$CI_MERGE_REQUEST_DIFF_BASE_SHA..$head") || exit 1 @@ -69,7 +81,7 @@ pipelines: depth: full script: - pip install commit-check - - echo "$BITBUCKET_BRANCH" | commit-check --branch + - commit-check --branch - | shas=$(git rev-list "$BITBUCKET_PR_DESTINATION_COMMIT..$BITBUCKET_COMMIT") || exit 1 status=0 @@ -104,7 +116,7 @@ steps: versionSpec: "3.13" - script: pip install commit-check displayName: Install Commit Check - - script: echo "${SYSTEM_PULLREQUEST_SOURCEBRANCH#refs/heads/}" | commit-check --branch + - script: commit-check --branch displayName: Check the branch name - script: | shas=$(git rev-list HEAD^1..HEAD^2) || exit 1 @@ -123,9 +135,9 @@ steps: - A pull request build checks out a merge commit whose first parent is the target branch and second the pull request, so `HEAD^1..HEAD^2` is exactly the commits the pull request adds. -- `System.PullRequest.SourceBranch` is `refs/heads/feature/x` in Azure Repos - and `feature/x` for a GitHub repository; `#refs/heads/` strips the prefix - where there is one. +- The branch name comes from `System.PullRequest.SourceBranch`, which is + `refs/heads/feature/x` in Azure Repos and `feature/x` for a GitHub + repository. Commit Check drops the `refs/heads/` prefix itself. - In Azure Repos the `pr:` section is ignored. Pull request builds come from a [build validation branch policy](https://learn.microsoft.com/en-us/azure/devops/repos/git/branch-policies#set-build-validation) on the target branch, and `System.PullRequest.SourceBranch` is only set for diff --git a/docs/guides/pre-commit.md b/docs/guides/pre-commit.md index eb1dc9c..61af741 100644 --- a/docs/guides/pre-commit.md +++ b/docs/guides/pre-commit.md @@ -8,7 +8,7 @@ Add Commit Check to `.pre-commit-config.yaml`: ```yaml title=".pre-commit-config.yaml" repos: - repo: https://github.com/commit-check/commit-check - rev: v2.18.2 + rev: v2.18.3 hooks: - id: check-message - id: check-branch @@ -55,7 +55,7 @@ Options can be passed as hook arguments, which keeps everything in one file: ```yaml title=".pre-commit-config.yaml" repos: - repo: https://github.com/commit-check/commit-check - rev: v2.18.2 + rev: v2.18.3 hooks: - id: check-message args: @@ -68,6 +68,26 @@ A `cchk.toml` is usually the better choice once you have more than a couple of options, because CI and the CLI read it too. See [Configuration](../configuration.md) for the precedence rules. +## Fixing the message instead of rejecting it + +Give `check-message` the `--fix` argument and it corrects a message whose +every failure has a mechanical fix, such as a type written `Fix` or a missing +colon, and lets the commit through: + +```yaml title=".pre-commit-config.yaml" +repos: + - repo: https://github.com/commit-check/commit-check + rev: v2.18.3 + hooks: + - id: check-message + args: [--fix] +``` + +With that, `git commit -m "Fix: add streaming support"` records +`fix: add streaming support`. A message that needs a judgment, such as one +with no type at all, is rejected as before. More in +[Fixing a message in place](../example.md#fixing-a-message-in-place). + ## Skipping a hook Occasionally you need to get a commit through — a mid-rebase fixup, an From ddd6ae54356b0f7e24e44df0dc0f00e2860fb61c Mon Sep 17 00:00:00 2001 From: Claude Date: Wed, 7 Oct 2026 18:27:24 +0000 Subject: [PATCH 2/2] docs: list the tag and file hooks in the pre-commit guide - The hook table gains check-files (CC302-CC304) and check-tag (CC401), pre-push hooks since 2.16.0 that the README already sends readers here for. - check-message and the App run CC001-CC016 since 2.18.0, not CC001-CC013. - A note says pre-commit runs no hook for a push that creates a ref without new commits, so a tag pushed on its own after its commit is never checked. Checked with pre-commit 4.6.2 at rev v2.18.3: check-files rejected a 4 KB file over max_size = "1KB", check-tag rejected release-2.0 pushed with its commit, and release-1.0 pushed alone on an already-pushed commit ran no hook. Co-Authored-By: Claude Opus 5.5 (1M context) Claude-Session: https://claude.ai/code/session_013rE6bouKaJvsRyKA4tjqCb --- docs/guides/github-app.md | 2 +- docs/guides/pre-commit.md | 10 ++++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/docs/guides/github-app.md b/docs/guides/github-app.md index 4241e0b..56191bd 100644 --- a/docs/guides/github-app.md +++ b/docs/guides/github-app.md @@ -47,7 +47,7 @@ way everywhere: ### Which rules -The App runs the commit message, author and branch rules — [CC001–CC013](../rules.md#commit-message-rules), +The App runs the commit message, author and branch rules — [CC001–CC016](../rules.md#commit-message-rules), [CC101–CC102](../rules.md#author-rules) and [CC201–CC202](../rules.md#branch-rules) — with the commit's own branch as the branch under test. One thing it does not do: the push, file and tag rules ([CC301–CC304](../rules.md#push-rules), diff --git a/docs/guides/pre-commit.md b/docs/guides/pre-commit.md index 61af741..98aca63 100644 --- a/docs/guides/pre-commit.md +++ b/docs/guides/pre-commit.md @@ -36,18 +36,24 @@ That is it. The next malformed commit message is rejected before it exists. | Hook ID | Stage | Rules | |---|---|---| -| `check-message` | `commit-msg` | [CC001–CC013](../rules.md#commit-message-rules) | +| `check-message` | `commit-msg` | [CC001–CC016](../rules.md#commit-message-rules) | | `check-branch` | `pre-commit` | [CC201–CC202](../rules.md#branch-rules) | | `check-author-name` | `pre-commit` | [CC101](../rules.md#cc101) | | `check-author-email` | `pre-commit` | [CC102](../rules.md#cc102) | | `check-no-force-push` | `pre-push` | [CC301](../rules.md#cc301) | +| `check-files` | `pre-push` | [CC302–CC304](../rules.md#push-rules) | +| `check-tag` | `pre-push` | [CC401](../rules.md#cc401) | -`check-no-force-push` also needs its own install: +The three `pre-push` hooks need their own install too: ```console $ pre-commit install --hook-type pre-push ``` +pre-commit runs no hook for a push that creates a ref without carrying new +commits. So a new tag pushed on its own, when the commit it points at is +already on the remote, is never seen by `check-tag`. + ## Configuring without a TOML file Options can be passed as hook arguments, which keeps everything in one file: