Development teams frequently use the Git version control system when they work on a project. Therefore, it is important to observe and follow certain conventions so that you don't confuse others. One of these conventions focuses on how to write commit messages. After all, this is how someone can tell their co-workers about the changes made to the code. One of these conventions is the Conventional Commits specification. Based on this convention, commits are short and include useful information about the changes made. In this topic, we will discuss the correct way to write commit messages according to the Conventional Commits specification.
Remember that your company may have its own commit messaging rules. In this topic, we will only discuss some generally accepted recommendations.
Conventional Commits specification
Conventional Commits is a standard for making commit messages' meaning more accessible for people. This also makes it easier for developers and third-party contributors to navigate changes to the code. It offers a straightforward set of guidelines for developing an explicit commit history. The Angular Commit Guidelines is a major source of inspiration and the foundation for the Conventional Commits specification.
Besides the fact that this specification makes messages more readable for developers, it also simplifies writing automated tools on top of it. For example, creating automated tools that will generate changelogs or do some analysis based on the messages.
The latest version of the convention is 1.0.0 and all the peculiar properties mentioned here are related to this version.
Commit message structure
Like any rule, Conventional Commits specification has its own structure. The generally accepted style of writing commit messages has the following structure:
<type>[(scope)][!]: <description>
[body]
[footer]Type — Of the many types of commits, the main types are
featandfix. But there are alsobuild,chore,docsand others. You will learn about each of these types a bit later.Scope (optional) — Scope describes the part of code or documentation that is affected by the changes made by this commit. For example:
api,parser, etc. Indicated in parentheses. You can identify multiple scopes that can be separated by,,/and\.Exclamation mark (optional) — The exclamation mark is used to emphasize the importance of the commit. You should also include the
BREAKING CHANGEfooter. It describes the important changes made in the commit.Description — This part includes a short description of the changes made. The description length is usually one brief sentence.
Body (optional) — In this part, the changes are described in more detail. You are allowed to write a couple of small paragraphs.
Footer (optional) — Typically, includes
BREAKING CHANGEas it was said before. This footer explains the significant changes that were made. Such changes significantly affect the architecture of the application and should be taken into account as a matter of urgency.
Each footer must begin with a word token and should be followed by either :<space> or <space># separator, and then end with a string value. This is inspired by the git trailer convention, which provides a similar structure.
Now let's look at some examples. The shortest commit message may look like this:
fix: /users api endpoint error fixHere is the commit message that describes the scope where changes have been made:
feat(api): add /documents endpoint An example of an important commit with BREAKING CHANGE footer:
chore!: drop support for Node 6
BREAKING CHANGE: use JavaScript features not available in Node 6.Now let's take a quick look at the main commit types.
Commit types
According to the Conventional Commits specification, there are two main types of commits:
feat (Feature) — Use when new functionality gets added to the application.
fix (Fix) — Use when changes made by a commit fix errors in already existing parts of the application without changing its functionality.
But sometimes these two types are not enough to cover the changes we made. So there are also other types that are used by the community and supported by linting tools:
build (Build) — Use to make changes to the build system or external dependencies that are required for the application to work.
chore (Chores) — Use when changes are not related to the operation of the application.
CI (Continuous Integrations) — Use when changing the continuous integration configuration.
docs (Documentation) — Use when changing the documentation, such as typo fixes, adding languages, etc.
perf (Performance) — Use when making changes aimed at improving the performance of the app.
refactor (Refactoring) — Use when there are changes in the structure of the code that don't affect the functionality.
revert (Reverts) — Use for a commit that reverts the previous changes that have been made by mistake or with some violations.
style (Style) — Use for changes in the style of the code, without changing its structure (adding/deleting whitespace/newlines, etc.).
test (Testing) — Use when changing the testing system like adding new tests or changing old ones.
Maybe it was a lot, right? But by using all these types in practice, you will easily remember them and they will work as a guide. In the next section, you will see the command line plugin that can help you write commit messages.
Commitlint
Commitlint is a simple tool for listing commit messages. It makes sure that your messages comply with the established set of rules and suggests changing errors. You can visit the official website of this tool to find guidelines and installation instructions.
Commitlint can be installed using Node Package Manager (NPM) via this command:
npm install @commitlint/cli @commitlint/config-conventionalThen you need to create commitlint.config.js file in your project directory and add these lines to the file:
module.exports = {
extends: [
"@commitlint/config-conventional"
],
}This makes it clear to the utility that you will use conventional commits config. Then you need to install husky and enable its hooks so that commitlint can run while making commits:
npm install husky
npx husky installAnd the last step — you need to add a pre-commit hook to run commitlint before the commit is done:
npx husky add .husky/commit-msg "npx --no -- commitlint --edit $1"And that's it, you can use commitlint! Let's try to make some unconventional commits and see how commitlint reacts to them.
git commit -m "abc: unconventional commit message"husky > commit-msg (node v10.1.0)
No staged files match any of provided globs.
⧗ input: abc: unconventional commit message
✖ type must be one of [build, chore, ci, docs, feat, fix, perf, refactor, revert, style, test] [type-enum]
✖ found 1 problems, 0 warnings
ⓘ Get help: https://github.com/conventional-changelog/commitlint/#what-is-commitlint
husky > commit-msg hook failed (add --no-verify to bypass)As you can see, commitlint warns about the mistakes and does not allow you to execute the commit.
But if you correct your message:
git commit -m "feat: login page add"The commit will be successful.
Conclusion
In this topic, we discussed that commit messages have rules that you need to obey called Conventional Commits. You are familiar with the structure of writing messages and the types of commits. Also, you got acquainted with Commitlint — a useful tool that will help you write commit messages. This information will be useful to you, and you can follow these rules even if you do not work on large projects for big companies yet.