Conventional Commits Standard
Professional teams conventional commits use karti hain. Changelog auto-generate hota hai.
"fix", "update", "changes", "wip", "asdfgh" — these commit messages are useless. They tell you nothing about what changed or why.
Without context, you cannot understand what a commit does without reading the entire diff. Code review becomes harder. Bisecting bugs becomes harder. Generating changelogs is impossible.
"What did I change last week?" — impossible to answer with bad commit messages.
Git log becomes a wall of noise instead of a useful project history. Good commit messages are DOCUMENTATION. They tell the story of your project.
# BAD commit messages
git log --oneline
# abc1234 fix
# def5678 update
# ghi9012 changes
# jkl3456 stuff
# mno7890 wip
# pqr1234 final
# stu5678 final_v2
# vwx9012 final_final_really
# GOOD commit messages (conventional commits)
git log --oneline
# abc1234 feat(auth): add JWT authentication
# def5678 fix(api): handle null response from payment gateway
# ghi9012 chore(deps): update express to v4.18
# jkl3456 docs: update API endpoint documentation
# mno7890 refactor(db): extract connection pool to shared module
# pqr1234 test(auth): add integration tests for login flow
# stu5678 ci: add PostgreSQL service to test workflow
# The good messages tell you:
# - WHAT type of change (feat, fix, chore)
# - WHERE the change happened (scope: auth, api, db)
# - WHY the change was needed (the description)
git bisect shows useless messages. Changelogs cannot be generated. The cost compounds over time — a project with 1000 commits of "fix" and "update" has no useful history.Conventional Commits is a specification for commit message formatting. It provides a simple set of rules for creating an explicit commit history.
Format: type(scope): description
Types:
feat:— new feature (triggers MINOR version in semver)fix:— bug fix (triggers PATCH version in semver)docs:— documentation onlystyle:— formatting, semicolons, whitespace (no code change)refactor:— code restructuring (no feature or fix)perf:— performance improvementtest:— adding or updating testschore:— maintenance, dependencies, build configci:— CI/CD configuration changes
Breaking changes: feat!: or feat(scope)!: description (triggers MAJOR version)
Footer: BREAKING CHANGE: description or Closes #123
# Conventional Commit format
# type(scope): description
# | | |
# | | └─ imperative mood, lowercase, no period
# | └─ optional: module/area of change
# └─ required: type of change
# Examples:
feat(auth): add login with OAuth2
fix(api): resolve timeout on slow network
docs(readme): add installation instructions
style(lint): fix semicolon warnings
refactor(cart): extract pricing logic to service
perf(queries): add index to orders table
test(auth): add unit tests for token validation
chore(deps): update dependencies
ci: add coverage report to workflow
# Breaking change (MAJOR version)
feat(api)!: change response format from XML to JSON
# OR with footer:
feat(api): change response format
BREAKING CHANGE: API responses now use JSON instead of XML
# With issue reference
fix(payments): handle declined cards
Closes #42
# Multi-paragraph commit
feat(dashboard): add real-time analytics
Implement WebSocket connection for live data updates.
This replaces the previous polling approach.
Closes #100Commit messages should be validated automatically, not by human review. Humans forget. Humans take shortcuts. Automation does not.
commitlint checks commit messages against the conventional commits format. @commitlint/config-conventional provides the standard rules.
Combine with Husky to run commitlint on every commit message. Invalid messages are rejected — the commit is not created.
This ensures 100% compliance across the entire team. No exceptions, no gradual degradation.
# Install commitlint + Husky
npm install --save-dev @commitlint/cli @commitlint/config-conventional husky
# Configure commitlint
echo "module.exports = {extends: ['@commitlint/config-conventional']};" > commitlint.config.js
# Setup Husky hook
npx husky init
echo "npx --no -- commitlint --edit \$1" > .husky/commit-msg
# Now try bad commit messages:
git commit -m "update stuff"
# ⧗ input: update stuff
# ✖ type may not be empty [type-empty]
# ✖ subject may not be empty [subject-empty]
# ✖ type must be one of [feat, fix, docs, style, refactor, perf, test, chore, ci] [type-enum]
#
# ✖ 3 problems (3 errors, 0 warnings)
# Good commit passes:
git commit -m "feat(auth): add login page"
# ✔ passes!
# Even better: use commitizen for interactive prompts
npm install -g commitizen cz-conventional-changelog
echo '{"path": "cz-conventional-changelog"}' > ~/.czrc
git cz
# Interactive prompts guide you to write proper messages
Conventional commits enable automatic changelog generation. This is where the real payoff happens.
conventional-changelog reads your commit history and produces a categorized changelog. standard-version goes further — it bumps the version, generates the changelog, and creates a git tag, all automatically.
semantic-release goes even further: analyzes commits, determines version, generates notes, publishes to npm, creates GitHub release.
Without conventional commits, someone must manually write changelogs — error-prone and tedious. With conventional commits, changelogs are a byproduct of your commit discipline.
# Generate changelog from conventional commits
npm install -g conventional-changelog-cli
# First release
conventional-changelog -p angular -i CHANGELOG.md -s -r 0
# Creates CHANGELOG.md with all commits categorized:
# ## 1.0.0 (2024-01-15)
# ### Features
# * **auth:** add login page (abc1234)
# * **dashboard:** add real-time analytics (def5678)
# ### Bug Fixes
# * **api:** handle null response (ghi9012)
# * **payments:** handle declined cards (jkl3456)
# Subsequent releases
conventional-changelog -p angular -i CHANGELOG.md -s
# Using standard-version (bump + changelog + tag)
npm install --save-dev standard-version
npx standard-version
# 1. Analyzes commits since last tag
# 2. Bumps version (feat→minor, fix→patch, !→major)
# 3. Updates CHANGELOG.md
# 4. Creates git tag (v1.1.0)
# 5. Commits version bump + changelog
# Release command
npm run release # → npx standard-version
git push --follow-tags origin mainThe ultimate goal: commit with conventional format, and EVERYTHING else is automated.
Pipeline: commit → commitlint validates → CI runs tests → semantic-release publishes.
semantic-release automates: version bump, changelog, git tag, GitHub release, npm publish. No manual version bumps. No manual changelogs. No manual releases.
The commit message IS the release instruction. feat: = minor release. fix: = patch. ! = major.
This is how professional open-source projects and mature teams operate.
# The complete automated release setup
# 1. Enforce commit format
npm install --save-dev @commitlint/cli @commitlint/config-conventional husky
# 2. Generate changelogs
npm install --save-dev standard-version
# 3. Full automation (optional, advanced)
npm install --save-dev semantic-release
# package.json scripts
cat > package.json << 'EOF'
{
"scripts": {
"commitlint": "commitlint --edit",
"release": "standard-version",
"release:first": "standard-version --first-release"
},
"devDependencies": {
"@commitlint/cli": "^18.0.0",
"@commitlint/config-conventional": "^18.0.0",
"husky": "^9.0.0",
"standard-version": "^9.5.0"
}
}
EOF
# Workflow:
# 1. Developer writes: git commit -m "feat(auth): add OAuth2"
# 2. Husky + commitlint validates the message
# 3. CI runs tests
# 4. On main merge, run: npm run release
# 5. standard-version:
# - Reads commits since last tag
# - Bumps version (2.1.3 → 2.2.0 because feat)
# - Updates CHANGELOG.md
# - Commits + tags v2.2.0
# 6. git push --follow-tags origin main
# 7. GitHub release created automatically
Lo kar liya — Key Points:
- ✅ Conventional Commits standardize commit messages with format type(scope): description
- ✅ Types include feat, fix, docs, style, refactor, perf, test, chore, ci — each has semantic meaning
- ✅ feat: triggers MINOR version bump, fix: triggers PATCH, ! triggers MAJOR (breaking change)
- ✅ commitlint + Husky automatically validates commit messages, rejecting non-conventional formats
- ✅ Conventional commits enable auto-generated changelogs using conventional-changelog or standard-version
- ✅ semantic-release fully automates: version bump, changelog, git tag, GitHub release, npm publish
- ✅ The commit message becomes a machine-readable instruction for your release pipeline
Want to track your progress?
Log in to save your place and pick up where you left off.
Progress track karna chahte ho?
Login karo apni progress save karne ke liye aur jahan chhoda tha wahan se shuru karo.
Login