Git Commit Message Conventions for Readable Project History
Quick answer
Quick answer: write a short imperative subject line of about 50 characters, leave a blank line, and use the body to explain why the change was made, not just...
Quick answer: write a short imperative subject line of about 50 characters, leave a blank line, and use the body to explain why the change was made, not just what changed. Keep each commit focused on one logical change. Optionally adopt a structured convention such as conventional commits if you want automated changelogs and version bumps.
What Makes a Good Commit Message?
A commit message is documentation attached to a specific change, and it is often the only explanation that survives. Months later, someone running blame on a confusing line will read it to understand why the code looks that way. The diff already shows what changed, so the message should capture the reason: the problem, the constraint, or the trade-off behind the decision.
The subject line is the part most tools display, so it matters most. Keep it short, around 50 characters, and write it in the imperative mood, as in add retry to payment client, because Git itself uses that style for generated messages. Skip trailing periods and avoid vague subjects like fix bug or update stuff, which make the history useless for searching.
The body is optional for trivial changes and valuable for everything else. Separate it from the subject with a blank line, wrap lines at about 72 characters so it reads well in terminals, and explain context, alternatives you rejected, and side effects. Reference issue or ticket numbers so the change links back to the discussion.
Add retry with backoff to payment client
The payment provider returns sporadic 503 responses during
maintenance windows. Retrying idempotent requests up to three
times with exponential backoff avoids failed checkouts.
Non-idempotent calls are not retried to prevent double charges.
Refs: PAY-482
Should You Use Conventional Commits?
Conventional commits add a machine-readable prefix to the subject, such as feat, fix, docs, refactor, or chore, optionally with a scope in parentheses. A breaking change is marked explicitly. The format enables tooling that generates changelogs and decides version numbers from the history, which suits libraries and services with frequent releases.
The trade-offs are discipline and noise. The convention only works if everyone follows it, which usually requires a commit-message check in a hook or CI. Some teams find the prefixes add ceremony without benefit, particularly for internal applications where no changelog is produced. Choose it when you will actually use the output.
- Use it if you automate releases, changelogs, or semantic version bumps.
- Skip it if the history is only read by your team and plain, clear subjects already work.
- Whatever you pick, document it in the contributing guide and enforce it consistently.
How Do Commit Habits Affect History Quality?
Good messages depend on good commit boundaries. Atomic commits, each doing one logical thing, are easier to describe, review, revert, and bisect. A commit mixing a refactor, a bug fix, and a formatting change produces a message that must say and, which is a sign it should be split.
Your merge strategy changes where the message matters. With squash merges, the pull request title and description often become the final commit message on the main branch, so the quality of that text is what future readers see. Intermediate commits such as wip or fix typo can be cleaned up with interactive rebase before sharing, as long as the branch is yours alone.
Tooling helps too. A commit message template, configured in Git, reminds authors of the structure. A commit-msg hook can check the subject length or format. Keep checks forgiving enough that they guide rather than frustrate, and let reviewers focus on the substance of the message.
Frequently Asked Questions
How long should a commit subject line be?
About 50 characters is a common guideline, with 72 as a practical upper limit. Shorter subjects display fully in logs and interfaces and force clearer wording.
Why use the imperative mood?
It matches messages Git generates, such as merge and revert, and reads as a description of what applying the commit does. Consistency matters more than the grammar itself.
Should every commit have a body?
No. Small, self-explanatory changes can have only a subject. Add a body whenever the reason, trade-off, or side effect is not obvious from the diff.
Can I fix a bad commit message after pushing?
You can rewrite it, but that changes history and requires a force push, which is risky on shared branches. Avoid rewriting published commits unless your team agrees.
Summary
Write short imperative subjects, explain the why in the body, and keep commits atomic. Adopt conventional commits only if you use the automation they enable, and enforce your convention gently with templates and checks. Consult the Git documentation for configuration options in your version.