Compared with other tools¶
What else checks commit messages, branch names and pull request titles on GitHub, what each one does, and when it is the better choice. Prices and features are as the projects list them in September and October 2026; follow the links for the current state. GitHub's own rulesets are on their own page.
The field¶
| Tool | What it is | What it checks | Where it runs | Price |
|---|---|---|---|---|
| commitlint with commitlint-github-action | The reference Conventional Commits linter in the JavaScript world: shared configs, plugins, a commitizen prompt | Commit messages | Node hook (husky), CI Action | Free, open source |
| gitlint | A Python commit message linter with a commit-msg hook, configured in a .gitlint file; one of the two commit linters the pre-commit hooks page features. Its latest release, 0.19.1, is from March 2023, and its PyPI page says the maintainer is looking for co-maintainers |
Commit messages: title and body length, whitespace, required words, regexes; Conventional Commits and sign-off as opt-in rules | Git hook, pre-commit, CLI | Free, open source |
| action-semantic-pull-request | The most-used pull request title check; Electron, Vite and Vercel run it | The pull request title (optionally the single commit, for squash merges) | GitHub Action | Free, open source |
| Semantic PRs | A GitHub App with the same idea: type and scope on the title or the commits | Pull request title or commits | GitHub App | Free, open source |
| commitcheck | A hosted App that applies one regular expression, set in its web admin | Commit message, pull request title or description, by regex | GitHub App | Free for public repositories; $25 a month for private ones |
| DCO app and DCO-2 | The sign-off check the Linux kernel and the CNCF use, with a remediation flow for missing sign-offs | Signed-off-by trailers |
GitHub App | Free, open source |
| PRLint, PR Title Checker | Regular expressions over pull request fields | Title, body, labels, branch | App / Action | Free, open source |
| Commit Check | One rule engine, documented rule by rule, run as a hook, a CLI, an Action, a hosted App or an MCP tool | Commit message, branch name, author name and email, sign-off, AI attribution, force pushes, file size and paths, tag names; the pull request title (Action) and the squash message of a pull request (App) | All of the above | Free, open source; the App's private organization repositories move to a paid plan later |
What is different about Commit Check¶
- One config, every place it runs. The same
cchk.tomldrives the pre-commit hook, the Action, the App and the MCP server. The others cover one place each: commitlint is a Node hook and an Action; the title checkers are Actions or Apps; commitcheck is an App. - More than the message. Branch names, author identity, sign-off, AI attribution trailers, force pushes and file rules are rules, not separate tools to find and wire up.
- A failure explains itself. Every rule has a stable ID, a one-line error, a suggestion and a documentation page, and the Action and App show all of it where the failure is. A regex tool reports a mismatch.
- Squash-aware. The App can check the message a squash merge would land, built from the repository's merge settings, rather than every commit on the branch or only the title.
- No JavaScript toolchain. It is a Python package with no runtime dependencies; a Go, Rust or Java repository does not need Node to lint its commits.
Where the others are stronger¶
- commitlint's ecosystem. Years of shared configs (
@commitlint/config-*), plugins and editor integrations, plus an interactive prompt for writing the message. Commit Check has no prompt, and its rules are the ones it ships. - A Node monorepo already on husky. If commitlint is installed and the policy is "message only", there is little to gain from switching.
- Sign-off remediation. The DCO app can accept a later commit that certifies earlier ones, and lets a maintainer override. Commit Check checks the trailer and stops there.
- Rejecting the push itself. Only GitHub's rulesets (and a server-side hook on GitHub Enterprise Server) refuse a ref update; see the rulesets page. Every tool above, Commit Check included, marks the commit or blocks the merge.
Coming from gitlint¶
Both are Python, both run as a commit-msg hook through pre-commit, so the
switch is a change to .pre-commit-config.yaml and a translation of
.gitlint into cchk.toml.
Replace the hook:
repos:
- repo: https://github.com/commit-check/commit-check
rev: v2.19.4
hooks:
- id: check-message
Install it the same way: pre-commit install --hook-type commit-msg.
Two defaults differ. Commit Check requires
Conventional Commits unless you turn it off, where
gitlint makes it an opt-in rule (contrib=CT1). And gitlint requires a body
out of the box (B6), where Commit Check does not. This keeps gitlint's
defaults:
[commit]
conventional_commits = false # drop if you used contrib=CT1
subject_max_length = 72 # T1
subject_min_length = 5 # T8
allow_wip_commits = false # T5's default word, WIP
require_body = true # B6
Rule by rule:
| gitlint | Commit Check |
|---|---|
T1 title-max-length |
subject_max_length (CC004) |
T5 title-must-not-contain-word (default WIP) |
allow_wip_commits = false (CC010), which rejects a subject that starts with WIP; gitlint rejects the word anywhere in the title |
T7 title-match-regex, B8 body-match-regex |
message_pattern, one regex over the whole message (CC001) |
T8 title-min-length |
subject_min_length (CC005) |
B5 body-min-length, B6 body-is-missing |
require_body (CC011); there is no minimum length |
M1 author-valid-email |
the check-author-email hook (CC102), with author_email_pattern |
CT1 contrib-title-conventional-commits |
conventional_commits, on by default (CC001) |
CC1 contrib-body-requires-signed-off-by |
require_signed_off_by (CC012) |
CC2 contrib-disallow-cleanup-commits |
allow_fixup_commits = false (CC009) |
I4 ignore-by-author-name |
ignore_authors |
| merge, revert, fixup commits ignored | the format rules already skip the subjects git writes; CC006, CC007 and CC009 decide whether they are allowed |
| T2–T4, T6 whitespace and tab rules, T3 trailing punctuation, B1–B4 body line rules, B7 changed-file mention, user-defined Python rules | no equivalent |
The last row is the honest gap: if your policy depends on body line length or a custom rule written in Python, gitlint still does that and Commit Check does not. What you gain is the rest of this page: branch names, authors, the Action, the App, and a release that is current.
Which to choose¶
- You want the pull request title checked and nothing else:
action-semantic-pull-request. - You are in a JavaScript repository with husky and want plugins: commitlint.
- You need sign-off with a remediation flow: the DCO app, or DCO-2.
- You rely on gitlint's body line rules or your own Python rules: gitlint.
- You want one policy for messages, branches and authors, the same everywhere a commit is made and checked, with a hosted option that needs no workflow file: Commit Check.