Commithelper
A tool to create and lint commit messages. It has two modes prompt
and check
. The former asks you questions to create a well-formed commit message, while the latter lints a given commit message.
Table of contents:
Usage
First add commithelper
as a dev dependency to your project with npm install commithelper --save-dev
.
commithelper prompt [--file <path>] [--config <path>]
Interactively asks the user questions to create a commit message. Use the --file
option to specify a path to write the final message to. If omitted the message is printed to stdout. If the path already contains a file that only contains comments (lines starting with #
) this file is overwritten, but all comment lines (starting with #
) are kept. If the path contains a file with non-comment lines no questions are asked and program exits sucessful. This is useful when other tooling is creating the commit message or when using git commit --amend
. Use the --config
option to specify where to find the config file. If this is omitted, the config is read from the commithelper
field in the package.json
.
commithelper check [--file <path>] [--fix] [--config <path>]
Lints a commit message according to the configuration. Use --file
to specify where to find the file containing the commit message. If omitted the message is read from stdin. Use --fix
to try to automatically fix the commit message to pass linting. This means it will correct capitalization of the subject and correctly wrap the body of the message. Use --config
to specify where to find the config file. If this is omitted, the config is read from the commithelper
field in the package.json
.
It is recommended to use git hooks with this tool. There are several npm packages that help you set up git hooks automatically, e.g. husky or ghooks.
Use the prepare-commit-msg
hook with the prompt
mode to interactively create a commit message and use the commit-msg
hook for the check
mode.
Comparison with other tools
commitlint
The commitlint package and its plugins are only suited to check an existing commit message against a set of rules. While there is @commitlint/prompt-cli
, it just states that the commits have to have the form <type>(<scope>): <subject>
without telling you what the valid options are, so it is pretty useless.
Also it is very complicated to configure as many rules available are barely documented at all.
commitizen
The quesions in the prompt
mode of commithelper
is heavily inspired by commitizen. But commitizen can't lint an existing commit message, so if the user is using the git client built into their editor or provides the message with git commit -m
commitizen can't help.
Also, by default commitizen requires one of several adapters, each with their own configuration options which makes setting it up quite complicated.
Setup
Setup with ghooks
Install ghooks in your project with npm install ghooks --save-dev
. Then add config.ghooks
to package.json
like this:
{
…
"config": {
"ghooks": {
"prepare-commit-msg": "exec < /dev/tty && npm exec -- commithelper prompt --file $1",
"commit-msg": "commithelper check --file $1 --fix",
…
}
}
…
}
Setup with husky
Install husky in your project with npm install husky --save-dev
. Then add a prepare
script to your package.json
that installs the husky hooks.
{
"scripts": {
…,
"prepare": "husky install"
}
}
Then add a new executable file .husky/prepare-commit-msg
with the content:
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
exec < /dev/tty && npm exec commithelper -- prompt --file $1
and a new executable file .husky/commit-msg
with the content:
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
npm exec commithelper -- check --file $1 --fix
Then run npm run prepare
to install the hooks in your project.
Config file
You can either have a seperate json file and use the --config
option to point commithelper
to it, or omit --config
and add a commithelper
field in your package.json
. The config object has the following fields:
key | type | default | description |
---|
subjectLimit | number | 100 | The maximum number of characters that the git subject line (first line of the commit message) is allowed to have. This is including the type and the scope |
subjectSeperator | string | ':' | The character to seperate type and scope from the subject. E.g. with '/' the message would look like <type>(<scope>)/<subject> . May not be the empty string |
typePrefix | string | '' | A string that is added before the type , e.g. with '[', the message would look like [<type>(<scope>): <subject> |
typeSuffix | string | '' | A string that is added after the type , e.g. with ']', the message would look like <type>](<scope>): <subject> |
types | (string | { name: string, message: string })[] | default names: ['feat', 'fix', 'chore'] | All the commit types that are allowed for this repo. name is what will be at the place of <type> in the commit message, message is the explanation presented to the user during prompt mode |
scopes | (string | { name: string, message: string })[] | [] | All the scopes that are allowed for all of the commit types |
scopeOverrides | { [type]: (string | { name: string, message: string })[] } | {} | Override the allowed scopes for a particular commit type . If this is set for a particular type the array defined here is used as allowed scopes instead of the array defined in the scopes option |
allowCustomScopes | boolean | false | Set this to true if the user is allowed to write out a scope that is not on the list of allowed scopes |
bodyWrap | number | 72 | The maximum line length that is allowed in the commit body, wraps the body accordingly with --fix or in prompt mode |
ticketPrefix | string | 'ISSUES CLOSED:' | The string that marks the list of tickets that this commit closes. May not be the empty string |
ticketNumberPrefix | string | '#' | A string that is in front of the ticket number. The default is useful for GitHub issues which start with # (e.g. #134 ). Use e.g. 'JIRA-' for other numbering systems |
ticketSeperator | string | ',' | The string which is used to seperate multiple ticket numbers in the same line |
breakingPrefix | string | 'BREAKING CHANGES:' | The string that should start the description of a breaking change. May not be the empty string |
breakingRequiresBody | boolean | false | Set this to true to require a commit with a breaking change to also have a body in addition to the note describing the breaking change |
allowBreakingChanges | string[] | ['feat', 'fix'] | The commit types that are allowed to have breaking changes. Use the empty array to allow breaking changes for all types |
upperCase | boolean | false | Set this to true to require the first letter of the <subject> to be upper case (requires lower case when set to false ) |
skipQuestions | ('body' | 'breaking' | 'issuesClosed')[] | [] | Do not ask the user for a body, breaking changes or closed issues |