Write each commit as a small, coherent change. If it is hard to summarize cleanly, the commit may be doing too much.
Start with a short subject line that summarizes the change. If the change is simple enough, the subject alone can be the full message.
When the change needs explanation, add a blank line after the subject and then write a body. Git tools treat the text before the first blank line as the title, so keeping the subject separate matters.
Write the subject as an instruction, using imperative mood. Think "Add support for X", "Remove deprecated code", or "Refactor parser", not "Added", "Removing", or "More fixes".
A good test is: "If applied, this commit will ..." and then your subject should read naturally.
Use the body to explain the context behind the change. Describe what problem this commit solves, why the change was needed, any important side effects, and anything a future maintainer would not immediately learn from reading the diff alone.
Do not use the body to narrate the code mechanically. The diff already shows how the code changed. The commit message should focus on why the change exists and what matters about it.
If relevant, put issue references or related tracking information at the end of the message.
<brief summary of the change>
<why this change was needed>
<what problem it fixes or improves>
<any side effects, constraints, or follow-up context>
Resolves: #123
See also: #456
Not every commit needs a body. For a very small change, a single clear subject line is enough.
Good commit messages improve the usefulness of tools like git log, git shortlog, git blame, revert, and rebase, because they preserve context about why a change happened.