Writing better commits

August 01, 2022

Have you ever pushed a commit with a message:

fix
update 
fix34 - this should work... 
fingers crossed v13249

etc.?

Do you prefer using multiple commits per feature branch or do you squash regularly to achieve nice linear commit history? How about your teammates?

As you can see there are many possible approaches, but you could ask:

Why does it even matter?

When working with a team of developers it is a good idea to develop a common practise of messaging what is committed. Think about it as a brief explanation for others (including you a few months from commit being made).

Using established tools is always a great idea

My personal flavor is conventional commits. It’s well known, agreed-upon approach for writing commit messages in a form of:

<type>[optional scope]: <description>

[optional body]

On a daily basis the most useful types are:

  • feat - new feature, which corresponds to MINOR version bump (more on that later in the article),
  • fix - bugfix, which corresponds to PATCH version bump,
  • refactor - self-explanatory - no new features or fixes, just code quality changes for better DX,
  • chore - “other” unclassified changes,
  • ci - continuous integration changes.
  • perf - performance changes

Scope is optional, I usually fill it out with component name or service I’m working on.

Description should be a one line brief explanation of what and why.

If the scope is enormous I suggest filling out a commit message body with a WHY section and bullet points of what has been done.

refactor(DataTable): Unify param management.

WHY: Limit number of data requests.

- Simplify sortField method, as it always returned column.name.
- Use Order enum more consistently.
- Change scripts extension to .sh

Conventional commits can be easily used from command-line:

git commit -m "feat(Auth): Register User service"

or inside an IDE, as most popular ones offer a conventional commit plugins.

I also like to pair conventional commits with branch naming convention of feature/shiny-component and bugfix/what-was-wrong-description, but that’s just my personal preference.

The value added

There are multiple benefits of using conventional commits:

  1. Organization - lower decision fatigue, don’t have to think what to write and how to format a message, if a team member is in doubt can use official docs.
  2. Limit commit scope - if you happen to write very long and hard to review merge requests, conventional commits can help with deciding whether changes concern a new feature, a fix, performance change or refactoring.
  3. Improved releases - each commit type is connected with semantic versioning, so it can help with app releases and as a bonus commits can be used to generate automatic change log.
  4. Automatic PR description - repositories such as Gitlab format conventional messages as merge request descriptions.

Further reading:

  1. Official documentation
  2. Keep a changelog
  3. More on semantic versioning
  4. How to generate a changelog
  5. Tool for generating a changelog

Profile picture

Written by Jacek Malczyk software engineer based in Warsaw, clean coder, ReactJS enthusiast.

© 2022