A well-written commit message saves hours of confusion six months later. After years of debugging production issues and onboarding new team members, these patterns have made the biggest difference.

Start With the Basics That Actually Matter

Before diving into advanced tips, let’s ensure the basics are covered. A good git commit message should clearly and succinctly describe the what and the why of the commit. Here are some fundamental practices:

1. Keep the Subject Line Concise and Informative

Fifty characters forces focus on what really changed. Those long, rambling subject lines get cut off anyway.

Instead of “fixes” write “Fix user login issue.” The extra context costs nothing but saves everything.

2. Write Like Git Does

Git’s own messages use imperative mood. “Add” not “Added.” “Fix” not “Fixes.” Following the same pattern makes the history consistent.

Example: Use “Add” instead of “Added,” and “Fix” instead of “Fixes.”

3. Explain the Why in the Body

The code diff shows what changed. The commit message should explain why it needed to change.

Example:

Add JSON parsing capability

Replace XML parser with JSON to reduce latency for end users. 
Heavy XML processing was causing 200ms delays during peak traffic.

4. Reference Issue or Ticket IDs

“Closes #123” connects commits to tickets. Six months later, that ticket thread might be the only place the business context survived.

Example: Append “Closes #123” to connect a commit to a GitHub issue or Jira ticket.

Beyond the Basics: What Really Works

Moving beyond the basics, here are some advanced strategies to refine your git practices further.

[Tip]: ☝️How to undo a Git Commit 👇

5. Craft a Narrative

The best commit messages read like project history, not technical documentation. Explain not just what was changed but why it was necessary. This turns a functional message into a piece of the project’s story.

Example:

Refactor database connection logic

Switch to singleton pattern to prevent connection exhaustion. 
Previous approach opened 50+ simultaneous connections under load,
causing timeouts during daily traffic spikes.

6. Emphasize Small, Focused Commits

If summarizing a commit is hard, it’s probably doing too much. Focused commits write themselves.

Example: “Optimize image loading” beats “Update image handling and fix cache issues and add compression.”

7. Use Git Commands for Managing Complex Changes

For larger features, utilize git reset, git rebase -i, and git cherry-pick to organize and clean up your commit history. This makes each commit a readable “chapter” of your development story.

Example: To combine related changes into a single commit, you might use:

git rebase -i HEAD~4  # Interactively rebase the last four commits

8. Fill in the Blank: “If this commit is applied, it will …”

This technique forces you to describe the commit’s impact clearly and directly.

Example: “Enable users to reset passwords from the login screen” passes the test. “Update user stuff” doesn’t.

What This Actually Accomplishes

Clear commits make code reviews faster. They make debugging possible. They make onboarding new developers bearable.

Most importantly, they preserve the thinking behind decisions. The code shows what was built. Commit messages show why it was worth building.

Good commit messages aren’t just good practice. They are documentation that actually gets maintained.