DEV Community

Cover image for How to Write Commit Messages That Are Actually Useful
Techifive
Techifive

Posted on

How to Write Commit Messages That Are Actually Useful

Most commit messages are either too vague, too noisy, or completely useless three weeks later. Here’s how to write ones that help your team, your future self, and even your AI tools.


Most commit messages fail for one simple reason

They describe what you just did, but not why it mattered.

That is why so many commit histories end up looking like this:

  • fix bug
  • changes
  • updated
  • final final
  • misc
  • cleanup
  • working version

These messages might feel fine in the moment.

But later?

They are almost useless.

A good commit message is not there to help present you.
It is there to help:

  • future you
  • your teammates
  • reviewers
  • maintainers
  • anyone debugging later
  • anyone reading history to understand product or architecture decisions

And now, increasingly, it also helps AI tooling understand your codebase changes better.

That means commit messages are no longer a small habit.
They are part of engineering quality.


What a useful commit message actually does

A useful commit message should answer one or more of these questions:

  • What changed?
  • Why did it change?
  • What problem does this solve?
  • What was the impact?
  • Is there anything risky, temporary, or notable about this change?

That does not mean every commit message needs to become a novel.

It means every commit message should provide enough signal that someone reading it later can understand the intent of the change without opening ten files and guessing.

That is the standard.


The simplest rule: write for the reader, not the moment

When you are committing code, you already know what you changed.

The reader does not.

So the goal is not to leave yourself a breadcrumb like:

yep, I remember this

The goal is to leave a trail that still makes sense when:

  • the context is gone
  • the task is half-forgotten
  • the bug comes back
  • the feature behaves strangely
  • the change needs to be reverted
  • someone new joins the project

That is why vague messages are so expensive.

They push the cost of understanding onto everyone later.


A simple format that works really well

You do not need an overly fancy system.

For most teams, this basic structure is enough:

Subject line

A short summary of the change.

Optional body

A few lines explaining:

  • why the change was made
  • what tradeoff was involved
  • what side effects or follow-ups matter

That is it.

A strong subject line carries most of the weight.
A short body adds context where needed.


The best practical pattern for most developers

Here is the version I recommend most often:

Subject line formula

Verb + object + reason/result

Examples:

  • Fix checkout total rounding for discount edge cases
  • Add retry logic for failed webhook deliveries
  • Refactor auth middleware to simplify role checks
  • Improve dashboard query performance for large accounts
  • Remove unused analytics dependency from admin app

This works because it gives immediate clarity.

It tells the reader:

  • the action
  • the area
  • the purpose or impact

That is usually enough to make a commit actually useful.


What separates a bad commit message from a good one

Bad

fixed issue

Better

Fix login redirect loop after session timeout

Why the second one wins:

  • it names the actual issue
  • it points to behavior, not just effort
  • it helps anyone scanning history later

Another example:

Bad

update api

Better

Add pagination to orders API to reduce response size

Again, the better message explains the change in terms of system behavior and purpose.

That is the whole game.


The golden rule: commit the smallest meaningful change

A lot of bad commit messages are really a symptom of bad commit shape.

If one commit contains:

  • a bug fix
  • a refactor
  • a style cleanup
  • a config change
  • a test rewrite
  • a random import reorder

then the message is almost guaranteed to be messy.

Good commit messages become easier when commits are:

  • focused
  • intentional
  • scoped to one idea

So before improving your wording, improve your commit boundaries.

A precise commit makes a precise message much easier.


Use the subject line like a headline, not a diary entry

The subject line should be short, specific, and skimmable.

It should make sense in git log without needing extra explanation.

That means avoid messages like:

  • I changed a few things
  • trying another fix
  • more work on this
  • temp
  • small updates
  • address review comments

Those are status updates, not historical records.

Instead, write the change as something someone else can understand on its own.

Better versions:

  • Resolve review feedback in payment error handling
  • Split profile update form into separate validation hooks
  • Prevent duplicate invoice creation on retry

Now the history is readable.


Traditional best practices that still matter

These are old-school for a reason.
They still work.

1. Keep the first line concise

Aim for a clean, readable subject line.
It should be easy to scan in logs and PR views.

2. Start with an action verb

Use words like:

  • Fix
  • Add
  • Remove
  • Refactor
  • Improve
  • Rename
  • Prevent
  • Simplify
  • Update

This creates clarity fast.

3. Be specific about the area affected

Name the system, module, page, flow, or behavior.

Not:
Fix issue

Better:
Fix email verification link handling in signup flow

4. Use the body when context matters

If the change includes tradeoffs, risk, or reasoning, explain it.

Example:

Refactor image upload pipeline to reduce memory spikes

Body:

  • Move resizing to background job
  • Avoid large in-request processing for multi-file uploads
  • Keeps existing API response format unchanged

That is extremely useful history.

5. Reference tickets only as support, not as the whole message

Bad:
JIRA-482

Better:
Fix broken password reset token validation

Body:
Refs JIRA-482

Ticket numbers help.
They do not replace meaning.


The most useful commit messages explain why

This is where great commit messages pull away from merely decent ones.

A lot of developers stop at describing what changed.

But in many cases, the more valuable information is why the change happened.

For example:

Okay

Increase cache TTL for product search

Better

Increase product search cache TTL to reduce repeated DB load during peak traffic

Now the reader understands the intention.

That matters because code often outlives the original discussion.
The commit message may be the clearest surviving clue.


When to include a body

Use a body when the change is not obvious from the diff alone.

That often includes:

  • architectural decisions
  • temporary workarounds
  • performance tradeoffs
  • compatibility concerns
  • breaking changes
  • security-related rationale
  • unusual implementation choices

Example

Replace polling with webhook-based sync for order status

Body:

  • Reduces background job volume and API waste
  • Keeps polling as fallback for providers without webhook support
  • Follow-up cleanup needed after legacy provider migration

That is excellent commit history.
It tells a future reader what happened and what still matters.


Commit message examples that are actually strong

Feature work

Add saved filters to admin customer search

Bug fix

Fix cart item duplication when browser back button is used

Refactor

Refactor billing service to separate tax and invoice logic

Performance

Optimize report generation query for large customer datasets

Security

Sanitize filename handling in document upload endpoint

Cleanup

Remove dead feature flag for legacy onboarding flow

Testing

Add regression tests for invoice retry idempotency

Each one is:

  • focused
  • readable
  • useful later

That is the bar.


What not to do

Here are the habits that quietly ruin commit history.

1. Do not write messages that only make sense today

Examples:

  • this should work
  • another try
  • fix again
  • done

These age terribly.

2. Do not use commit messages as emotional journaling

We have all felt this:

  • finally fixed this stupid bug
  • why was this broken
  • I hate css

Funny once.
Not useful later.

3. Do not describe noise instead of meaning

Bad:
change variable names and update code

Better:
Rename payment status fields for webhook consistency

4. Do not hide risky changes behind soft language

If something is a workaround, say so.
If it is temporary, say so.
If it changes behavior, say so.

Ambiguity hurts teams.


A practical structure for different commit types

If you want a reliable internal pattern, this one works well.

For bug fixes

Fix [behavior/problem] in [area]

Examples:

  • Fix duplicate session creation in mobile login flow
  • Fix CSV export encoding for non-English characters

For features

Add [capability] to [area/use case]

Examples:

  • Add bulk archive action to support inbox
  • Add structured metadata to blog schema output

For refactors

Refactor [area] to [benefit/reason]

Examples:

  • Refactor image service to simplify format handling
  • Refactor auth guards to reduce duplicated permission checks

For performance work

Improve/Optimize [area] for [result]

Examples:

  • Optimize product page queries for faster first load
  • Improve worker concurrency handling for queue throughput

For cleanup/removal

Remove [thing] from [area]

Examples:

  • Remove deprecated Stripe event mapping
  • Remove unused CSS for legacy landing page

This pattern keeps teams consistent without feeling robotic.


How AI changes commit messages

Now the modern part.

AI is changing commit messages in two very practical ways.

1. AI can help write better commit messages

If you are using AI in your workflow, it can turn a diff into a strong first draft.

That is useful.
But only if you review it.

A good AI-assisted commit message should still be:

  • specific
  • scoped
  • honest
  • written for your codebase context

Do not just accept generic output like:
Update code and improve functionality

That is AI-generated nonsense wearing a collared shirt.

2. Better commit messages make AI tools more useful later

This part is underrated.

Good commit history improves:

  • codebase search
  • change tracing
  • debugging assistance
  • AI-generated summaries
  • onboarding help
  • blame/history analysis

If your history is full of vague commits, AI tools will have less signal to work with.

So a good commit message is not just for humans anymore.
It is part of your machine-readable engineering context too.


The best way to use AI for commit messages

Use AI as an assistant, not a substitute.

Here is a practical workflow:

Step 1: Stage only the meaningful change

Do not dump unrelated files into one commit.

Step 2: Ask AI to summarize the diff

Have it produce:

  • a short subject line
  • an optional body
  • maybe 2–3 alternatives

Step 3: Edit the message yourself

Check:

  • is it specific?
  • does it mention the real behavior?
  • does it explain the why when needed?
  • does it avoid fake certainty?

Step 4: Keep your team conventions

AI should adapt to your standards, not flatten them.

That is the smart balance.


Prompts that actually work well with AI

If you use AI, prompt it like this:

Simple prompt

Write a concise Git commit message for this diff. Make it specific, start with an action verb, and focus on user-visible behavior or engineering purpose.

Better prompt

Write 3 Git commit message options for this diff:

  • one concise
  • one standard
  • one with a short explanatory body Focus on what changed and why. Avoid vague wording like “update” or “fix issue.”

For larger changes

Summarize this staged diff as a useful Git commit message. Use a clear subject line and add a body only if the reasoning or tradeoff matters. Mention risk, workaround status, or follow-up if relevant.

Those prompts usually produce much better results than “write commit message.”


Team-level advice: create a standard everyone can actually follow

A lot of teams overcomplicate commit conventions.

Then nobody follows them.

The best standard is one that is:

  • clear
  • lightweight
  • easy to remember
  • actually used

A very workable team rule is:

Team rule

Every commit message should:

  1. say what changed
  2. identify the area affected
  3. explain why when it is not obvious

That alone is enough to improve most histories dramatically.


What really makes a commit history excellent

It is not perfect grammar.
It is not fancy prefixes.
It is not obsessive formatting.

A great commit history is one where someone can scroll through it and understand:

  • what the team built
  • what broke
  • what got fixed
  • what changed direction
  • where the risky parts were
  • how the system evolved

That is incredibly valuable.

And it comes from consistent, thoughtful commit messages — not heroic effort.


Where this matters for real product teams

This is especially important for teams building client work, web apps, SEO systems, AI workflows, or ongoing digital products.

Why?

Because those projects often involve:

  • frequent iteration
  • changing requirements
  • bug fixes under time pressure
  • cross-functional collaboration
  • future handoffs and maintenance

That means commit history becomes part of project clarity.

A clean history makes it easier to:

  • debug
  • onboard
  • review
  • deploy
  • maintain
  • explain decisions to clients or teammates

That is one reason good engineering teams treat communication inside the repo as part of the product.

And honestly, that is also the kind of detail-oriented workflow clients appreciate when working with a company like Techifive. Clean commits do not sell a project on their own, obviously, but they are part of the deeper signal: the work is being done with care, traceability, and long-term usefulness in mind.

That stuff matters.


My recommended formula

If you want one practical takeaway, use this:

Default formula

[Action] + [specific area] + [reason/result]

Examples:

  • Fix token refresh logic to prevent forced logout loops
  • Add canonical tag support to CMS blog pages
  • Refactor search filters to simplify mobile state handling
  • Optimize image delivery for faster landing page load

That formula is simple enough to use every day and strong enough to improve almost any codebase.


Final thought

Useful commit messages are not about being formal.

They are about being helpful.

A good commit message reduces confusion later.
It saves debugging time.
It improves collaboration.
It makes code history readable.
And now, with AI in the workflow, it also increases the value of your repo as structured context.

So the next time you are about to commit something, do not ask:

“What did I just do?”

Ask:

“What would someone need to know about this change six weeks from now?”

That question usually leads to a much better message.


Discussion

What is the worst commit message you have ever seen in a real project?

Top comments (0)