ModernCalcs

Git Commit Linter

Check a commit message against Conventional Commits and standard Git formatting rules before you commit.

Looks good — passes all checks
Subject line is not empty
Subject ≤ 50 characters (currently 35)
Subject doesn't end with a period
Description starts lowercase (after type/scope)
Convention: 'feat: add login' not 'feat: Add login'.
Follows Conventional Commits format: type(scope): description
Type "feat" is a recognized Conventional Commit type
Written in imperative mood (not past tense)
Blank line between subject and body
Body lines wrapped at ≤ 72 characters

Git Commit Linter: Write Commit Messages Your Team Can Actually Use

A messy commit history makes git log, code review, and automated changelogs harder for everyone. This linter checks your commit message against the widely-used Conventional Commits specification plus classic Git formatting conventions — subject length, imperative mood, and body line wrapping — and tells you exactly what to fix.

Formula
type(scope): short description

Followed by a blank line, then an optional body wrapped at 72 characters.

Why Conventional Commits Format Matters

Prefixing a commit with a type like feat, fix, or chore lets tools like semantic-release automatically determine whether a change is a major, minor, or patch version bump, and lets changelog generators group commits by category without any manual bookkeeping.

The 50/72 Rule

This convention (popularized by Tim Pope's classic 'A Note About Git Commit Messages') says: keep the subject line to 50 characters or less, leave a blank line, then wrap the body at 72 characters. It's not arbitrary — it matches how terminal tools like git log display commit messages by default.

Imperative Mood, Explained

Git's own auto-generated commit messages ('Merge branch', 'Revert...') use imperative mood, so human-written messages should match that style for consistency. A quick test: your subject line should complete the sentence 'If applied, this commit will ___.'

Practical Examples

A Passing Commit Message

Follows Conventional Commits and the 50/72 rule.

  • 1.feat(auth): add password reset flow
  • 2.
  • 3.Sends a reset link via email and expires it after 15 minutes.
  • 4.All checks pass

A Commit Message With Issues

Common mistakes this linter catches.

  • 1.Subject: 'Fixed the bug in login page that caused errors.'
  • 2.Issue: past tense ('Fixed' instead of 'fix')
  • 3.Issue: ends with a period
  • 4.Issue: 55 characters, over the 50-char guideline

Common Conventional Commit Types

  • feat: A new feature
  • fix: A bug fix
  • docs: Documentation only changes
  • refactor: Code change that neither fixes a bug nor adds a feature
  • chore: Maintenance tasks, tooling, dependencies

What This Linter Checks

  • Subject line length (≤ 50 recommended, ≤ 72 hard limit)
  • No trailing period on the subject
  • Conventional Commits type(scope): format
  • Imperative mood in the description
  • Blank line before the body, body wrapped at 72 chars

Frequently Asked Questions

What is Conventional Commits format?

A specification (type(scope): description) for structuring commit messages so tools can automatically generate changelogs and determine semantic version bumps. Common types are feat, fix, docs, style, refactor, perf, test, build, ci, and chore.

Why is imperative mood recommended?

Git itself uses imperative mood for its own generated messages (like 'Merge branch...'), and the convention is that a commit message should complete the sentence 'If applied, this commit will ___' — so 'add feature' reads correctly, but 'added feature' doesn't.

Why does the subject line length matter?

git log --oneline and GitHub's commit list both truncate long subject lines. Keeping it under 50 characters (and never over 72) ensures the summary stays fully readable in every tool that displays it.

Why should the body be wrapped at 72 characters?

It's a long-standing Git convention so that commit messages display cleanly in terminal-based tools like git log, which typically indent output, without needing the terminal to soft-wrap awkwardly.

Does this tool check the diff or just the message?

Just the message. It has no access to your actual code changes — it only lints the text you paste for formatting and structure.

What happens if I don't use a scope?

Scope is optional in Conventional Commits — 'fix: correct off-by-one error' is valid without parentheses. The linter accepts both scoped and unscoped formats.

Is my commit message sent anywhere?

No, all linting runs locally in your browser with plain JavaScript regex checks.