How to Write Git Commit Messages | Character Limits and Best Practices
Git commit messages are essential clues for understanding a codebase's change history. Well-written messages dramatically improve the efficiency of code reviews and bug investigations months later. Conversely, vague messages become technical debt that drags down the entire team's productivity. This article covers character count guidelines and practical best practices for commit messages. Use Character Counter to verify your message length.
Surprising Facts About Commit Messages
The "50-character subject, 72-character body wrap" convention traces back to the email era. Git creator Linus Torvalds carried over the practice of sending patches via email during Linux kernel development. Email clients typically displayed 80 columns, and accounting for quote markers and indentation, 72 characters was the optimal body width.
According to GitHub data, the average commit message length in open-source projects is estimated at 40–50 characters. However, message quality correlates with project health — projects with very short messages (under 10 characters) tend to have lower bug-fix efficiency.
Basic Structure and Character Count Guidelines
A Git commit message follows a two-part structure: a subject line and a body, separated by a blank line. This structure aligns with how git log --oneline and GitHub's commit list display only the subject.
| Element | Character Guideline | Reason |
|---|---|---|
| Subject line | 50 characters or less | Displays without truncation in GitHub's list view |
| Subject (hard limit) | 72 characters or less | Beyond 72, GitHub adds an ellipsis (...) |
| Body line width | Wrap at 72 characters | Fits standard terminal width (80 cols) with indent margin |
| Body total | No limit | Add detailed explanations as needed |
Conventional Commits and Prefix Usage
Conventional Commits is a specification that gives commit messages a consistent structure. Adding a type prefix to the beginning of each message makes the nature of changes immediately identifiable and enables automated CHANGELOG generation and semantic versioning.
The basic format is <type>(<scope>): <description>. The scope is optional and indicates the module or component affected.
| Prefix | Purpose | Example |
|---|---|---|
feat | New feature | feat(auth): add OAuth2 login support |
fix | Bug fix | fix(api): resolve null pointer in user endpoint |
docs | Documentation change | docs: update API reference for v2 |
style | Code style (no behavior change) | style: fix indentation in config file |
refactor | Refactoring | refactor(db): simplify query builder logic |
test | Adding or fixing tests | test: add unit tests for payment module |
chore | Build or tooling changes | chore: upgrade webpack to v5 |
perf | Performance improvement | perf(search): add index for full-text query |
ci | CI/CD configuration | ci: add GitHub Actions workflow |
Good vs. Bad Commit Messages
| Bad Example | Problem | Good Example |
|---|---|---|
fix bug | Which bug? | fix(cart): prevent duplicate items on rapid click |
update | What was updated? | docs: add setup instructions for local dev |
WIP | Work-in-progress left in history | feat(ui): add skeleton loader for product list |
asdfgh | Meaningless string | refactor: extract validation logic into helper |
Fixed the thing that was broken... | Verbose, exceeds 50 chars | fix(auth): restore session after token refresh |
- Use imperative mood: Write "Add" not "Added," "Fix" not "Fixed." This matches Git's own generated messages (e.g., "Merge branch...").
- No period at the end of the subject: Saves space and follows convention.
- Write "why" in the body: The subject says "what," the body explains "why" the change was necessary.
- One commit = one logical change: Don't bundle unrelated changes into a single commit.
Team Commit Message Conventions
While personal projects allow flexibility, team development requires unified rules. The following practices help maintain message quality across an organization:
- commitlint: Automatically checks messages against Conventional Commits rules. Integrate into CI to catch violations before merge.
- Git hooks (husky): Use
commit-msghooks to validate message format locally. - Templates: Set a shared template with
git config commit.templateto prevent omissions. - Review messages in PRs: Include commit message quality as part of pull request reviews.
Overly strict rules can slow development, so adopt them incrementally. Start with prefix standardization, then introduce commitlint once the team is comfortable.
Conclusion
The widely accepted convention for Git commit messages is a subject line of 50 characters or less with body text wrapped at 72 characters. Conventional Commits prefixes make change types instantly recognizable and support automated CHANGELOG generation. Good messages concisely convey "what" and "why," while bad messages are vague and lack information. Use Character Counter to check your commit message length.