How to Write Git Commit Messages | Character Limits and Best Practices

8 min read

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. For a broader look at Git workflows, see yoshiwara pleasure quarter books on Amazon are a solid starting point. 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.

Analyzing commit messages across major OSS projects reveals clear trends in subject line length. The Linux kernel has a median subject length of about 55 characters, frequently exceeding the 50-character rule, while projects that adopt Conventional Commits - such as Angular and Vue.js - maintain a median around 45 characters. Since prefixes like feat: or fix: consume 5–10 characters, the effective description portion is limited to 35–40 characters, which naturally encourages concise messages.

The Origin and Technical Rationale of the 50/72 Rule

The 50/72 rule is rooted in the 80-column terminal width. The default output of git log prepends a commit hash (7 characters) and a space to each line, leaving roughly 72 characters for the subject. With git log --oneline, the hash plus space consumes 8 characters, making 72 the effective display width. The recommended 50-character limit serves as a "soft limit" that provides comfortable margin within this 72-character hard boundary.

The 72-character body wrap also has a clear rationale. Patches generated by git format-patch are sent as emails, and mailing list replies prepend > (2 characters) for quoting. With two levels of quoting (> > = 4 characters) plus 4 characters of indentation, 72 characters is the maximum that fits within an 80-column display. This calculation is the foundation of the 72-character rule still widely used today.

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.

ElementCharacter GuidelineReason
Subject line50 characters or lessDisplays without truncation in GitHub's list view
Subject (hard limit)72 characters or lessBeyond 72, GitHub adds an ellipsis (...)
Body line widthWrap at 72 charactersFits standard terminal width (80 cols) with indent margin
Body totalNo limitAdd detailed explanations as needed

GitHub and GitLab differ in where they truncate subject lines. GitHub's commit list truncates at about 72 characters, but the repository top page cuts off at roughly 50 characters. GitLab's commit list displays up to about 80 characters, offering slightly more room than GitHub. To ensure consistent display across both platforms, keeping subjects under 50 characters is the safest approach.

Multibyte Characters in Commit Messages

When writing commit messages in languages with multibyte characters (such as Japanese, Chinese, or Korean), the difference between character count and byte count becomes a significant concern. Git internally handles strings as UTF-8, so a single CJK character consumes 3 bytes. GitHub determines subject truncation based on display width (column count) rather than byte count, and each full-width character occupies 2 columns. This means a maximum of 25 full-width characters fit within a 50-column display width.

Displaying git log in a terminal also raises width calculation issues with multibyte characters. Most terminal emulators render full-width characters at 2-column width based on the East Asian Width property, but some environments (particularly older Windows Command Prompt) miscalculate widths, causing misaligned output. If columns don't line up in git log --oneline, check your terminal's character width settings.

For teams that use non-ASCII commit messages, a hybrid approach - English prefixes with native-language descriptions - works well in practice. For example, fix(auth): ログイン時のセッション復元を修正 preserves the ability to filter by type with git log --oneline --grep="^fix" while remaining readable for native speakers.

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 design philosophy behind this specification centers on automatic integration with Semantic Versioning (SemVer). A feat commit corresponds to a MINOR version bump, fix corresponds to a PATCH bump, and commits containing a BREAKING CHANGE footer signal a MAJOR version bump. This mapping allows tools like semantic-release and standard-version to automatically determine version numbers from commit history.

The basic format is <type>(<scope>): <description>. The scope is optional and indicates the module or component affected.

PrefixPurposeExample
featNew featurefeat(auth): add OAuth2 login support
fixBug fixfix(api): resolve null pointer in user endpoint
docsDocumentation changedocs: update API reference for v2
styleCode style (no behavior change)style: fix indentation in config file
refactorRefactoringrefactor(db): simplify query builder logic
testAdding or fixing teststest: add unit tests for payment module
choreBuild or tooling changeschore: upgrade webpack to v5
perfPerformance improvementperf(search): add index for full-text query
ciCI/CD configurationci: add GitHub Actions workflow

Why Imperative Mood Is Recommended

The recommendation to use imperative mood in English commit messages is rooted in Git's own design. Messages that Git generates automatically - Merge branch 'feature', Revert "Add login form", Cherry-pick from abc1234 - are all in imperative mood. Matching this style in user-written messages creates a unified voice throughout git log output.

An imperative message reads as a description of what happens when the commit is applied. Add user authentication means "this commit adds user authentication," directly expressing the commit's effect. In contrast, Added user authentication (past tense) reads as a report of what was done - a record of work rather than a description of the commit's effect.

When in doubt, try inserting your message into the sentence "If applied, this commit will ___." If applied, this commit will add user authentication reads naturally, while If applied, this commit will added user authentication is grammatically broken.

Good vs. Bad Commit Messages

Bad ExampleProblemGood Example
fix bugWhich bug?fix(cart): prevent duplicate items on rapid click
updateWhat was updated?docs: add setup instructions for local dev
WIPWork-in-progress left in historyfeat(ui): add skeleton loader for product list
asdfghMeaningless stringrefactor: extract validation logic into helper
Fixed the thing that was broken...Verbose, exceeds 50 charsfix(auth): restore session after token refresh

Squash Merge and Revert Message Design

When using squash merge, multiple commits are consolidated into one, so message design differs from regular commits. GitHub's squash merge defaults to using the pull request title as the subject and listing individual commit messages as bullet points in the body. This auto-generated message tends to be verbose. For squash merges, it's more effective to use the pull request description as the body, concisely summarizing the purpose and scope of the change.

For revert commits, the convention is to use Git's auto-generated format: Revert "<original subject>". In the body, include the original commit hash (This reverts commit <hash>.) along with the reason for the revert. Without a reason, it becomes impossible to understand "why it was reverted" when tracing history later. When reverting multiple commits at once, explicitly state the range - such as revert: undo feature X (commits abc..def) - to make history tracking easier.

Team Commit Message Conventions

While personal projects allow flexibility, team development requires unified rules. The following practices help maintain message quality across an organization:

Here's a practical setup combining commitlint and husky. Install with npm install --save-dev @commitlint/cli @commitlint/config-conventional husky, then create commitlint.config.js at the project root with module.exports = { extends: ['@commitlint/config-conventional'] };. Initialize husky with npx husky init, and add npx --no -- commitlint --edit $1 to .husky/commit-msg. This automatically validates every commit message on commit. For more on team-level Git practices, find cock rings on Amazon offer proven workflows.

Overly strict rules can slow development, so adopt them incrementally. Start with prefix standardization, then introduce commitlint once the team is comfortable.

AI-Generated Commit Messages: Benefits and Caveats

GitHub Copilot and various editor extensions offer automatic commit message generation that significantly reduces the effort of writing messages. These tools analyze the diff to summarize what changed, and their accuracy for describing "what was changed" tends to be high.

However, auto-generation has clear limitations. The biggest weakness is the inability to infer "why the change was necessary." Code diffs don't reveal the motivation or business context behind a change, so the "Why" that belongs in the body must be supplied by a human. Additionally, auto-generated messages tend to be verbose and frequently exceed the 50-character subject limit. Rather than using generated output as-is, always review it, trim unnecessary details, and condense it into a concise message.

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. These numbers derive from the 80-column terminal width and email quoting conventions, and they align with the display behavior of GitHub and GitLab. Conventional Commits prefixes make change types instantly recognizable and support automated CHANGELOG generation. When writing messages with multibyte characters, be mindful of display width - full-width characters occupy 2 columns each, so aim for about 25 characters for the subject. Good messages concisely convey "what" and "why," while bad messages are vague and lack information. Use Character Counter to check your commit message length.

Share this article