Git � �9 min read

Clean Commits: Writing Better Messages

Good Git commit messages are more than a description of what you changed. They create a useful history of your project, helping you understand why a change was made months or even years later. In this article, we’ll look at practical ways to write cleaner, clearer commit messages and introduce conventions that can make your Git history easier to understand and maintain.

Admin
Admin
.NET & IoT Developer
Clean Commits: Writing Better Messages

Good Git commit messages are more than a description of what you changed. They create a useful history of your project, helping you understand why a change was made months or even years later. In this article, we’ll look at practical ways to write cleaner, clearer commit messages and introduce conventions that can make your Git history easier to understand and maintain.

Why Commit Messages Matter

It is very easy to treat a Git commit as nothing more than a button you press after finishing some work.

You make a change, stage your files and type something like:

Updated stuff

Or perhaps:

Fixes

The problem is that these messages might make sense at the time, but they provide very little useful information later.

Imagine looking through the history of a project six months from now and finding commits called "Changes", "Update", "Fix", "More changes" and "Final changes". You know that something happened, but you have no idea what those changes actually involved.

A good commit message becomes part of the documentation for your project. It gives future developers, your colleagues and even your future self a quick explanation of what happened.

Git itself recommends starting a commit with a short summary, followed by a more detailed description when additional context is required.

Describe What Changed

The first rule of a good commit message is simple: describe the actual change.

Consider a commit containing a change to an application's authentication system.

A message such as:

Updated authentication

is technically true, but it is not particularly useful.

A better message would be:

Add refresh token support to authentication

Now we immediately know what was changed.

Another example might be:

Fix null reference when loading customer profile

This tells us considerably more than:

Fixed bug

The goal is to make the commit understandable without requiring somebody to open every changed file.

Explain Why When It Matters

Describing what changed is useful, but sometimes the most valuable information is why the change was necessary.

For example:

Increase API timeout to handle slow payment responses

tells us what happened.

A more detailed commit could explain the reason:

Increase API timeout for payment requests

The payment provider can occasionally take more than 30 seconds
to respond during periods of high traffic. The previous timeout
caused valid payment requests to fail prematurely.

This becomes particularly valuable when somebody later considers changing the timeout back.

Without the explanation, they might assume the value was arbitrary. With the explanation, they understand the decision that was made.

Git's own development guidelines emphasise that useful commit messages should help explain the problem being solved and justify the chosen solution.

Keep the First Line Short

The first line of a commit is particularly important because it is commonly displayed in Git logs, GitHub, Visual Studio and other development tools.

Git recommends a short summary of no more than around 50 characters, although this should be treated as a guideline rather than an absolute rule.

For example:

Fix customer profile loading

is much easier to scan than:

Fixed an issue that was occurring when the customer profile page was being loaded and sometimes causing a null reference exception

If the change needs more explanation, put that information in the body of the commit.

The result is a history that remains easy to scan while still allowing detailed information to be recorded when necessary.

Use Imperative Language

A useful convention is to write the first line as an instruction or action.

For example:

Add customer validation

rather than:

Added customer validation

Similarly:

Fix login timeout

is preferable to:

Fixed login timeout

This style creates a consistent history where each commit describes an action.

You do not have to obsess over grammar, but consistency makes a surprisingly big difference when browsing a large repository.

Avoid Meaningless Messages

Some commit messages appear regularly in development projects:

Changes
Update
Fix
Bug fix
Stuff
Testing
More changes
Final
Final fix
Really final fix

The problem is not that these messages are short. The problem is that they communicate almost nothing.

A short message can still be excellent.

For example:

Fix incorrect order total

contains only five words, but tells us exactly what the commit addressed.

The objective is not to write long commit messages. The objective is to write useful ones.

Keep Commits Focused

Good commit messages become much easier to write when the commit itself represents one logical change.

For example, suppose you have changed the login validation, updated the navigation menu, fixed a database query and reformatted several unrelated files.

You could commit everything together with:

Update application

But this creates a problem.

If you separate the work into logical commits, you might instead have:

Fix login validation
Update navigation menu
Optimise customer query
Format service classes

Each commit now has a clear purpose.

GitHub also recommends keeping commits focused around small, related groups of changes because this makes the history easier to understand.

Use the Commit Body for Context

Not every commit needs a long description.

A simple change such as:

Fix spelling mistake in README

probably does not need anything else.

A more complicated change might benefit from a body.

For example:

Fix customer search timeout

The customer search was timing out when the database contained
a large number of records. The query was loading unnecessary
columns before filtering the results.

The query now applies the filter before retrieving the remaining
customer information.

The first line gives us the summary.

The body explains the problem and the solution.

This is especially useful for changes that involve design decisions or behaviour that might otherwise be difficult to understand later.

Introducing Conventional Commits

If you want to take commit messages a step further, you can adopt the Conventional Commits convention.

Conventional Commits provides a lightweight structure for making commit messages both human-readable and machine-readable.

The basic format is:

type: description

For example:

feat: add customer export

or:

fix: prevent duplicate customer records

A scope can also be included:

fix(api): handle missing customer address

The convention commonly uses types such as feat for new functionality, fix for bug fixes, docs for documentation, refactor for code restructuring and test for testing changes.

The advantage is that somebody scanning the Git history can immediately see the nature of each change.

A Practical Conventional Commit

Consider a new feature being added to an ASP.NET Core application.

Instead of:

Added export functionality

you could write:

feat(customers): add CSV export

A bug fix might be:

fix(orders): prevent duplicate order submission

A documentation change could be:

docs: update installation instructions

And a refactoring could be:

refactor(auth): simplify token validation

These messages are short but provide considerably more information.

Conventional Commits can also be useful when projects use automation to generate changelogs or determine version changes from the commit history.

Breaking Changes

Some changes require more attention than others.

If a change breaks an existing API or requires consumers of your software to make changes, Conventional Commits provides a way of identifying it.

For example:

feat(api)!: remove legacy customer endpoint

The exclamation mark indicates a breaking change.

Alternatively, the commit body can contain a BREAKING CHANGE footer explaining what has changed.

This can be particularly useful for libraries and APIs where developers outside the immediate project may depend on the existing behaviour.

Commit Messages Are Part of Your Project History

One of the biggest advantages of good commit messages only becomes apparent over time.

Imagine investigating a problem in a project two years after the original code was written.

You discover that a particular piece of code looks unusual. You use Git to inspect its history and find:

fix(payments): prevent duplicate payment requests

You can immediately see that the unusual code was introduced deliberately to address a payment problem.

A poor message such as:

Changes

would leave you with very little useful information.

This is why commit messages should be considered part of the project's historical record.

Writing Better Commit Messages in Practice

Before committing, take a moment to look at the changes you are actually about to record.

Ask yourself what has changed and why it has changed.

If the answer can be expressed clearly in a single sentence, use that sentence as your commit message.

For example:

Fix incorrect VAT calculation

If the reason is important, add a body explaining it.

Fix incorrect VAT calculation

VAT was being calculated before the discount was applied,
resulting in an incorrect total for discounted products.

This takes only a few seconds but could save considerably more time in the future.

A Simple Formula

If you are struggling to write a commit message, a simple formula works well:

Action + What Changed + Where

For example:

Fix validation in customer registration

Or:

Add caching to product service

Or:

Update error handling in payment API

If somebody needs more information, explain the reason in the commit body.

The important thing is that somebody reading the Git history should be able to understand the purpose of the commit without opening the entire codebase.

Final Thoughts

Git makes it incredibly easy to create a history of every change made to a project, but the quality of that history depends heavily on the information we put into our commits.

A good commit message does not need to be complicated. It simply needs to be clear, concise and meaningful.

Describe what changed. Explain why when necessary. Keep commits focused and use a consistent style. If your project benefits from additional structure, consider adopting Conventional Commits.

After all, the person most likely to benefit from a good commit message might not be another developer.

It might be you, six months from now, trying to remember exactly why you wrote that piece of code in the first place.

Share:

Become a member

Get the latest news right in your inbox. It's free and you can unsubscribe at any time. We hate spam as much as we do, so we never spam!

Read next

Git Workflows for Solo Developers

Version control is essential for any developer, even when working alone. A clear Git workflow helps you organise changes, track features, and avoid breaking your main codebase. In this article, we explore simple and practical Git workflows that solo developers can adopt to keep projects maintainable, predictable, and easy to manage.

Admin 08-Mar-2026

The Bedroom Coder — retro computers, modern .NET, and late-night experiments.

Navigation

Contact

Want to talk retro tech or modern coding? I'd love to hear your thoughts.

© 2026 The Bedroom Coder. All rights reserved.