Conventional Commits - Specification for Your Commit Messages
Tags: git, productivity, programming, javascript
Published: 2023-02-02 11:18:31

> This content was originally published in spanish on [my blog](https://carlosazaustre.es/conventional-commits)

## What are Commit Messages?
Commit messages are a way of documenting changes made in a code repository.

These messages are very useful for understanding what changes were made in a project and why they were made.

When working in a development team, it is very important that all team members can understand what changes were made to the code and why they were made.

## Conventional Commits
{% embed https://www.youtube.com/watch?v=SigVVJmUGv8 %}

As stated on their official page: It is a specification
for giving meaning to commit messages making them understandable both for machines and for people. 

It provides a simple set of rules for creating an explicit commit history; which makes it easier to write automated tools. 

This convention fits with SemVer, since we can explain in the commit messages if it's a feature, bugfix, even if there are *Breaking Changes*.

If you were unfamiliar with the term Semantic Versioning, in this short video I'll explain it to you:

{% embed https://www.youtube.com/watch?v=k_nV7ExQdw4 %}

The structure of a commit message following the specification would be as follows:

```
<type>[optional scope]: <commit description>

[message body, optional]

[footer(s), optional]

```

## Commit Types

The commit types are as follows:

- **feat**: A new feature or functionality. It would have correlation with a MINOR version following *SemVer*.

- **fix**: A corrected error. It would have correlation with a PATCH version following *SemVer*.

- **BREAKING CHANGE**: A change that contains this word in the message footer or a ! sign after the type or scope,
breaks compatibility with previous versions. It would have correlation with a MAJOR version following *SemVer*.

The following types are also allowed:

- **build**: Changes that affect the build system or external dependencies (e.g. changes to the package.json).

- **ci**: Changes to our continuous integration configuration files and scripts.

- **docs**: Changes to documentation.

- **chore**: Other changes that do not affect source code.

- **perf**: A code change that improves performance.

- **refactor**: A code change that does not correct an error or add a feature.

- **style**: Changes that do not affect the meaning of the code (whitespace, format, missing commas, etc).

- **test**: Add missing tests or correct existing tests.

### Scope

The scope is optional and serves to specify the scope of the commit. For example, if we are working on a monorepo project, we can specify the package we are modifying.

### Examples

Let's see some examples of commit messages following the specification:

**Commit that adds a new feature, without a specific scope.**
```
feat: add support for TypeScript
```

**Commit that fixes a bug, within the ui package of our project.**
```
fix(ui): bugfix on Button component
```
**Commit that breaks compatibility with previous versions, although it doesn't add new features or fix bugs.**
```
chore!: drop support for Node 6

BREAKING CHANGE: use JavaScript features not available in Node 6.
```

**Commit that adds missing tests.**
```
test(ui): add missing tests for Button component
```

**Commit that adds a task for the continuous integration/deployment system.**
```
ci: add GitHub Actions workflow
```

**Commit with a long descriptive message and multiple footers.**
```
fix(api): prevent duplicate users from being created

This commit fixes a bug where the API would allow duplicate users to be created with the same email address. This commit also adds a new `unique` constraint to the `users` table to prevent this from happening in the future.

Paired with: X
Fixes #123
```

## Why use Conventional Commits?

- It allows for automatic generation of the CHANGELOG file.

- Automatically determines version changes following SemVer (based on the types of commits used).

- Communicates the nature of changes to other team members or anyone interested.

- Activates build and deployment or publishing processes.

- Makes it easier for others to contribute to the project by allowing them to explore the commit history in a more structured way.

## Tools to use Conventional Commits

### VSCode Plugin

The first one I use is the VSCode extension or plugin, [Conventional Commit](https://marketplace.visualstudio.com/items?itemName=vivaxy.vscode-conventional-commits). It helps me choose the type of commit, the scope, write the message,... all based on dialog windows.

### Gitemoji

To make our commits more colorful, we can use the [Gitemoji](https://gitmoji.dev/) convention. It's a convention where
emojis represent the type of commit. For example, the emoji 🐛 represents a bugfix, ✨ a new feature, etc... So with a quick glance you can see what type of change has been made.

### Commitlint
[Commitlint](https://commitlint.js.org/#/) is a tool that allows us to configure rules to validate commit messages.
Just like we use a linter to check if we follow certain style rules in our code, we can use it for commit messages.

For this, you need to install the `@commitlint/cli` and `@commitlint/config-conventional` libraries in your project.

```
npm install --save-dev @commitlint/cli @commitlint/config-conventional
```

Once installed, you must create a configuration file called `commitlint.config.js` in the root of your project with the following content:
```javascript
module.exports = {
  extends: ["@commitlint/config-conventional"],
};
```

### Husky
We already saw [what Husky was used for in a previous post](https://carlosazaustre.es/husky-lintstaged). Now we will add a new rule to the `pre-commit` hook to verify and validate if the commit message complies with the Conventional Commits rules.

If you already have Husky configured, all you have to do is run the following command in the root of your project to add the command to the `commit-msg` hook:

```
npx husky add .husky/commit-msg  'npx --no -- commitlint --edit ${1}'
```

And that's it, every time you make a commit, it will verify that it follows the rules.

### CHANGELOG

Finally, it is also interesting to be able to automatically generate the CHANGELOG file from the commit messages. There are various tools for this, one of them is [Conventional Changelog](https://github.com/conventional-changelog/conventional-changelog)

---

Hope this is helpful ✨

---

Do Like 💛 & Save 🔖

---
Do **Follow** me on [Twitter](https://twitter.com/carlosazaustre) and [Linkedin](https://linkedin.com/in/carlosazaustre) for more content related to Web Programming and JavaScript

![Carlos Azaustre on Twitter](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/r3me5n5aghext9ano5ap.png)