When working on a project many people don't have the time to write meaningful commit messages. For me, I have to work with many other developers which involve reviewing their commits, reviewing merge requests, creating and fixing stuff, etc. And all that simultaneously for multiple projects. Often their commit message does not describe what changes did they did in that current commit, and I have to dig through their code to understand that, and it can be a nightmare sometimes.
Even if they write a good message, many people have their own style or convention of writing their commit messages. To solve this particular problem I started using commitlint
along with commitizen
so that my team adheres to a commit convention.
Sneak peek to the end result 👇
Step 1: Setup husky
and commitlint
Firstly, you will need husky
, which is used for writing git hooks. See More
Install husky
to your project.
npx husky-init && npm install
or, if you prefer yarn like me
npx husky-init && yarn
Next, we are going to install commitlint and commitlint-config-gitmoji
yarn add -D @commitlint/cli commitlint-config-gitmoji
or,
npm install --save-dev @commitlint/cli commitlint-config-gitmoji
The @commitlint/cli
will be used to check if our commit message follows the convention we configured for the project and the commitlint-config-gitmoji
is the commit convention preset we will be using. There are other conventions as well which you can use.
The commitlint-config-gitmoji
follows the below convention.
You need to provide a emoji (or gitmoji) then a type, following a scope (not mandatory), and then the subject, which is your actual commit message. You can add a body and footer too if you like.
:gitmoji: type(scope?): subject
body?
footer?
Example,
✨ feat(api): add middleware for user authentication
Now, we need to define the commitlint config for our project. Create a file named commitlint.config.js
and define your config given below.
module.exports = {
extends: ['gitmoji'],
rules: {
'header-max-length': [0, 'always', 100],
},
};
You can customize the rules of your commit message per you like similarly to eslint. See here
Step 2: Add commitlint
checking as a git hook
Next, we need to add commitlint
as a git hook using husky
to check our commit message before every commit. To do this run the below command.
yarn husky add .husky/commit-msg 'yarn commitlint --edit "$1"'
OR
npx husky add .husky/commit-msg 'npx --no-install commitlint --edit "$1"'
This will create a file named commit-msg
inside your project inside .husky
folder.
Note: husky
by default creates a pre-commit
file, which runs npm test
. If you don't have a test script defined in your package.json
it will throw an error. You can remove the npm test
line from the pre-commit
file or add a valid test script.
Now try to do a commit 😏
Well now my fellow teammates cannot commit unless they write a proper commit message 😈.
commitlint
prevents us from doing a commit if the commit message does not adhere to the structure provided by commitlint-config-gitmoji
.
Step 3: Adding commitizen
cli for composing commit messages
Coming to the last part, now we will create a CLI helper to generate the commit message using commitizen
. Also we are using cz-customizable
to customize the CLI helper.
yarn add -D commitizen cz-customizable
OR
npm install --save-dev commitizen cz-customizable
Next, add a commitizen config in your package.json
like below
{
....
"devDependencies": {
...,
},
"config": {
"commitizen": {
"path": "cz-customizable"
}
}
}
Now create a file in your root folder named .cz-config.js
to customize the options of the CLI helper, and paste the below config.
module.exports = {
types: [
{ value: ':sparkles: feat', name: '✨ feat:\tAdding a new feature' },
{ value: ':bug: fix', name: '🐛 fix:\tFixing a bug' },
{ value: ':memo: docs', name: '📝 docs:\tAdd or update documentation' },
{
value: ':lipstick: style',
name: '💄 style:\tAdd or update styles, ui or ux',
},
{
value: ':recycle: refactor',
name: '♻️ refactor:\tCode change that neither fixes a bug nor adds a feature',
},
{
value: ':zap: perf',
name: '⚡️ perf:\tCode change that improves performance',
},
{
value: ':white_check_mark: test',
name: '✅ test:\tAdding tests cases',
},
{
value: ':truck: chore',
name: '🚚 chore:\tChanges to the build process or auxiliary tools\n\t\tand libraries such as documentation generation',
},
{ value: ':rewind: revert', name: '⏪️ revert:\tRevert to a commit' },
{ value: ':construction: wip', name: '🚧 wip:\tWork in progress' },
{
value: ':construction_worker: build',
name: '👷 build:\tAdd or update regards to build process',
},
{
value: ':green_heart: ci',
name: '💚 ci:\tAdd or update regards to build process',
},
],
scopes: [
{ name: 'ui' },
{ name: 'android' },
{ name: 'ios' },
{ name: 'home' },
{ name: 'planner' },
{ name: 'settings' },
],
scopeOverrides: {
fix: [{ name: 'merge' }, { name: 'style' }, { name: 'test' }, { name: 'hotfix' }],
},
allowCustomScopes: true,
allowBreakingChanges: ['feat', 'fix'],
// skip any questions you want
skipQuestions: ['body'],
subjectLimit: 100,
};
Also, add a npm script to run the commitizen
cli.
{
"scripts": {
...,
"cm": "cz"
},
"dependencies": {
...
}
}
You can modify the config as per your choice. See here
Now run the script to see commitizen
in action.
yarn cm
OR
npm run cm
Ta-da, now you and everyone in your team can easily write beautiful conventional commit messages.
Top comments (4)
Liked your articled.
I standardized around cz-customizable which I found is a better alternative especially in standalone mode.
sorry.. I meant to say : that standalone mode for cz-customizable is great
Thanks a lot :)
Awesome.