DEV Community

Git commit message best practices with before and after rewrites

Run git log --oneline on almost any project and you'll find a stretch like this.

a1f3c2e wip
9be07d1 fix
3c44a9f more fixes
e02b8d1 asdf
7d1f6aa final changes for real

Every one of those commits was obvious to the person who wrote it, on the day they wrote it. A year later, during a git bisect at 11 PM, none of them mean anything.

These are the git commit message best practices that fix that, each shown with a before and after rewrite, plus how conventional commits fit on top.

The seven habits that matter

  • Separate the subject from the body with a blank line.
  • Keep the subject around 50 characters, and wrap the body near 72.
  • Capitalize the subject and skip the trailing period.
  • Write the subject as a command, as in "Add", "Remove" or "Rename".
  • Say what changed and why. The diff already shows how.
  • Make one logical change per commit.
  • Reference the issue or ticket in the body or footer, not as the whole message.

A handy test for the subject is to finish the sentence "If applied, this commit will..." with it. "If applied, this commit will add rate limiting to the login endpoint" reads well. "If applied, this commit will fixed stuff" doesn't.

Before and after rewrites

Vague subject

fix

Prevent duplicate invoices when checkout is retried

The first tells you nothing. The second says what broke, from the outside, so anyone searching the log for "invoice" finds it.

Subject that's really a diary entry

Finally got the date picker working after hours of pain

Fix date picker ignoring the locale's first day of week

Feelings belong in the team chat. The log is for facts.

Everything in one commit

update settings page, fix typo in readme, bump eslint

Split it into three commits.

Add timezone selector to settings page
Fix typo in README install steps
Bump eslint from 8.56 to 8.57

Now each one can be reverted on its own, and blame points to the right change.

Missing the why

Change cache TTL to 300

Lower product cache TTL to 5 minutes

Prices stayed stale for up to an hour after edits in the admin panel, which caused support tickets during sales. Five minutes keeps database load low while letting price changes show up soon after they're saved. Refs #812

The subject tells you what. The body tells the next developer not to raise it back to an hour without thinking.

Where conventional commits fit

Conventional commits is a spec for a structured subject line. It adds a type and an optional scope in front of the description.

<type>(<scope>): <description>

[optional body]

[optional footer(s)]

Common types are feat, fix, docs, refactor, test, perf, build, ci and chore. A ! after the type, or a BREAKING CHANGE footer, marks a breaking change.

Here's the cache example in that style.

fix(cache): lower product cache TTL to 5 minutes

Prices stayed stale for up to an hour after admin edits. Refs #812

And a breaking one.

feat(api)!: require an API key for all v2 endpoints

BREAKING CHANGE: anonymous requests to /v2 now return 401. Clients must send the X-Api-Key header.

Most teams using the convention write lowercase descriptions, which clashes with habit 3. Pick one rule per repo and stick to it.

Why teams adopt it

The structure is machine readable. Tools can generate changelogs from feat and fix commits and work out the next semantic version. A fix maps to a patch, a feat to a minor and a breaking change to a major.

It also nudges people to think in single changes. If you can't pick one type for a commit, it's probably two commits.

When it's overkill

On a solo side project with no releases, the type prefix can be noise. The seven habits above matter more than the prefix. A clear plain subject beats a typed prefix followed by "stuff" every time.

Make it easy to do right

Set a real editor for commits so you're not cramming everything into -m. Add a commit template with git config commit.template ~/.gitmessage that reminds you of the subject and body shape. If your team uses conventional commits, run commitlint in a hook or a CI step so the format gets checked for you.

Finally, read your subject line cold, the way a stranger to the code would. If it only makes sense with context in your head, rewrite it. Rephrase AI keeps what a sentence means while changing the words, and you can line the result up against your first draft before you commit. Its blog also has a short post on ways to rephrase text for clarity, and the same ideas work on a commit body.

Your teammates, and you in a year, will be able to search the history and find what they need.

Read on DEV Community ↗ ← Back to News

Comments

No comments yet. Start the discussion.