DEV Community

Cover image for Not πŸ’©, here's how to write actually good commit messages (hint: It's not just adding commit-lint)
Jayant Bhawal for Middleware

Posted on • Updated on

Not πŸ’©, here's how to write actually good commit messages (hint: It's not just adding commit-lint)

  • Update build file
  • Fixes dependency array
  • Refactor
  • Fix tests
  • The most famous: Update README.md (Thanks Github 🀦)

These are... some spectacularly amazing commit messages that I've actually seen in the last month. πŸ‘€
And... some of these are in our codebases too.
A bit embarrassing. I know. πŸ˜…

But this is not okay πŸ™…, and ideally I would want to rid the world of these.

"Sure, whatever. I don't think anything will change even after reading this blog."

For anything to change, I need to convince you that:

  • This makes a real difference that YOU can feel or measure
  • This makes a difference to someone else (which might be attributed to you later)

"Okay, get on with it. What do I do, and what do I get from it?"

Well written commit messages have some obvious benefits:

1. πŸ§‘β€πŸ’» Easier debugging

git blame makes it super easy to understand why a change was introduced, and makes it easier to ask the author relevant questions about it.

git blame isn't the first tool that's used during debugging, but for complex issues related to business logic, it's a tool that comes into play especially in medium to large sized companies. Some code simply evokes the question "Why was it written the way it was?" or "What purpose was this originally solving?". The answers to some questions don't lie in engineering, but in product decisions. And the author who wrote that has the best chance of knowing what decisions were involved.

Context-less debugging

Of course, git blame will tell you the author of a commit even without the need for fancy messages. So why is this part of this blog post?

Because how often do YOU as an author remember what a commit that you write 6 months ago was doing? Especially when it has a commit message like "Refactor"? Tough luck right?

I've seen more experienced devs write exceptionally helpful commit messages. I think some of them overdid it a little, but here's a rough example:

Fix crash on login screen due to null pointer exception.

- Checks for null values before accessing user profile data
- Adds unit test to cover this scenario
- Issue linked: BUG-5678
Enter fullscreen mode Exit fullscreen mode

Maybe it's a bit too much, but damn if it isn't obvious AF.
Now when I need to debug an issue in this area, being able to git blame for the author and context can be a lifesaver.
I say this with confidence because I used to be both on the giving and receiving side of this at Uber.

This has a serious added benefit which you might overestimate as you read this blog:

  • Saves time for you and your team, and reduces frustration

Debugging in the absence of context is PAIN. It's not even the kind where you can say "What doesn't kill you, makes you stronger." Because it just frustrates you.

You know it. Your team knows it. And that's why you try to understand who introduced "that bug" anyway and talk to them, only to find out they left the company 2 years ago. Good luck. 🀝

With this, you're leaving behind a legacy that would make people remember you fondly and wish they could work with you again.

"What if I use merge or squash commits?"

Some people have strong opinions for or against them.

All I'll say is, merge commits help to contain the context of a PR contained within a commit to a degree, but the individual commits themselves may not have much context associated with them if they are not well written.

And because a PR might involve a variety of dissimilar changes that work together to ship a feature, and the constituent changes might have their own context for being written that way, squashing them might effectively muddle all that context making it difficult to draw inference from the commit history.

But perfectly functional software is written either way. As long as you and your team agree that your way of merging PRs works for you with minimal issues, who I am I interfere?

2. πŸ” Easier code reviews

If your org doesn't care too much about making code reviews be painless and not make it feel like a chore, you need to share this with your people:

Now, how do better commit messages help with code reviews?

From Middleware's analyzed data, an average PR in a mature codebase (active repo, past its setup phase) can be around 300 lines.

That's a lot of lines. And most of these changes are not happening in the same file. Neither should they. 300 lines is on the upper end of a file being readable (it's not a rule set in stone though).
It's a near-guarantee that different kinds of changes are being shipped in these PRs that NEED to go together for the desired functionality to be shipped.

If you can't make a smaller PR for any reason, you can make smaller commits in the same PR. Make each commit contain the smallest piece of logically isolated change, such that the commit message can sufficiently explain what it contains. Because you don't want to write a commit message that's a paragraph long either, you'll need to create a commit that's small enough that roughly 50-60 characters can explain what it's about.

Now, the reviewer can review your PR commit by commit without having to follow up with you for everything or wondering why something was written the way it was (if they do, they'll have to ask you [the author], you know? Do you really have much time for that?).

Meaningful commit messages

3. πŸš€ Better release notes!

Or if you're not generating "release notes" exactly, then it's still better documentation of the history of your project!

Github, specifically, also allows you to generate release notes for your project automatically from your commits. And release notes are seen by a LOT of people to get an idea of what fixes or features new releases contain.

See the releases section of the React codebase, and see how many reactions each release note has!

React release notes

Clearly release notes matter to people. And by writing well written commits, you're saving yourself effort from writing release notes.

And finally...

4. πŸ‘₯ Encourages better practices across the team

Use the force Luke

When team members see the benefits of well-written commit messages, they are likely to follow suit. This can lead to a more disciplined approach to code commits across the entire team, encouraging a culture of clarity and precision. This is the kind of stuff that makes an SDE1 act think and act like an SDE2.

Here's another example of such a commit:

Update permissions routing layer to handle subroutes independently.

- TKT-1234
- The permissions routing logic was previously coupled with its nested routes
- This change will allow you to move subroutes to any other parent route without also having to make any changes to how the permissions for that subroute are defined
Enter fullscreen mode Exit fullscreen mode

In environments where multiple people work on the same project, consistent and detailed commit messages can align everyone's understanding and expectations, reducing potential conflicts and misunderstandings, without needing as much time to block for context sharing.

And of course, if you can be the champion of better commit messages in your team or organization, you'd love to get the credits for any benefits that brings, won't you? πŸ‘€

Teams that can work asynchronously, is a team that can work efficiently. No one wants your teams to have bottlenecks on stuff like this. πŸ‘Œ

UPDATE:
I really should have covered this earlier, but if you're convinced about the idea of using good commit messages and are using it in some form regularly, you might be ready to take the next step.

The next step would be to have a standard way and structure of writing commits in your org. Adhering to standards can involve a bit of a friction in your experience, but it can prove to be fruitful in the long term.

Presenting, Conventional Commits!
Thanks @taosif7 for reminding me of this!

GitHub logo conventional-commits / conventionalcommits.org

The conventional commits specification

ConventionalCommits.org

Conventional Commits

This repo is the home of the Conventional Commits specification.

Repo Layout

We use HUGO as static site generator, so we use the directory structure HUGO proposes.

Our implementation

  • ./content: contains all the versions of the specification.
  • ./content/next/: contains the version of the specification (where all the changes SHOULD be made).
  • ./content/**/index.[lang].md: contains the content of the specification, if a language is specified it's a translation.

Contributing

We'd love your help refining the language of this specification, fixing typos, or adding more translations. Please don't hesitate to send a pull request.

Adding a translation

  1. Create a new file in ./content/version/index.[lang].md using the hugo command hugo new [version]/index.[lang].md.
  2. Ensure all files have the appropriate fields required (see others as an example)..
  3. Add the language to the config.yaml file (see others as an example).

Running project locally

There's a docker-compose.yml file ready that will help you to…

Conventional Commits is a specification for writing great commits in a standardised way. There are many tools which rely on commits written following this spec which may be able to automate even more things for you in terms of release notes, feature updates, separation of commits/PRs by the nature of the work involved in them (such as refactors, chores, fixes, features, etc.).

It's absolutely the next thing you should at least give a look.

Wrapping this up

Good commit messages have serious GAINS. πŸ’ͺ
Gains for you, and the teams that you're a part of.

Less time spent debugging, fewer frustration moments, better documentation, automatic release notes, etc.

As a side-effect of all those improvements, you might even notice faster code deliveries, lesser wait time in reviews, fewer rework cycles!

Go on! Take credit for all the efficiency improvements you introduced!

And see exactly how much of a gain it was for your teams by using a productivity intelligence tool, such as Middleware! πŸš€

GitHub logo middlewarehq / middleware

✨ Open-source dev productivity platform for engineering teams ✨

Middleware Logo

Open-source engineering management that unlocks developer potential

continuous integration Commit activity per month contributors
license Stars

Middleware Opensource

Introduction

Middleware is an open-source tool designed to help engineering leaders measure and analyze the effectiveness of their teams using the DORA metrics. The DORA metrics are a set of four key values that provide insights into software delivery performance and operational efficiency.

They are:

  • Deployment Frequency: The frequency of code deployments to production or an operational environment.
  • Lead Time for Changes: The time it takes for a commit to make it into production.
  • Mean Time to Restore: The time it takes to restore service after an incident or failure.
  • Change Failure Rate: The percentage of deployments that result in failures or require remediation.

Table of Contents

πŸš€ Features

…

Top comments (21)

Collapse
 
shivamchhuneja profile image
Shivam Chhuneja

Communication is key, right?

Collapse
 
adriens profile image
adriens

Communiction for the future you or anyone else <3

Collapse
 
shivamchhuneja profile image
Shivam Chhuneja

haha yep!!

Collapse
 
samadyarkhan profile image
Samad Yar Khan

Great article! Commits are you best friend while navigating a new code base :)

Collapse
 
willashworth profile image
Will Ashworth

Thanks for writing this. A good commit history helps paint a better picture for a newcomer to the team. The quicker we can onboard understanding, the sooner we can realize our return on investment in hiring. Not to mention how much easier it is for existing team members (or ourselves) to rapidly understand what we meant when taking a later look at a project's code long after implementation.

Collapse
 
aravind profile image
Aravind Putrevu

Tbh, never read commit history unless to RCA. But interesting approach for sure.

Collapse
 
ayush2390 profile image
Ayush Thakur

Loved the cameo of Sheldon in the article πŸ˜‚

Collapse
 
adriens profile image
adriens

Nice looking releaseNotes is the most visible and satisfying reward.
Also, when an incident or something strange appears in production, reveiwing commit messages can be so precisous ;-p

Collapse
 
ujjwal_raj_666e7c8f438645 profile image
Ujjwal Raj

nice read. I always use commitzen to commit.

Collapse
 
taosif7 profile image
Taosif Jamal

Ever heard of "Conventional Commits"?

Collapse
 
jayantbh profile image
Jayant Bhawal

Oh yeah, absolutely!
I should have mentioned that in the post, truly.

Conventional commits are awesome, but they can be overwhelming for devs who don't understand the need for them in the first place.
Because I often find conventional commits to be a little too opinionated and rigid for new devs, or devs who are just getting to understand the need for good commit messages.

I'd say conventional commits is the next step one can take after they understand why a good commit message helps, but again, not everyone needs something as thorough of a spec as conventional commits. It depends on your needs and troubles (like most things, isn't it?)

I'll add this to the post though. Thanks for the reminder!

Collapse
 
jayantbh profile image
Jayant Bhawal

Added it. Good stuff!
Btw, in case you didn't yet, maybe aicommit.app/ will be interesting to you!

Collapse
 
israel__xy profile image
lΓ₯tΓΈr

I find it quite difficult to use the git extension on Vs Code. How can I format my commit message in the terminal the way it was cited in this article?

Collapse
 
jayantbh profile image
Jayant Bhawal • Edited

You can change your git commit editor to use nano, or vim for a relatively convenient experience.

I personally just use the continuation character (\) to add multiline commit messages. Let me know if an example will help.

Collapse
 
tetedacier profile image
tetedacier

In the cli each -m option to git commit add a new line containing the associated text argument.

Collapse
 
albertguedes profile image
Albert R. C. Guedes

new: ...
change: ...
remove: ...

People like to complicate things unnecessarily.

Collapse
 
jayantbh profile image
Jayant Bhawal

Oh yeah. Devs have a tendency to over-engineer things, don't we? πŸ˜„

But I'd say the new/change/remove structure might prove insufficient.
To me, a commit message should just combine these 3 into a small description of the change, and a few words (or a ticket/issue ref) about why.

But again, I don't expect someone to realistically do this for every single commit ever. Only for the more consequential commits. A commit that removes a stray console.log can just say "Removes stray log".

Collapse
 
xephun profile image
X. Ephun

Looking forward to gpt-generated commit from git status summaries of commit batches...

Collapse
 
jayantbh profile image
Jayant Bhawal

Maybe you can look into aicommit.app/

Collapse
 
codeveronica profile image
Luma

Very good article! :)

Collapse
 
jayantbh profile image
Jayant Bhawal

Thanks, Luma!