- September 17, 2021
- 5 min read
Creating A Detailed Commit History With Conventional Commits
Use Conventional Commits to write a detailed git history that's easy for humans and tools to read, enabling automated changelogs and semantic versioning.
THE PROBLEM
Introduction
In short
- Conventional Commits provide a structured format that makes commit history easy for humans and systems to understand.
- The format requires a type and description, with optional scope, body, and footer, enabling programmatic changelog generation and semantic versioning.
- Starting with just feat and fix types makes adoption easier, and IDE extensions help guide the workflow.
Have you ever looked at your git log to get a sense of a branch's status only to be met with a wall of ticket numbers? Or have you had to determine a version for your upcoming release while manually maintaining a changelog? One of the best things we can do for our future selves is to write good commit messages. They allow us to keep track of changes and communicate the status of the repository to other team members. A popular approach is to add ticket numbers or other identifiers to the commit message. That will help us eventually track down what is happening in a repository but that kind of information is really meant for your project and issue tracking integration. Alternatively, adding a detailed commit message is also helpful but reduces our ability to scan the log to get our overview if too verbose. To make these tasks easier on ourselves we can follow a few simple rules.
CONVENTIONAL COMMITS
To The Rescue
Conventional Commits provide us with a specification centered around helping us write a detailed commit history that is easy for both humans to understand and other systems to digest. This more structured history gives us the ability to get that overview we were looking for at a glance with the added bonus of allowing us to programmatically generate changelogs and determine our next semantic version with additional tools.
FORMAT
Structurally Sound
Below is the Conventional Commit format and structure:
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]
Though this looks like it would make commits more complicated the only required pieces of information are the type and description. The type describes the intent of the changed code and the description summarizes the change. There are even specifications for formatting descriptions but that isn’t mission-critical to our current discussion. At the end of the day, we are just labeling or categorizing our commit. Is it fixing a bug? Use the fix type. Does this commit include a new feature? Then use the feat type. Using these two types alone already adds a layer of valuable information to our commit messages. If you’d like to detail what part of the application or system is being updated, reference that section in the scope slot. Not only will you quickly add more information to the commit message but tools like Lerna can use this content to track changes of packages in a monorepo. The body stores a more detailed summary of our changes and the footer is a great spot to call out related tickets, references, and/or acknowledgments.
COMMIT TYPES
More On Types
Thanks to tools like @commitlint/conventional-commits (based on the Angular convention) we have other types available to us to develop some granularity in our commit logs. Though these can be modified to meet your specific needs, below is a list of common types we can use to categorize our commits:
● build: Changes that affect the build system or external dependencies (example scopes: gulp, broccoli, npm)
● ci: Changes to our CI configuration files and scripts (example scopes: Circle, BrowserStack, SauceLabs)
● chore: A change that doesn’t have an effect on code and doesn’t meet the other type requirements (changing .gitignore)
● docs: Documentation only changes
● feat: A new feature
● fix: A bug fix
● perf: A code change that improves performance
● refactor: A code change that neither fixes a bug nor adds a feature
● test: Adding missing tests or correcting existing tests
Here are a few examples of how these types can be used with the conventional commit...convention:
● feat: add a new feature
● fix(utils): fix a bug in utils
● feat!: breaking change in API
● chore(deps): update dependencies
With the addition of these other types to the start of our commit messages, we’re able to provide a wealth of information to our commit log.
TOOLS & ADOPTION
The Remembering
I know what you’re thinking. I’m already following guidelines and specifications to complete my functional code, why should I use another one just to write commits! There is a bit of a learning curve and adjustment, at least there was for me, when I started using this convention. I suggest starting by just adding the feat or fix type to the start of your commit messages. Those 2 types should meet the majority of our use cases. Then start sprinkling in others like docs, test, and chore if the production code isn’t changing. There are also great tools and extensions we can use to help us write commits using this convention. Here are a few extensions for our IDEs:
Visual Studio Code
● Conventional Commits
● Commitizen Support
IntelliJ (JetBrains)
● Conventional Commit
There are also command-line tools like this one by commitizen that help us generate a commit message through a guided workflow and a commit linter to make sure the project adheres to the specification with something like husky and commit hooks.
RESULTS
Wrapping Up
After adopting just the required pieces of the standard, type, and description, I noticed that my commits became more deliberate and methodical. The footer stores ticket references for integration and pipeline purposes and I occasionally use the body to summarize a large feature or to describe breaking changes. Repository maintenance and git operations became easier and later phased out manual changelog management by using conventional changelog. Something that is worth pointing out too is that the entire team doesn’t have to conform to this standard either. If you aren’t opposed to squashing commits then team leads can take care of maintaining the standard. Check out Conventional Commits to read more about the specification to see if this is right for you or your team. There is an excellent FAQ section there that addresses many concerns and has additional information regarding usage with existing projects.
KEEP READING
Related Resources

Case Study
Custom Scheduling Platform for a National Specialty Pet Retailer
A new platform on AWS Lambda, API Gateway, and Aurora cut page load from 20 seconds to 1.5 and adds $800K a week in completed grooming appointments.
Read the pet retailer case study
Case Study
Leveraging GenAI to Empower JBS Dev's Sales and Delivery Teams
How JBS Dev used generative AI to share project knowledge between its sales and delivery teams and improve internal collaboration.
Read the case study
Case Study
Custom Retail Storefront for Moda Operandi
The new site and mobile app launched, and first-year revenue beat the forecast.
Read the Moda Operandi case study