3 Reasons Why You Should Use Conventional Commits
Published on November 20, 2023

Introduction

As a programmer, you might develop an application, a library, a microservice, or a monorepo full of services and libraries or (heaven forbid!) a huge monolith. No matter the type of application you develop, if you “do it right” you will use some version control (90% of the time it will be with git).

The question is – how do you manage your version history? How do you report bug fixing, feature addition, a chore done on the workspace, or even a breaking change? More importantly, how easy it is to see that?

Conventional Commits is a standardized approach to version control that enhances clarity, consistency, and collaboration among developers. In this post, we'll understand what Conventional Commits are, explore how they work, and explain the three main benefits you gain by using them.

Table of Contents

  1. What do Git Messages Looks Like Without Standards?

  2. What Does It Look Like With Conventional Commit?

  3. The Benefits of Using Conventional Commits

    1. Auto-Generated Changelog

    2. Auto Versioning According to SemVer

    3. Encouraging Better Communication in the Team

  4. Example From Production: Vivid’s Commit Message Standard

What Do Git Messages Looks Like Without Standards?

Standard Commit Examplestandard_commit_example

The picture above illustrates a common git commit sequence. It has a singular clear line which is good but leaves a lot of unanswerable questions. What can we tell from the commit messages? What does fix path mean? What path? In what component?

One cannot answer that just by looking at the commit history.

Nor can a machine do that. Remember that for later.

What Does It Look Like With Conventional Commit?

Comparatively, here's how commit messages look like according to the Conventional Commit standards:

Conventional Commit Exampleconventional_commit_example

By just looking at the first two pieces of information in each commit, we already learn so much. Going from bottom to top, we can see that a feature was added to the fab component, fixed something in typography, added a feature to the date-picker, did some chore in the docs, another feature related to accordion item, and so on.

Wouldn't you agree that our commmits are now clearer and more descriptive about changes in each push?

But developers don’t usually spend a lot of time looking at commit messages, right? Let’s see the real power of Conventional Commits.

The Benefits of Using Conventional Commits**

There are three main benefits to conventional commits: auto-generated changelogs, auto-versioning, and improved team communication.

1. Auto-Generated Changelog

There are many tools around that can generate a change log according to conventional commits. A changelog looks like this:

Example of Vivid's Auto Generated Changelogvivids_auto_generated_changelog

Did you notice how Conventional Commit standard already turns regular commmits into an easy-to-read change log? It even splits it into versions with dates to track down any new feature and bug fixes.

How can it know the version? This is the next benefit.

2. Auto Versioning According to SemVer

The Conventional Commit standard has the following structure:

{type}({scope}): {description}

The type is what kind of change was done. There are 3 main types: features, fixes, or chores.

The scope refers to the thing being impacted by this change. This can be a component, a library, an app, or a service.

The description describes more specifically what was changed.

That’s the gist of it. I’m not going to bore you with the full specifications, but I suggest reading it. It’s short and makes sense.

So, how does this help us with versioning?

SemVer is a way of versioning our software. The version is comprised of 3 digits: X.Y.Z.

X is called Major, Y is called Minor, and Z is called Patch.

When you do a breaking change, you raise a major version. That means the interface of this scope changed.

When you add a new feature (without breaking existing ones), you raise a minor version.

When you fix some bug without a feature and without breaking anything, you raise a patch version.

See where we are getting at?

Now a machine can read our commits and decide what version our scope should receive.

And you don’t have to do it yourself. Because Conventional Commits is a standard, many tools exist that provide auto changelog, auto versioning, and usually both.

One such tool is [release-please](https://github.com/googleapis/release-please), which also has a handy [github action](https://github.com/google-github-actions/release-please-action).

Encouraging Better Communication in the Team

In addition to commit messages being more readable, defining the structure gives us something else. It gives the commit message context. Even if the description is meh, because the type of the commit and its scope are well understood – the reader can at least anticipate what’s coming.

Take a look at this example:

Standarized Commits Still Lack Communicationstandarized_commits_example

Here is an attempt at standardisation. Still, a human looking at it cannot understand what type of change was done (is this a fix or a feature?) nor to what component. A change log cannot be inferred from this either.

If we change this a bit, it will look like this:

This isn’t much better, because the description isn't descriptive.

Then again, if one has to write the commit with fix(button): {description} it is less likely this person would write such a description. It is more likely a person would describe the fix or feat done on the button.

As usual, having some standards helps people do things better. It’s somewhat like the broken window theory.

Try it. See what happens.

Example From Production: Vivid’s Commit Message Standard

We are using Conventional Commits in Vonage's design system, Vivid.

It helps us generate our changelog and release log and auto-determine the release version.

In addition, our commit messages have been much better ever since.

But our conventional commit enforcement is not on each and every commit. During development, a developer can add as many commits as one likes with any message.

When someone creates a pull request (PR), though, we enforce a Conventional Commit on the pull request’s title:

Github Commit Title Lintergithub_commit_title_linter

A mandatory github action that verifies our PR title follows Conventional Commits

We’ve added another standard that helps us connect the commit to a JIRA ticket. Every PR title ends with (VIV-XXX) where XXX is the issue number. For example:

fix(disabled): adds a consistent cursor to disabled elements (VIV-999)

Eventually, in our release log, the VIV-XXX turns into a link to JIRA:

Convetional Commits With Jira Linksconvetional_commits_with_jira_links

Eventually, when a PR is merged, the PR title is set as the commit. We use squash + merge so all commit history is removed from the main branch and only the Conventional Commit remains. It looks like this:

Github Squash and Merge Buttongithub_squash_and_merge_button

If a pull request has more than one change (more than one fix or feature), one can always add them in the merge commit’s comments. We do it like this:

PR With Multiple Commitspr_with_multiple_commits

The Conventional Commit tool (in our case, release-please) will consider these comments as if they were part of the message.

This way, we take a relatively lax approach in regard to commit messages, making sure that the last step would be to actually describe the change.

Summary

Conventional commits give us two straightforward benefits: an auto-generated changelog and auto versioning.

There are many ways to achieve these goals.

One such tool is Beachball. This tool uses a CLI that generates a JSON file instead of reading git history. The big advantage here is that it is much easier to change the history if one made a mistake (changing git history can be quite messy…).

Aside from these two clear and immediate benefits, I claim it also helps encourage people to write better commit messages.

I might be wrong 🙂 Let me know on our Vonage Community Slack or send us a message on X, formerly known as Twitter.

Additional Resources

Design Systems: Lessons From Vivid

How Software Testing Can Contribute To Communication

An Introduction To Git

Yonatan KraVonage Software Architect

Yonatan has been involved in some awesome projects in the academy and the industry - from C/C++ through Matlab to PHP and javascript. Former CTO at Webiks and Software Architect at WalkMe. Currently he is a software architect at Vonage and an egghead instructor.

Ready to start building?

Experience seamless connectivity, real-time messaging, and crystal-clear voice and video calls-all at your fingertips.