iTranslated by AI
Conventional Commits: Basics and Supporting Technologies (commitlint + husky)
What is this?
This article summarizes the basic knowledge of Conventional Commits, a specification for unifying the format of commit messages, along with the know-how to smoothly advance development processes that incorporate it.
What is Conventional Commits?
Conventional Commits is a specification for providing a consistent set of rules for creating an explicit commit history. It is designed to be easily understood by both humans and machines, allowing for the description of concise yet clear commit messages. This not only makes it easier to track the evolution of a codebase later on but also facilitates integration with tools that automate release workflows and code reviews.
Basic Format
<type>[optional scope]: <description>
│ │ │
│ │ └─ Briefly describe the commit content
│ │
│ └─ Scope specifying the impact area of the commit (optional)
│
└─ Type specifying the kind of commit
feat: add new feature
fix(api): fix a bug
type
Among the types defined by the official Conventional Commits specification, the following two are representative:
-
fix: A patch for fixing a bug -
feat: Addition of a new feature
In addition to these, the following types are defined, allowing you to cover almost all types of changes:
-
docs: Documentation changes -
style: Changes in code style (e.g., adding semicolons, fixing line breaks) -
refactor: Code refactoring (excluding bug fixes or new feature additions) -
perf: Performance improvements -
test: Adding or correcting tests -
build: Changes to the build system or dependency updates -
ci: Changes to CI/CD configuration -
chore: Other changes
BREAKING CHANGE
Conventional Commits includes a special keyword called BREAKING CHANGE. By including this in the footer of a commit message, you can explicitly state that the commit introduces a breaking change to the existing code.
feat: add new feature
BREAKING CHANGE: this is a breaking change
Alternatively, you can use a ! after the type/scope to substitute for the BREAKING CHANGE keyword.
feat!: add new feature
feat(api)!: add new feature
Tools for checking commit messages
To incorporate Conventional Commits into your development process, it is effective to introduce tools that check the format of commit messages.
commitlint
As the name suggests, it is a linter for checking commit messages. You can configure Conventional Commits or your own message conventions to check if commit messages comply with the rules. In this article, I will introduce a setup to check messages for compliance with Conventional Commits.
npm install --save-dev @commitlint/cli @commitlint/config-conventional
# or yarn
yarn add --dev @commitlint/cli @commitlint/config-conventional
@commitlint/config-conventional is a package that provides the configuration for Conventional Commits. With this single package, you can easily implement the Conventional Commits specification. It fully supports the type definitions and BREAKING CHANGE checks mentioned earlier.
Next, create a configuration file. Write the following content in a file named commitlint.config.js in the root directory of your repository.
module.exports = {
// Reference the installed package
extends: ['@commitlint/config-conventional'],
};
Since it is a commit message, it is appropriate to check it at the time of committing. Therefore, we will build a mechanism where the commit message is checked upon execution of the commit by combining it with husky.
npm install --save-dev husky
# or yarn
yarn add --dev husky
Next, run the following command in the root directory of the repository to create the husky configuration file.
npx husky install
When the command is successful, a .husky directory is created in the root directory.
.
+├── .husky/
+│ └── _/
└── package.json
Husky configuration files are stored in the .husky/_ directory. These files are added to .gitignore by default, so they are not managed by Git. Therefore, you need to regenerate the husky configuration files every time the repository is cloned. To automate this task, add a prepare script.
{
"scripts": {
"prepare": "husky install"
}
}
The prepare script is a type of Lifecycle script that is automatically executed every time npm install is run. Therefore, the husky configuration files are generated in conjunction with the frequently executed npm install, preventing you from forgetting the setup.
Finally, configure husky to run the commit message check upon committing. Create the .husky/commit-msg file and write the following content.
.
├── .husky/
│ ├── _/
+│ └── commit-msg
└── package.json
npx --no-install commitlint --edit $1
Now, a Git hook called commit-msg will trigger upon committing, and the commit message will be checked. Let's actually commit and see if an error occurs.
# Entering an invalid commit message will cause an error and abort the commit.
git commit -m "add new feature"
⧗ input: add new feature
✖ subject may not be empty [subject-empty]
✖ type may not be empty [type-empty]
✖ found 2 problems, 0 warnings
ⓘ Get help: https://github.com/conventional-changelog/commitlint/#what-is-commitlint
# Entering a proper commit message will complete the commit without any issues.
git cm -a -m 'feat: add new feature'
[ci/commitlint 2aef98a] feat: add new feature
1 file changed, 2 insertions(+), 1 deletion(-)
Conclusion
Writing commit messages is a routine task in the process of software implementation, but its importance is rarely noticed. Especially in projects where small-scale and rapid development is required, commit messages tend to be neglected. This is because right after a commit, the changes are vividly remembered, making it hard to feel the need to record them in a message. However, commit messages are a crucial source of information for tracking the evolution of a codebase. If the format is inconsistent or the contents are unclear, it becomes difficult to trace the history of the codebase later on.
Conventional Commits is a very refined specification for unifying the format of commit messages. Additionally, many excellent tools exist to support it beyond those introduced in this article. We encourage you to adopt Conventional Commits and build a codebase that is easy to read and track for your future self and your team members.
Discussion
タイムリーでありがたい記事っす😁🙏