Back to Blog

The Art of Writing Good Git Commit Messages

We have all been there.

You run git log on a project you have not touched in a few months, and you are greeted by a wall of messages that look like this:

  • update
  • fixed the thing
  • wip
  • more styling
  • asdfghjkl
Usually, these are written at 2 AM when you just want to push your code and go to sleep. But here is the harsh truth: bad commit messages are a massive pain for your future self, and for anyone else who has to work on your codebase.

When a bug suddenly appears in production and you need to use git blame or git bisect to figure out when the code broke, seeing a commit message that says changes tells you absolutely nothing. You are forced to manually read the diffs to understand what happened.

A git commit message is not just a save point. It is communication with the future.

The Format I Use: Conventional Commits

I used to write sloppy commit messages until I forced myself to adopt the Conventional Commits specification. It is a lightweight convention that adds a tiny bit of structure to your commit messages.

It takes maybe two extra seconds to type, but it makes your git history readable, searchable, and incredibly clean.

The format looks like this:

<type>(<optional scope>): <subject>

The "Type"

This immediately tells the reader what kind of work was done. I stick to a handful of standard types:
  • feat: A new feature.
  • fix: A bug fix.
  • refactor: Code changes that neither fix a bug nor add a feature (like renaming variables or extracting components).
  • chore: Maintenance tasks like updating dependencies or config files.
  • docs: Documentation updates.
  • style: Formatting changes (spacing, missing semicolons) that do not affect code logic.

The "Scope"

This is optional, but it is great for larger projects. It tells you where the change happened. For example, feat(auth) or fix(navbar).

The "Subject"

This is the meat of the commit message. It should be a short, direct description of what changed.

The Golden Rule for the Subject Line

There is one simple rule I follow to write the subject line. It should always be written in the imperative mood (like a command).

A great way to test this is to see if your commit message makes sense when placed after this sentence:

"If applied, this commit will..."

Let's test it out:

  • If applied, this commit will add dark mode toggle to the header. (Makes sense!)
  • If applied, this commit will added dark mode. (Grammatically incorrect.)
  • If applied, this commit will fixed a bug. (Incorrect.)
  • If applied, this commit will fix navbar overlapping on mobile screens. (Makes sense!)

Bad vs. Good Examples

Let's look at some common bad commit messages and how they look after applying this format.

Bad Commit MessageGood Commit Message
fixed login bugfix(auth): handle null token error on login redirect
styling updatesfeat(ui): add hover state to primary buttons
updated packageschore: bump react and react-dom to v18
refactoringrefactor(blog): extract post card into separate component

Why This Actually Matters

Adopting this format changed how I work for a few reasons:

  1. It forces me to write smaller commits. If I struggle to write a single commit message because I changed the auth flow, updated the footer styling, and bumped a dependency all at once, it means my commit is too big. I need to break it into three separate commits.
  2. It makes generating changelogs trivial. Because every new feature is tagged with feat: and every bug fix with fix:, you can literally use scripts to auto-generate release notes based on your git history.
  3. It looks professional. When recruiters or other developers look at my open-source projects, a clean commit history shows that I care about maintainability and team collaboration.
Treat your git history like documentation. Your future self will thank you.