Skip to content
Generate now

How to Write Good Commit Messages (With Examples)

โ€œFixed stuff.โ€ โ€œWIP.โ€ โ€œasdf.โ€ Scroll through almost any Git history and you will find messages that made sense for ten seconds. Months later, when you are hunting down the change that broke checkout, they tell you nothing. A good commit message takes thirty seconds to write and saves hours of archaeology. This guide covers the conventions experienced teams follow, with examples you can copy into your own workflow.

Options

Tip: press Enter or Space to generate again.

Ready

The shape of a great message

A commit message has a subject line, a blank line and an optional body. The widely used โ€œ50/72โ€ guideline says:

  • Keep the subject to about 50 characters so it fits in one-line logs and tool interfaces.
  • Leave the second line blank; many tools rely on it to separate subject from body.
  • Wrap the body at about 72 characters so it reads well in a terminal.

The body is where you explain why the change was needed and what alternatives you rejected. The diff already shows what changed.

Write the subject in the imperative

Git itself writes messages like โ€œMerge branch โ€ฆโ€ and โ€œRevert โ€ฆโ€, so the convention is to phrase subjects as commands: โ€œAdd search filtersโ€, not โ€œAdded search filtersโ€ or โ€œAdds search filtersโ€. A handy test: the subject should complete the sentence โ€œIf applied, this commit will โ€ฆโ€.

Some before-and-after examples:

  • โ€œfixed bugโ€ โ†’ โ€œFix crash when cart is emptyโ€
  • โ€œchangesโ€ โ†’ โ€œRename user service to account serviceโ€
  • โ€œupdateโ€ โ†’ โ€œBump image library to patch memory leakโ€

Conventional Commits in a nutshell

Conventional Commits adds a small, machine-readable structure: type(scope): description. For example, fix(auth): handle expired refresh tokens. Common types include:

  • feat โ€” a new feature (maps to a minor version bump)
  • fix โ€” a bug fix (maps to a patch bump)
  • docs, style, refactor, perf, test, build, ci and chore โ€” everything else

A breaking change is marked with an exclamation mark, as in feat(api)!: remove v1 endpoints, or a BREAKING CHANGE: footer, and triggers a major bump. Release tools can then generate changelogs and version numbers straight from the history.

How to use the generator for demos and tooling

When you build a demo repository, test a commit-lint rule or record a tutorial, you need plausible history fast. The generator above helps:

  1. Leave Include scope on for messages like feat(cli): add search filters, or switch it off for the shorter type: description form.
  2. Generate up to 50 messages per batch, mixing types such as feat, test, refactor, style and perf with scopes like ui, auth, docs and deps.
  3. Feed them into a script that creates empty commits, or paste them into your changelog generatorโ€™s test fixtures.
  4. Use the batch to check that your lint rules accept valid messages and your changelog groups them correctly.

For real work, always describe what actually changed โ€” generic messages belong in sample data only.

Small habits that keep history clean

  • One logical change per commit. If the subject needs the word โ€œandโ€, consider splitting it.
  • Reference the issue in the body or footer so readers can find the discussion.
  • Tidy up before you share. Squash โ€œfix typoโ€ commits into the change they belong to before opening a pull request.
  • Read your log. Run git log --oneline now and then; if it does not tell a story, adjust your habits.

A full example with body

Here is what a complete message can look like:

fix(checkout): prevent double charge on slow networks

After a blank line, the body might say: โ€œThe pay button stayed active while the request was pending, so impatient users could submit twice. Disable the button until the response arrives and make the server reject duplicate order tokens.โ€ A footer can then list the related issue number.

In five lines, a future reader learns the symptom, the cause and both parts of the fix โ€” without opening the diff.

Pro tips

  • Write the message before you commit by asking โ€œwhy would a teammate need this change?โ€.
  • Avoid ending the subject line with a period.
  • Use the body to record decisions that are not obvious from the code.
  • Add a commit-msg hook or lint step so the convention is checked automatically.

Frequently asked questions

Can I edit a commit message after committing?

Yes. git commit –amend changes the most recent message. Avoid rewriting commits that others have already pulled, as it changes their history.

Should commit subjects start with a capital letter?

Plain-style messages traditionally do, while Conventional Commits descriptions usually start lowercase after the type. Follow whichever style your project already uses.

How long can a commit message body be?

As long as it needs to be. A few short paragraphs explaining the reasoning are far more useful than a single vague line.

Try a generator

Random Address Generator

Realistic street addresses with valid-format postal codes and phone numbers for 40 countries.

Fake Identity Generator

Complete fictional person profiles: name, birthday, address, phone, email, job and more.

Need random data? Get it now.

Pick any of 144 generators, hit Generate and copy or export the results as CSV, JSON or TXT. No account, no limits, nothing stored.

Start generating โ€” free