For the complete documentation index, see llms.txt. This page is also available as Markdown.

Commits

Lint the log with the same tool that lints the docs: a convention for the subject, body, and trailers, spelling on the body, and a hook that stops a bad commit.

A commit message has a subject, a blank line, a body, and trailers, and every project has rules about each. Commits is a package of those rules: the conventions people follow, Conventional Commits, Angular's format, gitmoji, Emoji-Log, the seven rules, the Linux kernel's patch format, the Go project's, a Jira key, and the rule sets of the linters people run, commitlint, gitlint, committed, conform, and commitizen, each transcribed rule for rule. A textfsm View reads the message into its parts, so a rule reaches the subject the way it reaches a heading.

Requires Vale v3.21.0 or later.

Install

The package is in the library, so its name is enough:

StylesPath = styles
Packages = Commits

[COMMIT_EDITMSG]
BasedOnStyles = Commits, Conventional
$ vale sync

The package brings the section, the View, and Commits, the core every convention shares: a blank line after the subject, the imperative mood, no whitespace at the edges, no fix or wip for a subject. You name the convention beside it.

Style
Enforces

Conventional

The specification, and only it

Commitlint

commitlint's rules, with config-conventional's on; goes with Conventional

Angular

Angular's guidelines; goes with Conventional

Gitmoji

One of the 75 gitmojis first, then a message

EmojiLog

One of Emoji-Log's seven labels

SevenRules

Chris Beams's seven rules: 50 characters, a capital, no period, the body wrapped at 72

Kernel

Subsystem prefix, 75 columns, Signed-off-by:, the Fixes: and Closes: tag forms

Go

Package prefix, no capital, Fixes #123

Jira

An issue key in the subject

Gitlint

gitlint's built-in rules at their defaults

Committed

committed's defaults

Conform

conform's commit policy

Commitizen

cz check's schema; goes with Conventional

Levels and toggles work as they do for any rule, and a limit is a parameter set with the bracket key:

A rule a tool leaves off by default, commitlint's scope-enum or references-empty, is off here too; Commitlint.References = YES turns it on. Each rule file in the package's styles opens with what it reports and why, carries its level, and links the passage it enforces. A guide per tool, commitlint, gitlint, committed, conform, and commitizen, maps that tool's config to the rules here.

The hook

A commit-msg hook receives the path of the message file. Vale reads it on stdin, and --path names the section that applies, since the text has no name of its own:

Vale exits non-zero on an error-level alert, so the commit stops with the alerts on screen. Lines Git adds as commentary, and the diff commit -v appends, are never seen by a rule. The package's script/commit-msg is that hook with two additions: messages Git writes itself, merges, reverts, and the fixup! and squash! that autosquash reads, are let through, and on a fresh clone it runs vale sync once, when the StylesPath has no Commits in it.

Git keeps .git/hooks outside version control, so a hook copied there protects one clone. To ship it with the repository, put it in a tracked directory and point core.hooksPath at it, once per clone:

A prepare script in package.json or a make setup target runs that for every contributor. The hook runners do the same thing under the hood, with husky, lefthook, or the pre-commit framework:

CI and pull requests

Because the message comes in on stdin, the same command works on what was pushed, on each commit of a pull request, and on the request's description:

Nothing on the server side can run a hook for a client, so the check in CI is the backstop for a clone that skipped the setup.

Output

The report can take the shape of the tool a team used before. The package ships templates, picked with --output by name once synced:

gitlint.tmpl, committed.tmpl, and conform.tmpl print those tools' forms, github.tmpl prints GitHub Actions annotations so an alert lands on the pull request at its line, and hook.tmpl is a short form for the terminal.

Spelling and the rest of Vale

The body is read as Markdown, so Vale.Spelling skips an identifier in backticks and catches a misspelling in prose, and any style already in use on the docs runs on the log with one line of config:

Your own rules

A rule reaches a part of the message by its scope, subject, gap, body, or trailer, and a rule that spans two parts is a conditional whose in names the second:

To change a list a rule holds, the types a project accepts, extend the rule in a style of your own with the pattern rewritten, and turn the original off. The TextFSM guide is the View itself: how the template reads a message, and how the same approach reads a subtitle file or a transcript.

Last updated