
Dev Git Commit Message
- 129 installs
- 73 repo stars
- Updated July 13, 2026
- vasilyu1983/ai-agents-public
Helps with git & pull requests tasks.
About
dev-git-commit-message is a Claude Code skill for git & pull requests. It helps solo builders move faster with AI-assisted development.
- dev-git-commit-message
- Git & Pull Requests
- AI-coding skill
Dev Git Commit Message by the numbers
- 129 all-time installs (skills.sh)
- +11 installs in the week ending Aug 5, 2026 (Skillselion tracking)
- Ranked #203 of 733 Git & Pull Requests skills by installs in the Skillselion catalog
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/vasilyu1983/ai-agents-public --skill dev-git-commit-messageAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 129 |
|---|---|
| repo stars | ★ 73 |
| Last updated | July 13, 2026 |
| Repository | vasilyu1983/ai-agents-public ↗ |
What it does
Helps with git & pull requests tasks.
Files
Git Commit Message Generator
Auto-generates conventional commit messages from git diffs with tiered format enforcement
Purpose
Analyze staged git changes and generate concise, meaningful commit messages following a tiered Conventional Commits specification. This skill examines file modifications, additions, and deletions to infer the type and scope of changes, producing commit messages that match the importance of the change - from detailed documentation for critical features to concise messages for minor updates.
Key Innovation: Three-tier format system that balances thoroughness for critical commits (feat, fix, security) with efficiency for routine changes (docs, chore, style).
When This Skill Activates
- When
/commit-msgcommand is invoked - When invoked from a
commit-msg/prepare-commit-msghook (if installed) - When user requests commit message suggestions
- When analyzing changes before creating a commit
Core Capabilities
1. Diff Analysis
- Parse
git diff --stagedoutput - Identify modified, added, and deleted files
- Analyze code changes (additions, deletions, modifications)
- Detect patterns across multiple files
2. Change Classification
- Determine commit type from changes:
feat: New features or functionalityfix: Bug fixessecurity: Security fixes or hardeningrefactor: Code restructuring without behavior changedocs: Documentation changesstyle: Formatting, whitespace, code styletest: Adding or modifying testschore: Build process, dependencies, toolingperf: Performance improvementsci: CI/CD configuration changesbuild: Build system changesrevert: Reverting previous commits
3. Scope Detection
- Infer scope from file paths and patterns:
- Directory names (e.g.,
api,auth,ui) - File name patterns (e.g.,
*.test.js→tests) - Framework conventions (e.g.,
components/,services/)
4. Message Generation
- Format:
type(scope): description - Enforce tier limits: Tier 1 summary max 50 chars; Tier 2/3 summary max 72 chars (ideal 50)
- Use imperative mood ("add" not "added")
- Focus on "what" and "why", not "how"
- Provide 2-3 alternative suggestions
Tier System: Smart Format Enforcement
This skill uses a three-tier format system that matches message detail to commit criticality:
Tier 1: Critical Commits (feat, fix, perf, security)
Requirements: Detailed documentation with impact statement
Format:
type(scope): summary line (max 50 chars)
- Detailed description point 1
- Detailed description point 2
- Detailed description point 3
This change [impact statement describing user-facing benefit or risk addressed].
Affected files/components:
- path/to/file1
- path/to/file2Why: Features, fixes, and performance changes affect users directly and need thorough documentation for future reference and changelog generation.
Tier 2: Standard Commits (refactor, test, build, ci)
Requirements: Brief context and file list
Format:
type(scope): summary line (max 72 chars)
Brief explanation of what changed and why (1-2 sentences).
Files: path/to/file1, path/to/file2Why: Internal improvements need context for maintainability but don't require extensive documentation.
Tier 3: Minor Commits (docs, style, chore)
Requirements: Summary line, optional description
Format:
type(scope): summary line (max 72 chars)
[Optional: Additional context if helpful]Why: Documentation and routine maintenance are self-explanatory from the diff; verbose messages add noise.
Workflow
0. Pre-staging typecheck (if project uses TypeScript):
- Run `tsc --noEmit` on changed files before staging
- Fix type errors before committing (avoids pre-commit hook retry loops)
1. Get staged changes (staged only, not working tree):
- git diff --staged --name-status
- git diff --staged --stat
- git diff --staged
2. Load config → frameworks/shared-skills/skills/dev-git-commit-message/config.yaml
3. Analyze changes:
- Count files modified/added/deleted
- Identify primary change type using analysis patterns
- Detect scope from project structure (config.yaml)
- Determine tier (1/2/3) based on commit type
- Extract key modifications
4. Generate commit messages:
- Apply tier-appropriate format
- Primary suggestion (best match)
- Alternative 1 (different scope/angle)
- Alternative 2 (broader/narrower focus)
5. Validate against rules:
- Check forbidden patterns
- Verify required elements present
- Ensure length limits
6. Present to user with explanation and tier infoOptional Modes (If Supported By The Caller)
--validate "<message>": Validate a commit message without generating suggestions (format/type/scope/length/forbidden patterns; then report required Tier 1/2/3 elements if missing).--tier <1|2|3>: Force the tier format (overrides auto-detection).--interactiveor-i: Ask for confirmation of type, scope, and summary before final output.
Output Format
[NOTE] Suggested Commit Messages (based on X files changed)
PRIMARY:
feat(api): add user authentication endpoints
ALTERNATIVES:
1. feat(auth): implement JWT token validation
2. feat: add user authentication system
ANALYSIS:
- 3 files modified in src/api/
- New functions: authenticateUser, generateToken
- Primary change: new feature (authentication)
- Scope detected: api/authConventional Commits Quick Reference
Type Guidelines:
feat: User-facing features or API additionsfix: Corrects incorrect behaviorrefactor: Improves code without changing behaviordocs: README, comments, documentation filesstyle: Formatting only (prettier, eslint --fix)test: Test files or test utilitieschore: Build scripts, package updates, configperf: Measurable performance improvementsci: GitHub Actions, CircleCI, build pipelines
Scope Guidelines:
- Use lowercase
- Be specific but not too narrow
- Match your project's module structure
- Omit if changes span multiple unrelated areas
Description Guidelines:
- Start with lowercase verb
- No period at the end
- Be specific and concise
- Focus on user impact for
featandfix
Edge Cases
Multiple unrelated changes:
- Suggest splitting into separate commits
- If forced to combine, use broader scope or omit scope
Breaking changes:
- Append exclamation mark after type/scope (example: feat(api)!: change auth flow)
- Include BREAKING CHANGE in body (handled by user)
WIP or experimental:
- Use
chore(wip): descriptionorfeat(experimental): description
No meaningful changes:
- Detect and warn: "No staged changes detected"
- Suggest
git addcommands
Integration Points
Pre-commit hook: Triggered before commit (if installed/configured) Slash command: Manual invocation via /commit-msg Direct skill call: From other skills or tools
Best Practices
1. Analyze context: Look at file paths, function names, import statements 2. Prioritize clarity: Prefer obvious descriptions over clever ones 3. Respect conventions: Follow project's existing commit patterns if detected 4. Avoid hallucination: Only describe what's actually in the diff 5. Be concise: 50 chars is ideal, 72 is maximum for first line 6. Stage specific files: Use git add <file1> <file2>, not git add -A or git add ., to avoid pulling in unrelated changes or sensitive files 7. Avoid heredoc in sandboxed shells: Sandboxed environments may block temp file creation for here-documents. Use git commit -m "$(cat <<'EOF'\nmessage\nEOF\n)" or pass -m "message" directly 8. Pre-commit typecheck: Run tsc --noEmit on the staged surface before committing to catch type errors early and avoid retry cascades from pre-commit hooks
Example Analyses
Scenario 1: New React component
Files: src/components/UserProfile.tsx, src/components/UserProfile.test.tsx
Changes: +120 lines, component definition, props interface, tests
Message: feat(components): add UserProfile componentScenario 2: Bug fix in API
Files: src/api/auth.ts
Changes: -5 +8 lines, fix token expiration check
Message: fix(auth): correct token expiration validationScenario 3: Documentation update
Files: README.md, docs/api.md
Changes: +45 lines documentation
Message: docs: update API documentation and READMEScenario 4: Dependency update
Files: package.json, package-lock.json
Changes: version bumps for eslint, typescript
Message: chore(deps): update eslint and typescriptAnalysis Patterns: Smart Type Detection
The skill uses pattern matching to intelligently detect commit types from diffs:
feat Detection
- New files created (especially in src/, components/, api/)
- New functions/classes exported (
export function,export class) - New API routes (
app.get,router.post, etc.) - New assets/skills (in .claude/, custom-gpt/, etc.)
- Threshold: 20+ lines added typically indicates feature
fix Detection
- Test file changes (often indicates bug reproduction)
- New conditionals (validation fixes)
- Error handling additions (
try,catch,throw) - Input validation (
validate,sanitize,check) - Commit message hints: Words like "bug", "issue", "error", "crash"
refactor Detection
- Balanced changes (similar additions and deletions)
- Function renames/moves (same logic, different location)
- No new features or fixes
- Test coverage unchanged
- Keywords: "extract", "move", "rename", "reorganize"
docs Detection
- File patterns:
.md,.txt,README,CHANGELOG,/docs/ - Pure documentation changes (no code modifications)
- Mixed code+docs: Prefer code type, note docs in description
test Detection
- File patterns:
test.js,spec.ts,__tests__/,/tests/ - Test framework patterns:
describe,it,test,expect,assert
style Detection
- CSS/styling files:
.css,.scss,.sass,.less - Formatter configs:
prettier,eslint - Whitespace-only changes
- Keywords: "formatting", "indent", "whitespace"
chore Detection
- Dependency files:
package.json,requirements.txt,Gemfile - Lock files:
package-lock.json,yarn.lock - Config files:
.gitignore,.env - Keywords: "dependency", "deps", "upgrade", "bump"
Configuration
Project-specific configuration loaded from config.yaml:
- Scope mapping: Maps directory patterns to scope names (e.g.,
frameworks/claude-code-kit/**→claude-kit) - Tier rules: Defines which commit types require which tier format
- Forbidden patterns: Blocks commits with generic messages or assistant/tool attribution
- Analysis patterns: Customizes type detection logic for your codebase
- Validation mode:
strict(block),warning(warn), ordisabled
Forbidden Patterns (Validation)
The skill automatically blocks commits with these patterns:
Generic/Vague Messages
- [FAIL] "Update files" → [OK] "docs: update API reference"
- [FAIL] "Fix stuff" → [OK] "fix(auth): correct token validation"
- [FAIL] "Change code" → [OK] "refactor(utils): simplify date formatting"
Assistant/Tool Attribution (Per Repository Policy)
- [FAIL] "Generated with Claude Code"
- [FAIL] "Co-Authored-By: Claude <noreply@anthropic.com>"
- [FAIL] Any assistant/tool attribution in commit messages
Work-in-Progress Markers
- [WARNING] "WIP: feature" (warning - should be squashed before merge)
- [WARNING] "temp: quick fix" (warning - should be squashed)
Missing Type
- [FAIL] Commits without type prefix (feat, fix, docs, etc.)
Error Handling
- No staged changes: Run
git statusand guide user togit addfiles - Binary files only: Note that commit message should mention file types
- Merge conflicts: Detect and suggest
chore: resolve merge conflicts - Git not available: Graceful failure with helpful error message
- Forbidden pattern detected: Show error with examples and block commit (strict mode)
- Missing required elements: List what's missing based on tier requirements
- Length exceeded: Show character count and suggest shortening
Integration with Repository
This skill integrates with the AI-Agents repository standards:
- CLAUDE.md reference: Mandatory skill usage before commits
- config.yaml: Project-specific scope mappings and rules
- Pre-commit hook: Automatic activation before git commits
- CONTRIBUTING.md: Commit guidelines for contributors
---
Commit Message Template
[assets/template-commit-message.md](assets/template-commit-message.md) — Copy-paste template and good/bad examples.
Use it to standardize type(scope): summary messages and keep history automation-friendly.
---
Security-Sensitive Commits
[assets/template-security-commits.md](assets/template-security-commits.md) — Guide for handling security-sensitive changes.
Key Sections
- Pre-Commit Security Checklist — Secrets detection, prohibited patterns
- Security-Related Commit Types — Security fix, enhancement, configuration
- Accidental Secret Commits — Immediate response, rotation, history cleanup
- Sensitive File Patterns — .gitignore templates, files that should never be committed
- Audit Trail Requirements — CVE, CVSS, CWE metadata for security commits
Do / Avoid
GOOD: Do
- Run secrets scan before every commit
- Rotate secrets immediately if exposed
- Use environment variables for credentials
- Document security fixes with CVE/CVSS
- Require security team review for auth changes
- Keep .gitignore updated for secret patterns
BAD: Avoid
- Committing secrets "temporarily"
- Using hardcoded credentials in tests
- Storing real credentials in example files
- Assuming deleted secrets are safe
- Committing before secrets scan completes
- Using generic commit messages for security fixes
Anti-Patterns
| Anti-Pattern | Problem | Fix |
|---|---|---|
| "Add secrets later" | Secrets committed accidentally | Use env vars from start |
| Secrets in tests | Real credentials in repo | Use mocks/test credentials |
| Force push to hide | History still recoverable | Rotate + document |
| Vague security commits | No audit trail | Include CVE/CVSS |
| No pre-commit scan | Secrets reach remote | Install gitleaks hook |
---
Optional: AI/Automation
Note: AI suggestions should preserve human intent.
- Commit message suggestions — Draft from diff analysis
- Type detection — Pattern-based commit type inference
- Scope detection — Auto-detect from changed paths
Bounded Claims
- AI-generated messages need human review and modification
- Automated type detection may miss context
- Security commits always need human judgment
---
Resources
| Resource | Purpose |
|---|---|
| references/conventional-commits-guide.md | Conventional Commits spec and tooling |
| references/commit-message-antipatterns.md | Common bad patterns, detection, linting |
| references/monorepo-commit-conventions.md | Scope strategies for multi-package repos |
| references/changelog-generation-guide.md | Changelog tooling setup, CI integration |
| data/sources.json | Curated external sources |
---
Version: 2.1.1 Last Updated: 2026-01-26 Repository: AI-Agents (documentation repository) Conventional Commits Spec: <https://www.conventionalcommits.org/>
Fact-Checking
- Use web search/web fetch to verify current external facts, versions, pricing, deadlines, regulations, or platform behavior before final answers.
- Prefer primary sources; report source links and dates for volatile information.
- If web access is unavailable, state the limitation and mark guidance as unverified.
Commit Message Template + Examples (Good/Bad)
Use this template to keep history readable and automation-friendly.
---
Core
Template
type(scope): summary
Why:
- ...
What:
- ...
Notes:
- Risks/rollback: ...
- Tests: ...Rules:
- Summary is imperative mood, no trailing period, <= 72 chars.
scopeis optional; use a stable module name.- Body explains intent and impact; avoid implementation trivia.
Conventional Commit Types (Common)
feat: new user-visible capabilityfix: bug fixperf: measurable performance improvementrefactor: code change without behavior changedocs: documentation onlytest: tests onlychore: maintenance, tooling, depsci: pipeline and build config
Good Examples
feat(api): add cursor pagination for /users
Why:
- Prevent unbounded scans on large tenants
What:
- Add cursor param + stable ordering
- Document response meta and examples
Notes:
- Tests: unit + contractfix(auth): reject expired refresh tokens
Why:
- Prevent session extension past TTL
What:
- Validate token expiry before rotation
Notes:
- Tests: added regression caseBad Examples (Avoid)
fix: stuffupdatechore: generated with <assistant>---
Do / Avoid
Do
- Do describe intent and impact (what and why)
- Do split unrelated changes into separate commits
- Do include tests/rollback notes for risky changes
Avoid
- Avoid vague summaries (“fix”, “update”, “changes”)
- Avoid mixing refactors and features in one commit
- Avoid attribution strings in commit messages (repository policy)
---
Optional: AI/Automation
- Generate initial suggestions from staged diff (human-edited)
- Draft a changelog-friendly summary for
feat/fix(human-verified)
Bounded Claims
- Automated suggestions can misclassify changes; humans own correctness.
Security-Sensitive Commits Guide
Best practices for handling security-sensitive changes in git commits.
---
Pre-Commit Security Checklist
Before Every Commit
- [ ] No hardcoded secrets (API keys, passwords, tokens)
- [ ] No credentials in configuration files
- [ ] No private keys or certificates
- [ ] No sensitive environment variables
- [ ] No internal URLs or IP addresses
- [ ] No PII (personal identifiable information)
- [ ] No proprietary algorithms exposed unintentionally
Secrets Detection Tools
# Gitleaks (recommended)
gitleaks detect --source . --verbose
# TruffleHog (alternative)
trufflehog filesystem .
# git-secrets (AWS-focused)
git secrets --scan
# detect-secrets (Yelp)
detect-secrets scanPre-Commit Hook Setup
# .pre-commit-config.yaml
repos:
- repo: https://github.com/gitleaks/gitleaks
rev: v8.18.0
hooks:
- id: gitleaks
- repo: https://github.com/Yelp/detect-secrets
rev: v1.4.0
hooks:
- id: detect-secrets
args: ['--baseline', '.secrets.baseline']Install:
pip install pre-commit
pre-commit install---
Security-Related Commit Types
Security Fix Commits
fix(security): patch XSS vulnerability in user input
Sanitize user input in comment fields to prevent
stored XSS attacks.
CVE: CVE-2024-12345
Severity: High
CVSS: 7.5
Closes #456Security Enhancement Commits
feat(security): add rate limiting to login endpoint
Implement token bucket rate limiting to prevent
brute force attacks on authentication.
- 5 attempts per 15 minutes per IP
- Exponential backoff after threshold
- Audit logging for rate limit events
Security-Review-By: @security-teamSecurity Configuration Changes
chore(security): rotate API keys for payment service
Replace expired API keys with new credentials.
Old keys revoked in provider dashboard.
NOTE: Credentials stored in HashiCorp Vault, not in repo.---
Handling Accidental Secret Commits
Immediate Response
# 1. Remove from working directory
rm path/to/secret-file
# 2. Remove from git history (if not pushed)
git reset --soft HEAD~1
# Edit to remove secret
git commit
# 3. If already pushed: ROTATE THE SECRET IMMEDIATELY
# Then remove from history:
# Option A: Interactive rebase (small number of commits)
git rebase -i HEAD~5
# Mark the commit as 'edit', remove secret, continue
# Option B: BFG Repo Cleaner (large history)
bfg --delete-files secret-file.txt
bfg --replace-text replacements.txt
# Option C: git-filter-repo (modern alternative)
git filter-repo --path secret-file.txt --invert-pathsPost-Incident Checklist
- [ ] Secret rotated/revoked immediately
- [ ] Affected systems identified
- [ ] Access logs reviewed for unauthorized use
- [ ] Commit removed from all branches
- [ ] Force push to remote (with team notification)
- [ ] Incident documented
- [ ] Pre-commit hooks added to prevent recurrence
---
Sensitive File Patterns
.gitignore for Secrets
# Environment files
.env
.env.local
.env.*.local
*.env
# Credentials
credentials.json
service-account.json
*.pem
*.key
*.p12
*.pfx
# AWS
.aws/credentials
*.aws
# GCP
gcloud-*.json
*-credentials.json
# Terraform
*.tfvars
.terraform/
terraform.tfstate*
# IDE
.idea/
.vscode/settings.json
# Database
*.sqlite
*.db
dump.sqlFiles That Should NEVER Be Committed
| Pattern | Contains |
|---|---|
*.pem, *.key | Private keys |
.env* | Environment variables |
credentials.json | Service account keys |
*.tfvars | Terraform secrets |
id_rsa*, id_ed25519* | SSH keys |
*.p12, *.pfx | Certificates |
secrets.yaml | Kubernetes secrets |
vault-*.json | Vault tokens |
---
Reversible vs Irreversible Changes
Reversible (Can Be Amended)
- Commit message typos
- Wrong branch
- Forgotten files
- Formatting issues
# Amend last commit (before push)
git commit --amend
# Interactive rebase for older commits
git rebase -i HEAD~3Irreversible After Push (Treat as Permanent)
- Secrets in commit content
- PII in commit messages
- Breaking changes to public API
- License-incompatible code
[WARNING] Even after removal from git history, secrets may be:
- Cached by GitHub/GitLab
- Indexed by search engines
- Mirrored by CI systems
- Downloaded by other developers
>
ALWAYS rotate exposed secrets.
---
Audit Trail Requirements
When to Include Audit Information
fix(security): address authentication bypass
SECURITY ADVISORY: SA-2024-001
CVE: CVE-2024-XXXXX
CVSS: 9.1 (Critical)
CWE: CWE-287 (Improper Authentication)
Reported-By: security@researcher.com
Reviewed-By: @security-lead
Approved-By: @cto
Disclosure: Coordinated (public disclosure in 30 days)Security Commit Metadata
| Field | When Required | Format |
|---|---|---|
| CVE | Known vulnerability | CVE-YYYY-NNNNN |
| CVSS | Security fix | Score (e.g., 7.5) |
| CWE | Vulnerability fix | CWE-NNN |
| Reviewed-By | Security changes | @username |
| Advisory | Public disclosure | SA-YYYY-NNN |
---
Branch Protection for Security
GitHub Branch Protection Settings
# Recommended settings for main branch
branch_protection:
required_reviews: 2
dismiss_stale_reviews: true
require_code_owner_review: true
required_status_checks:
- security-scan
- gitleaks
- dependency-check
enforce_admins: true
restrict_pushes: trueCODEOWNERS for Security Files
# .github/CODEOWNERS
/.env.example @security-team
/auth/ @security-team
/security/ @security-team
*.pem @security-team
/terraform/*.tf @security-team @devops---
Do / Avoid
GOOD: Do
- Run secrets scan before every commit
- Rotate secrets immediately if exposed
- Use environment variables for credentials
- Document security fixes with CVE/CVSS
- Require security team review for auth changes
- Keep .gitignore updated for secret patterns
- Use pre-commit hooks for automated scanning
BAD: Avoid
- Committing secrets "temporarily"
- Using hardcoded credentials in tests
- Storing real credentials in example files
- Assuming deleted secrets are safe
- Committing before secrets scan completes
- Using generic commit messages for security fixes
- Skipping review for "small" security changes
---
Anti-Patterns
| Anti-Pattern | Problem | Fix |
|---|---|---|
| "Add secrets later" | Secrets committed accidentally | Use env vars from start |
| Secrets in tests | Real credentials in repo | Use mocks/test credentials |
| Force push to hide | History still recoverable | Rotate + document |
| Vague security commits | No audit trail | Include CVE/CVSS |
| Single reviewer | Missed vulnerabilities | Require 2+ reviewers |
| No pre-commit scan | Secrets reach remote | Install gitleaks hook |
---
Optional: AI/Automation
Note: AI can detect patterns but should not be sole gatekeeper for security.
Automated Detection
- Secret pattern matching (entropy-based)
- Known credential format detection
- PII identification (names, emails, SSNs)
AI-Assisted Review
- Commit message security classification
- Dependency vulnerability correlation
- Breaking change impact analysis
Bounded Claims
- AI detection has false positives/negatives
- Human review required for security commits
- Automated alerts need triage, not auto-action
---
Related Resources
- dev-git-workflow/references/validation-checklists.md
- Conventional Commits
- Gitleaks
---
Last Updated: December 2025
# Git Commit Message Generator - Project Configuration
# This file customizes the skill behavior for your specific repository
project:
name: "AI-Agents"
type: "documentation-repository"
description: "AI prompt and agent library with multi-framework support"
# Directory patterns → Scope names
# Patterns are matched in order (first match wins)
scope_mapping:
# Framework-specific
"frameworks/claude-code-kit/**": "claude-kit"
"frameworks/codex-kit/**": "codex-kit"
"frameworks/gemini-kit/**": "gemini-kit"
"frameworks/shared-foundations/**": "shared-foundations"
"frameworks/a-smart-deploy/**": "smart-deploy"
# Custom GPT categories
"custom-gpt/education/**": "gpt-education"
"custom-gpt/lifestyle/**": "gpt-lifestyle"
"custom-gpt/productivity/**": "gpt-productivity"
"custom-gpt/programming/**": "gpt-programming"
"custom-gpt/research-n-analysis/**": "gpt-research"
"custom-gpt/writing/**": "gpt-writing"
"custom-gpt/altery/**": "gpt-altery"
"custom-gpt/**": "gpt"
# AI Agents
"ai-agents/**": "agents"
# Skills (cross-framework)
"**/skills/ai-prompt-engineering/**": "prompt-engineering"
"**/skills/ai-agents/**": "ai-agents"
"**/skills/ai-llm/**": "llm-engineering"
"**/skills/**": "skills"
# Documentation
"docs/agents/**": "docs-agents"
"docs/formatting/**": "docs-formatting"
"docs/diagrams/**": "docs-diagrams"
"docs/reference/**": "docs-reference"
"docs/**": "docs"
# Repository infrastructure
".claude/**": "tooling"
".cursor/**": "tooling"
".github/**": "ci"
# Root config files
"CLAUDE.md": "meta"
"GEMINI.md": "meta"
"AGENTS.md": "meta"
"README.md": "docs"
# Conventional Commits Configuration
conventional_commits:
# Enforce scope for these types
require_scope_for: ["feat", "fix", "perf", "security"]
# Optional scope for these types
optional_scope_for: ["refactor", "test", "build", "ci", "docs", "style", "chore"]
# Maximum lengths
max_summary_length: 72 # Hard limit
ideal_summary_length: 50 # Soft limit (warn if exceeded)
# Summary line rules
imperative_mood: true
lowercase_description: true
no_period_at_end: true
# Multi-scope handling
allow_multiple_scopes: true
multi_scope_separator: ","
multi_scope_threshold: 3 # If >3 files across scopes, suggest broader scope
# Tier System: Different format requirements by commit type
tier_rules:
tier1:
types: ["feat", "fix", "perf", "security"]
description: "Critical commits requiring detailed documentation"
requirements:
- summary_line
- detailed_description
- affected_components
- impact_statement
format: |
<type>(<scope>): <summary>
- Detailed change 1
- Detailed change 2
- Detailed change 3
This change [impact statement - what user-facing benefit or risk addressed].
Affected files/components:
- path/to/file1
- path/to/file2
tier2:
types: ["refactor", "test", "build", "ci"]
description: "Standard commits requiring brief context"
requirements:
- summary_line
- brief_description
- affected_files
format: |
<type>(<scope>): <summary>
Brief explanation of what changed and why.
Files: path/to/file1, path/to/file2
tier3:
types: ["docs", "style", "chore"]
description: "Minor commits with optional description"
requirements:
- summary_line
- optional_description
format: |
<type>(<scope>): <summary>
[Optional: Additional context if needed]
# Forbidden Patterns (case-insensitive)
forbidden_patterns:
# Generic/vague messages
- pattern: "^(update|fix|change)\\s+(files?|stuff|things?|code)$"
reason: "Too vague - specify what was updated/fixed"
examples:
- "Update files → docs: update API reference"
- "Fix stuff → fix(auth): correct token validation"
# AI attribution (per your requirements)
- pattern: "generated with.*claude"
reason: "AI attribution not allowed in commit messages"
- pattern: "co-authored-by:\\s*claude"
reason: "AI attribution not allowed in commit messages"
- pattern: "noreply@anthropic\\.com"
reason: "AI attribution not allowed in commit messages"
# Work-in-progress markers
- pattern: "^wip[:\\s]"
reason: "WIP commits should be squashed before merging"
severity: "warning" # Warning only, not blocking
- pattern: "^temp[:\\s]"
reason: "Temporary commits should be squashed before merging"
severity: "warning"
# Missing/invalid type prefix (Conventional Commits)
- pattern: "^(?!((feat|fix|perf|security|refactor|test|build|ci|docs|style|chore|revert))(\\([a-z0-9][a-z0-9,._-]*\\))?(!)?:\\s).+"
reason: "Commit must start with conventional prefix: type(scope): summary"
# Poor descriptions
- pattern: "^(feat|fix|docs)\\([^)]+\\):\\s*(add|update|fix|change)\\s*$"
reason: "Description too vague - specify what was added/fixed"
examples:
- "feat(api): add → feat(api): add user search endpoint"
# Required Elements by Type
required_elements:
feat:
- "What new functionality was added"
- "Which module/component affected"
- "User-facing benefit or use case"
fix:
- "What bug was fixed"
- "What incorrect behavior occurred"
- "How it was corrected"
security:
- "What vulnerability was addressed"
- "Severity level (if applicable)"
- "Whether it affects existing users"
perf:
- "What was optimized"
- "Measurable improvement (if available)"
- "Any trade-offs made"
refactor:
- "What was refactored"
- "Why the refactor was needed"
- "Confirmation of no behavior change"
# Analysis Patterns: How to detect commit types from diffs
analysis_patterns:
feat:
indicators:
file_patterns:
- "new file"
- "create mode"
code_patterns:
- "^\\+.*\\bfunction\\s+\\w+\\(" # New functions
- "^\\+.*\\bclass\\s+\\w+" # New classes
- "^\\+.*\\bexport\\s+(function|class|const)" # New exports
- "^\\+.*\\b(app\\.(get|post|put|delete)|router\\.)" # New routes
- "^\\+.*\\bskill\\s*:" # New skills
- "^\\+.*\\btemplate" # New templates
minimum_additions: 20 # Threshold for feature vs. minor update
fix:
indicators:
file_patterns:
- "test\\.(js|ts|py|go)" # Test file changes often indicate bug fixes
code_patterns:
- "^\\+.*\\bif\\s*\\(" # New conditionals (often validation fixes)
- "^\\+.*\\b(try|catch|throw|error)" # Error handling
- "^-.*\\b(bug|issue|error|fail)" # Removing buggy code
- "^\\+.*\\b(validate|sanitize|check)" # Input validation
commit_message_hints:
- "\\b(bug|issue|error|crash|fail)\\b"
refactor:
indicators:
balanced_changes: true # Similar additions and deletions
code_patterns:
- "^-.*\\bfunction\\s+\\w+\\(.*\\n^\\+.*\\bfunction\\s+\\w+\\(" # Renamed functions
- "extract|move|rename|reorganize" # Common refactor words
no_new_features: true
test_coverage_unchanged: true
docs:
indicators:
file_patterns:
- "\\.md$"
- "\\.txt$"
- "README"
- "CHANGELOG"
- "/docs/"
exclude_with_code: false # Allow mixed code + docs
test:
indicators:
file_patterns:
- "test\\.(js|ts|py|go|java)"
- "spec\\.(js|ts)"
- "__tests__/"
- "/tests?/"
code_patterns:
- "^\\+.*(describe|it|test|expect|assert)\\("
style:
indicators:
file_patterns:
- "\\.(css|scss|sass|less)$"
- "prettier"
- "eslint"
code_patterns:
- "^[+-]\\s*$" # Only whitespace changes
- "formatting|indent|whitespace"
chore:
indicators:
file_patterns:
- "package\\.json"
- "package-lock\\.json"
- "yarn\\.lock"
- "requirements\\.txt"
- "Gemfile"
- "\\.gitignore"
- "\\.env"
commit_message_hints:
- "\\b(dependency|dependencies|deps|upgrade|bump)\\b"
# Scope Detection Strategy
scope_detection:
strategy: "smart" # Options: smart, directory, manual, auto
# Smart detection rules
smart_rules:
# Single directory → Use that scope
- condition: "single_directory"
action: "use_directory_scope"
# Multiple files in same framework → Use framework scope
- condition: "same_framework"
action: "use_framework_scope"
# Changes span multiple frameworks → Use broader scope
- condition: "multiple_frameworks"
action: "suggest_broader_scope"
suggestions: ["frameworks", "cross-framework"]
# All files in docs/ → Use 'docs' scope
- condition: "all_in_docs"
action: "use_docs_scope"
# Mixed code + docs → Prefer code scope, note docs in description
- condition: "mixed_code_docs"
action: "prefer_code_scope"
# When to omit scope
omit_scope_when:
- "changes span more than 5 different scopes"
- "repository-wide refactor"
- "general documentation updates"
# Output Preferences
output:
show_analysis: true # Show reasoning behind suggestions
show_alternatives: true # Show alternative commit messages
alternative_count: 2 # Number of alternatives to generate
show_character_count: true # Display character count for summary
show_tier: true # Show which tier applies
show_validation: true # Show validation results
color_coding: true # Use color codes for terminal output
# Validation Behavior
validation:
mode: "strict" # Options: strict, warning, disabled
block_on_forbidden: true # Block commits with forbidden patterns
block_on_missing_required: true # Block if required elements missing
block_on_length_exceeded: true # Block if summary too long
allow_override: true # Allow --no-verify bypass
show_examples_on_error: true # Show examples when validation fails
# Integration Settings (informational; no automation reads these fields)
integration:
update_claude_md: false # Docs live in CLAUDE.md/AGENTS.md
create_contributing_guide: false # CONTRIBUTING.md is maintained manually
install_git_hooks: false # Auto-install git hooks (set true to enable)
# Metrics & Reporting
metrics:
track_compliance: false # Track format compliance over time
generate_reports: false # Generate monthly compliance reports
report_path: ".claude/skills/dev-git-commit-message/reports/"
# Version
version: "2.1.1"
last_updated: "2026-01-26"
{
"metadata": {
"title": "Git Commit Message - Sources",
"description": "Primary sources for commit message conventions, Conventional Commits, and security-sensitive git hygiene",
"last_updated": "2026-01-17"
},
"standards": [
{
"name": "Conventional Commits Specification 1.0.0",
"url": "https://www.conventionalcommits.org/en/v1.0.0/",
"description": "Authoritative Conventional Commits standard",
"add_as_web_search": true
},
{
"name": "Semantic Versioning 2.0.0",
"url": "https://semver.org/",
"description": "SemVer specification",
"add_as_web_search": false
},
{
"name": "Keep a Changelog",
"url": "https://keepachangelog.com/",
"description": "Changelog format standard",
"add_as_web_search": false
}
],
"git_docs": [
{
"name": "Git Documentation",
"url": "https://git-scm.com/doc",
"description": "Official Git documentation hub",
"add_as_web_search": false
},
{
"name": "Pro Git (book)",
"url": "https://git-scm.com/book/en/v2",
"description": "Git best practices and workflows",
"add_as_web_search": false
},
{
"name": "How to Write a Git Commit Message (cbea.ms)",
"url": "https://cbea.ms/git-commit/",
"description": "Classic, high-signal commit message guidance",
"add_as_web_search": false
}
],
"tooling": [
{
"name": "commitlint",
"url": "https://commitlint.js.org/",
"description": "Lint commit messages against Conventional Commits rules",
"add_as_web_search": true
},
{
"name": "semantic-release",
"url": "https://semantic-release.gitbook.io/",
"description": "Automated releases driven by commit messages",
"add_as_web_search": true
},
{
"name": "pre-commit framework",
"url": "https://pre-commit.com/",
"description": "Manage pre-commit hooks (formatting, linting, secrets scanning)",
"add_as_web_search": true
}
],
"security": [
{
"name": "Gitleaks",
"url": "https://gitleaks.io/",
"description": "Secret scanning for git repos (local + CI integration)",
"add_as_web_search": true
},
{
"name": "TruffleHog",
"url": "https://github.com/trufflesecurity/trufflehog",
"description": "Find and verify leaked secrets in git history",
"add_as_web_search": true
},
{
"name": "CVSS v4.0 Calculator (FIRST)",
"url": "https://www.first.org/cvss/calculator/4.0",
"description": "Severity scoring reference for security-related commits and advisories",
"add_as_web_search": false
}
],
"optional_ai": [
{
"name": "aicommits (Optional)",
"url": "https://github.com/Nutlope/aicommits",
"description": "AI commit message generator CLI (optional; must be human-edited)",
"add_as_web_search": true,
"optional": true
},
{
"name": "JetBrains AI Assistant VCS Integration (Optional)",
"url": "https://www.jetbrains.com/help/ai-assistant/ai-in-vcs-integration.html",
"description": "AI-powered commit message generation in JetBrains IDEs (optional; requires human review)",
"add_as_web_search": true,
"optional": true
},
{
"name": "Windsurf AI Commit Messages (Optional)",
"url": "https://docs.windsurf.com/windsurf/ai-commit-message",
"description": "AI-powered commit message generation in Windsurf IDE (optional; requires human review)",
"add_as_web_search": true,
"optional": true
},
{
"name": "AI Commit VS Code Extension (Optional)",
"url": "https://marketplace.visualstudio.com/items?itemName=Sitoi.ai-commit",
"description": "VS Code extension for AI-generated conventional commits (optional; requires human review)",
"add_as_web_search": true,
"optional": true
}
]
}
Changelog Generation Guide
Generating changelogs from commit history using Conventional Commits. Covers tooling, configuration, output format, CI integration, manual overrides, and versioning automation.
---
Table of Contents
1. Tools Overview 2. Setup: conventional-changelog 3. Setup: standard-version 4. Setup: semantic-release 5. Setup: changesets 6. Output Format: Keep a Changelog 7. Customization 8. CI Integration 9. Manual Overrides 10. Versioning Integration 11. Example Workflow 12. Do / Avoid 13. Checklist: Changelog Release
---
Tools Overview
| Tool | Auto Version Bump | Auto Changelog | Auto Publish | Monorepo Support | Human Approval Step |
|---|---|---|---|---|---|
| conventional-changelog | No | Yes | No | Via --commit-path | N/A (generate only) |
| standard-version | Yes | Yes | No | Limited | Yes (review before push) |
| semantic-release | Yes | Yes | Yes | Via plugins | No (fully automated) |
| changesets | Yes | Yes | Yes | Built-in | Yes (changeset files) |
Choosing a tool:
- Need full automation with no human gate? Use semantic-release.
- Want to review changelog before release? Use standard-version or changesets.
- Need per-package changelogs in a monorepo? Use changesets.
- Only need changelog generation (no versioning)? Use conventional-changelog directly.
---
Setup: conventional-changelog
The lowest-level tool. Generates a changelog from commit history without touching versions.
npm install --save-dev conventional-changelog-cliAdd to package.json:
{
"scripts": {
"changelog": "conventional-changelog -p conventionalcommits -i CHANGELOG.md -s",
"changelog:all": "conventional-changelog -p conventionalcommits -i CHANGELOG.md -s -r 0"
}
}-p conventionalcommitsselects the Conventional Commits preset-i CHANGELOG.mdreads from and appends to the existing changelog-swrites output to the same file as input-r 0regenerates the entire changelog from all commits (not just since last tag)
Per-Package Changelog (Monorepo)
conventional-changelog -p conventionalcommits -i packages/auth/CHANGELOG.md -s \
--commit-path packages/auth---
Setup: standard-version
Handles version bumping + changelog generation + git tagging. Does not publish.
npm install --save-dev standard-version{
"scripts": {
"release": "standard-version",
"release:minor": "standard-version --release-as minor",
"release:major": "standard-version --release-as major",
"release:dry": "standard-version --dry-run"
}
}Configuration via .versionrc or .versionrc.json:
{
"types": [
{ "type": "feat", "section": "Features" },
{ "type": "fix", "section": "Bug Fixes" },
{ "type": "perf", "section": "Performance" },
{ "type": "refactor", "section": "Refactoring", "hidden": true },
{ "type": "docs", "section": "Documentation", "hidden": true },
{ "type": "style", "hidden": true },
{ "type": "chore", "hidden": true },
{ "type": "test", "hidden": true },
{ "type": "ci", "hidden": true },
{ "type": "build", "hidden": true }
],
"commitUrlFormat": "https://github.com/org/repo/commit/{{hash}}",
"compareUrlFormat": "https://github.com/org/repo/compare/{{previousTag}}...{{currentTag}}"
}Note: standard-version is in maintenance mode. The maintainers recommend migrating to release-please or semantic-release for new projects.
---
Setup: semantic-release
Fully automated: analyzes commits, determines version, generates changelog, publishes, creates GitHub release.
npm install --save-dev semantic-release @semantic-release/changelog @semantic-release/gitrelease.config.js:
module.exports = {
branches: ['main'],
plugins: [
['@semantic-release/commit-analyzer', {
preset: 'conventionalcommits',
releaseRules: [
{ type: 'feat', release: 'minor' },
{ type: 'fix', release: 'patch' },
{ type: 'perf', release: 'patch' },
{ type: 'revert', release: 'patch' },
{ breaking: true, release: 'major' },
],
}],
['@semantic-release/release-notes-generator', {
preset: 'conventionalcommits',
presetConfig: {
types: [
{ type: 'feat', section: 'Features' },
{ type: 'fix', section: 'Bug Fixes' },
{ type: 'perf', section: 'Performance' },
],
},
}],
['@semantic-release/changelog', { changelogFile: 'CHANGELOG.md' }],
['@semantic-release/git', {
assets: ['CHANGELOG.md', 'package.json', 'package-lock.json'],
message: 'chore(release): ${nextRelease.version} [skip ci]',
}],
'@semantic-release/github',
],
};---
Setup: changesets
Human-in-the-loop approach. Developers create changeset files describing their changes; the release process consumes them.
npx changeset initCreating a Changeset
npx changeset
# Prompts: which packages? major/minor/patch? summary?This creates a markdown file in .changeset/:
---
"@acme/auth": minor
"@acme/api": patch
---
Add OAuth2 PKCE flow to auth package. API package updated to
accept new token format.Consuming Changesets on Release
npx changeset version # Bumps versions, writes CHANGELOGs, deletes consumed changesets
npx changeset publish # Publishes to npm---
Output Format: Keep a Changelog
The Keep a Changelog format is the de facto standard. All major tools can produce it.
# Changelog
## [2.1.0] - 2026-02-10
### Features
- **auth**: add OAuth2 PKCE flow ([#234](https://github.com/org/repo/pull/234))
- **search**: add full-text product search
### Bug Fixes
- **cart**: prevent negative quantity on item update ([#567](https://github.com/org/repo/issues/567))
- **checkout**: correct address validation for PO boxes
### Performance
- **images**: implement progressive JPEG loading
### BREAKING CHANGES
- **auth**: session-based tokens removed; migrate to JWT ([migration guide](./docs/migration-2.1.md))
## [2.0.1] - 2026-01-15
### Bug Fixes
- **api**: correct pagination offset calculationStandard Sections
| Section | Maps From | SemVer Impact |
|---|---|---|
| Features | feat commits | Minor bump |
| Bug Fixes | fix commits | Patch bump |
| Performance | perf commits | Patch bump |
| BREAKING CHANGES | ! or BREAKING CHANGE footer | Major bump |
| Documentation | docs commits | No bump (usually hidden) |
| Refactoring | refactor commits | No bump (usually hidden) |
---
Customization
Grouping by Type
Control which types appear and under what heading using .versionrc (standard-version) or presetConfig (semantic-release):
{
"types": [
{ "type": "feat", "section": "New Features" },
{ "type": "fix", "section": "Fixes" },
{ "type": "perf", "section": "Performance Improvements" },
{ "type": "refactor", "section": "Internal Changes", "hidden": false },
{ "type": "chore", "hidden": true },
{ "type": "docs", "hidden": true }
]
}Filtering by Scope
Hide internal-only changes from the public changelog:
// release.config.js — custom transform
['@semantic-release/release-notes-generator', {
preset: 'conventionalcommits',
writerOpts: {
transform: (commit, context) => {
// Hide internal scopes from public changelog
const internalScopes = ['deps', 'ci', 'infra', 'internal'];
if (internalScopes.includes(commit.scope)) return;
return commit;
},
},
}],Adding PR Links
Most tools support linking commits to PRs or issues:
{
"issueUrlFormat": "https://github.com/org/repo/issues/{{id}}",
"commitUrlFormat": "https://github.com/org/repo/commit/{{hash}}",
"userUrlFormat": "https://github.com/{{user}}"
}---
CI Integration
Auto-Generate Changelog on Release
# GitHub Actions: release on push to main
name: Release
on:
push:
branches: [main]
jobs:
release:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
persist-credentials: false
- uses: actions/setup-node@v4
with:
node-version: 20
- run: npm ci
- name: Release
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
run: npx semantic-releaseChangesets Bot (for PR-Based Workflow)
# GitHub Actions: check for changeset in PRs
name: Changeset Check
on: pull_request
jobs:
check:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: changesets/action@v1
with:
publish: npx changeset publish
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}---
Manual Overrides
Editing Generated Changelogs
After running standard-version --dry-run or changeset version:
1. Review the generated CHANGELOG.md 2. Edit entries for clarity, grammar, or context 3. Add migration notes under a ### Migration subsection 4. Remove noise entries (internal refactors that leaked into public changelog) 5. Commit the edited changelog as part of the release commit
Adding Migration Notes
## [3.0.0] - 2026-02-10
### BREAKING CHANGES
- **auth**: replace API key auth with OAuth2 tokens
### Migration
To migrate from v2.x to v3.0:
1. Register your application at https://dashboard.example.com/oauth
2. Replace `X-API-Key` header with `Authorization: Bearer <token>`
3. Update SDK: `npm install @acme/sdk@3`
See [full migration guide](./docs/migration-v3.md).Overriding Version Bumps
When auto-detection gets it wrong:
# Force a specific version with standard-version
npx standard-version --release-as 2.0.0
# Force with semantic-release (via commit)
# Add a commit with BREAKING CHANGE footer to trigger major bump
# Force with changesets (edit the changeset file)
# Change "minor" to "major" in the changeset markdown frontmatter---
Versioning Integration
How Commit Types Map to Version Bumps
BREAKING CHANGE (in footer or !) -> MAJOR (3.0.0 -> 4.0.0)
feat -> MINOR (3.0.0 -> 3.1.0)
fix, perf, revert -> PATCH (3.0.0 -> 3.0.1)
docs, style, refactor, test,
chore, ci, build -> No release (unless configured)Pre-release Versions
# standard-version
npx standard-version --prerelease alpha # 1.0.0 -> 1.0.1-alpha.0
# semantic-release (branch-based)
# release.config.js
branches: [
'main',
{ name: 'beta', prerelease: true },
{ name: 'alpha', prerelease: true },
]---
Example Workflow
End-to-end flow from commit to GitHub release:
1. Developer commits:
feat(auth): add OAuth2 PKCE flow
fix(cart): prevent negative quantity
2. PR merged to main
3. CI triggers semantic-release:
a. Analyze commits since last tag (v2.0.3)
b. Determine bump: feat -> MINOR -> v2.1.0
c. Generate changelog entries
d. Update CHANGELOG.md
e. Bump package.json to 2.1.0
f. Create git tag v2.1.0
g. Commit changelog + version files
h. Create GitHub release with changelog body
i. Publish to npm (if configured)
4. Result:
- Git tag: v2.1.0
- CHANGELOG.md updated with Features + Bug Fixes sections
- GitHub release created with formatted notes
- npm package published (optional)---
Do / Avoid
Do
- Use Conventional Commits consistently so tooling can parse history
- Hide internal types (
chore,ci,style) from public changelogs - Review generated changelogs before publishing (even with automation)
- Include migration notes for breaking changes
- Link entries to PRs or issues for traceability
- Use
--dry-runbefore actual releases to preview output - Configure
fetch-depth: 0in CI so the tool can read full git history
Avoid
- Manually writing changelogs from scratch when commit history is conventional (let tools generate the first draft)
- Publishing changelogs that include internal noise (
chore(deps): bump lodash) - Running changelog generation without tags (tools need tags to determine ranges)
- Mixing changelog tools in the same repo (pick one and commit to it)
- Skipping the
BREAKING CHANGEfooter for breaking changes (tools miss the major bump) - Using
[skip ci]on release commits without understanding the downstream effects
---
Checklist: Changelog Release
- [ ] All commits since last tag follow Conventional Commits format
- [ ]
git fetch --tagsrun before generation (tags are up to date) - [ ] Dry run reviewed:
npx standard-version --dry-runor equivalent - [ ] Generated entries are accurate and human-readable
- [ ] Internal changes (
chore,ci,docs) hidden from public changelog - [ ] Breaking changes have migration notes
- [ ] PR/issue links are present in entries
- [ ] Version bump is correct (major/minor/patch matches changes)
- [ ] Release commit does not trigger another CI release cycle (
[skip ci]or conditional) - [ ] GitHub release created with changelog body
---
Cross-References
- conventional-commits-guide.md -- Format spec that changelog tools depend on
- commit-message-antipatterns.md -- Anti-patterns that break changelog generation
- monorepo-commit-conventions.md -- Per-package changelog strategies for monorepos
Commit Message Anti-Patterns
Common commit message failures, how to detect them, and how to fix them. Each anti-pattern includes the root cause, a concrete example, and a corrected version.
---
Table of Contents
1. Anti-Pattern Catalog 2. Anti-Pattern Reference Table 3. Detection Patterns 4. Linting with commitlint 5. Do / Avoid 6. Checklist: Pre-Commit Message Review
---
Anti-Pattern Catalog
1. The "What" Without "Why"
Describes the code change but omits the motivation. Future readers see what happened but cannot understand why.
BAD: fix(auth): change token expiry from 24h to 1h
GOOD: fix(auth): reduce token expiry to 1h to limit session hijack windowThe body is the right place for deeper rationale when the subject line cannot carry the full context.
2. Generic Messages
Messages like "update", "fix", "changes", or "WIP" carry zero information. They make git log, git bisect, and changelog generation useless.
BAD: update
BAD: fix stuff
BAD: changes
GOOD: fix(cart): prevent negative quantity on item update3. Overly Long First Lines
Lines exceeding 72 characters truncate in git log --oneline, GitHub commit lists, and email patches. The ideal subject length is 50 characters; the hard maximum is 72.
BAD: feat(api): add comprehensive user search endpoint with full-text search across all profile fields including bio and location
GOOD: feat(api): add full-text user search endpointMove detail to the commit body.
4. Missing Type Prefix
Commits without a Conventional Commits type prefix break automated changelog generation, semantic versioning, and commit-based CI filtering.
BAD: add login page
BAD: fixed validation error on signup
GOOD: feat(auth): add login page
GOOD: fix(signup): correct email validation regex5. Mixed Concerns in One Commit
A single commit that bundles a feature, a refactor, and a bug fix. This makes git revert, git cherry-pick, and git bisect unreliable.
BAD: feat: add dashboard, fix auth bug, refactor utils
GOOD (3 separate commits):
feat(dashboard): add analytics overview panel
fix(auth): correct token refresh race condition
refactor(utils): extract date formatting helper6. Emoji Abuse
Inconsistent or meaningless emoji usage that conflicts with or replaces type prefixes. Emojis add visual noise without adding searchability.
BAD: :sparkles: :bug: update stuff
BAD: fix: :rotating_light: correct linting errors
GOOD: fix(lint): resolve ESLint warnings in auth moduleIf your team uses gitmoji, enforce a consistent mapping (e.g., gitmoji.dev) and never mix emoji with Conventional Commits type prefixes in the same project.
7. Tool/Assistant Attribution
Commit messages that credit the tool that generated them. The commit should describe the change, not the tool that wrote it.
BAD: feat: add search (generated by Copilot)
BAD: Co-Authored-By: Claude <noreply@anthropic.com>
GOOD: feat(search): add full-text product searchAI-assisted code is fine. Advertising it in the commit message is noise.
8. Tense and Mood Violations
Using past tense or gerund instead of imperative mood. The convention is imperative because a commit message completes the sentence: "If applied, this commit will ..."
BAD: feat: added user profile page
BAD: fix: fixing validation on checkout
GOOD: feat(profile): add user profile page
GOOD: fix(checkout): correct address validation---
Anti-Pattern Reference Table
| Anti-Pattern | Bad Example | Fix |
|---|---|---|
| What without why | change timeout to 30s | fix(api): increase timeout to 30s to prevent upstream 504s |
| Generic message | update | docs(readme): add deployment instructions |
| Long first line | feat(api): add comprehensive user search... (90 chars) | feat(api): add user search endpoint (36 chars) |
| Missing type | add dark mode toggle | feat(ui): add dark mode toggle |
| Mixed concerns | add dashboard, fix auth, update deps | Split into 3 commits |
| Emoji abuse | :sparkles: :bug: stuff | feat(search): add autocomplete |
| Tool attribution | feat: add login (via Claude) | feat(auth): add login flow |
| Past tense | fixed broken tests | fix(tests): correct flaky timeout in auth suite |
| Trailing period | docs: update README. | docs: update README |
| ALL CAPS | FIX: RESOLVE LOGIN BUG | fix(auth): resolve login redirect loop |
---
Detection Patterns
Regex patterns for catching common anti-patterns in CI or git hooks.
Generic Messages
^(update|fix|changes|stuff|wip|tmp|temp|misc|minor|oops|checkpoint)(\s|$)Missing Type Prefix
^(?!(feat|fix|docs|style|refactor|test|chore|perf|ci|build|revert)(\(.+\))?!?:)Overly Long Subject
^.{73,}$Past Tense Verbs After Type Prefix
^(feat|fix|docs|refactor|test|chore|perf|ci|build)\(.*\):\s+(added|fixed|changed|updated|removed|deleted|created|modified|implemented|resolved)Tool Attribution
(generated by|co-authored-by:.*(copilot|claude|gpt|ai|bot|assistant)|via (copilot|claude|chatgpt))Trailing Period
^.+\.\s*$---
Linting with commitlint
Install and Configure
npm install --save-dev @commitlint/cli @commitlint/config-conventional// commitlint.config.js
module.exports = {
extends: ['@commitlint/config-conventional'],
rules: {
// Enforce type prefix
'type-empty': [2, 'never'],
// Subject max length
'header-max-length': [2, 'always', 72],
// No trailing period
'header-full-stop': [2, 'never', '.'],
// Lowercase type
'type-case': [2, 'always', 'lower-case'],
// Imperative mood (custom plugin required for full enforcement)
'subject-case': [2, 'never', ['sentence-case', 'start-case', 'pascal-case', 'upper-case']],
// Allowed types
'type-enum': [2, 'always', [
'feat', 'fix', 'docs', 'style', 'refactor',
'test', 'chore', 'perf', 'ci', 'build', 'revert'
]],
},
};Hook Integration
# With Husky
npx husky add .husky/commit-msg 'npx commitlint --edit $1'
# With pre-commit (Python)
# .pre-commit-config.yaml
repos:
- repo: https://github.com/alessandrojcm/commitlint-pre-commit-hook
rev: v9.5.0
hooks:
- id: commitlint
stages: [commit-msg]CI Enforcement
# GitHub Actions
- name: Lint commits
uses: wagoid/commitlint-github-action@v5
with:
configFile: commitlint.config.js---
Do / Avoid
Do
- Write the subject in imperative mood ("add", "fix", "remove")
- Keep subject under 72 characters (50 ideal)
- Include a type prefix on every commit
- Separate subject from body with a blank line
- Explain "why" in the body when the subject alone is insufficient
- One logical change per commit
- Run commitlint in CI and as a git hook
Avoid
- Generic messages ("update", "fix", "changes", "WIP")
- Past tense or gerund ("added", "fixing")
- Trailing periods on the subject line
- Tool/assistant attribution in commit metadata
- Mixing unrelated changes in a single commit
- Emoji as a replacement for type prefixes
- Subjects over 72 characters
---
Checklist: Pre-Commit Message Review
Before pushing, verify each commit message:
- [ ] Starts with a valid type prefix (
feat,fix,docs, etc.) - [ ] Subject is 72 characters or fewer
- [ ] Uses imperative mood ("add" not "added")
- [ ] No trailing period on the subject line
- [ ] Describes a single logical change
- [ ] Includes the "why" (in subject or body)
- [ ] No tool/assistant attribution
- [ ] No generic placeholder text ("update", "WIP", "misc")
- [ ] Scope matches project conventions (if used)
- [ ] Breaking changes are marked with
!orBREAKING CHANGEfooter
---
Cross-References
- conventional-commits-guide.md -- Type definitions, scope strategy, format spec
- monorepo-commit-conventions.md -- Scope conventions for multi-package repositories
- changelog-generation-guide.md -- How anti-patterns break automated changelog generation
Conventional Commits Reference Guide
Format Specification
<type>[optional scope]: <description>
[optional body]
[optional footer(s)]Commit Types
Primary Types
feat: A new feature for the user
- Adds new functionality
- Introduces new API endpoints
- Creates new user-facing capabilities
- Examples: new component, new API route, new CLI command
fix: A bug fix
- Corrects incorrect behavior
- Resolves user-reported issues
- Patches security vulnerabilities
- Examples: fix validation, correct calculation, resolve crash
refactor: Code change that neither fixes a bug nor adds a feature
- Improves code structure
- Enhances readability
- Optimizes without changing behavior
- Examples: extract function, rename variables, reorganize modules
Documentation & Formatting
docs: Documentation only changes
- README updates
- API documentation
- Code comments
- Wiki pages
- Examples: update README, add JSDoc comments
style: Changes that don't affect code meaning
- Formatting (prettier, eslint --fix)
- Whitespace, semicolons
- Code style only (no logic changes)
- Examples: run prettier, fix indentation
Testing & Build
test: Adding or correcting tests
- New test cases
- Test utilities
- Test configuration
- Examples: add unit tests, fix flaky test
chore: Changes to build process or auxiliary tools
- Package updates
- Build script changes
- Development tooling
- Examples: update dependencies, configure webpack
Performance & CI/CD
perf: Performance improvements
- Measurable speed improvements
- Memory optimization
- Bundle size reduction
- Examples: optimize algorithm, lazy load component
ci: Continuous Integration changes
- GitHub Actions
- CircleCI, Travis CI
- Build pipelines
- Examples: update CI workflow, add deployment step
Special Cases
revert: Reverts a previous commit
- Format:
revert: <reverted commit message> - Include commit hash in body
build: Changes affecting build system
- Webpack, rollup, vite configuration
- Build dependencies
- Examples: update build config, change bundler
Scope Guidelines
What is Scope?
The scope indicates which part of the codebase was modified:
feat(auth): add login componentfix(api): correct validation errordocs(readme): update installation steps
Scope Best Practices
1. Use lowercase: feat(api) not feat(API) 2. Be specific but not narrow: feat(user-profile) not feat(user-profile-avatar-upload-button) 3. Match your project structure: Use module names, directory names, or functional areas 4. Omit when unclear: If changes span many areas, scope is optional
Common Scopes by Project Type
Web Applications:
ui,components,layout,stylesapi,routes,middleware,controllersauth,user,admindb,models,migrationsconfig,env,settings
Libraries/Packages:
core,utils,helperstypes,interfacescli,commandsparser,compiler,renderer
Full-Stack Projects:
frontend,backend,sharedserver,clientdesktop,mobile,web
Description Guidelines
The Perfect Description
1. Use imperative mood: "add" not "added", "fix" not "fixed"
- [OK]
feat: add user dashboard - [FAIL]
feat: added user dashboard
2. Keep it concise: 50 characters ideal, 72 maximum
- [OK]
fix(auth): correct token expiration check - [FAIL]
fix(auth): correct the token expiration check which was causing users to be logged out too early
3. Be specific: Clearly state what changed
- [OK]
feat(api): add pagination to user list endpoint - [FAIL]
feat: improve API
4. No period at the end
- [OK]
docs: update README installation section - [FAIL]
docs: update README installation section.
5. Focus on what and why, not how
- [OK]
perf(images): reduce bundle size with lazy loading - [FAIL]
perf(images): use React.lazy and Suspense to implement code splitting
Breaking Changes
Indicating Breaking Changes
Option 1: Exclamation mark
feat(api)!: change authentication flow to OAuth2Option 2: BREAKING CHANGE footer
feat(api): change authentication flow
BREAKING CHANGE: The authentication endpoint now requires OAuth2 tokens
instead of API keys. All clients must update their authentication logic.When to Use
- API changes that require user updates
- Removed functionality
- Changed behavior of existing features
- Renamed public methods or properties
Multi-line Commits
With Body
feat(api): add user search endpoint
Implement full-text search across user profiles including
name, email, and bio fields. Uses database indexes for
performance.With Footer
fix(auth): resolve session timeout issue
Closes #123
Refs #456Common Footers
Closes #123: Closes issueFixes #123: Fixes issueRefs #123: References issueBREAKING CHANGE:: Describes breaking changeCo-authored-by:: Credits co-authors
Real-World Examples
Feature Development
feat(chat): add real-time message notifications
Implement WebSocket connection for live message updates.
Includes visual and sound notifications.
Closes #234Bug Fixes
fix(cart): prevent duplicate items on rapid clicks
Add debouncing to "Add to Cart" button to prevent race
condition when user clicks multiple times quickly.
Fixes #567Refactoring
refactor(utils): extract date formatting into shared helper
Move duplicate date formatting logic from components into
centralized utility function. No behavior changes.Documentation
docs(api): add examples for authentication endpoints
Include curl examples and response samples for all auth
endpoints in API documentation.Dependencies
chore(deps): update react to v18.2.0
Update React and React-DOM to latest stable version.
Includes performance improvements and bug fixes.Performance
perf(images): implement progressive image loading
Replace eager loading with progressive JPEG loading to
improve perceived performance on slow connections.Configuration
ci: add automated dependency updates
Configure Dependabot to automatically check for and create
PRs for dependency updates weekly.Common Patterns to Avoid
BAD: Too Vague
fix: bug fix
feat: new feature
chore: updatesBAD: Too Detailed (save for body)
feat: add a new user authentication system with JWT tokens and refresh token rotation using Redis for storage and bcrypt for password hashingBAD: Wrong Type
feat: fix login bug → fix(auth): resolve login validation
docs: add new API endpoint → feat(api): add user search endpointBAD: Mixed Changes
feat: add dashboard and fix auth bug and update docs
→ Split into 3 commitsTooling
Commitlint
Enforce conventional commits in CI:
{
"extends": ["@commitlint/config-conventional"]
}Commitizen
Interactive commit message wizard:
npm install -g commitizen
git czHusky
Git hooks for commit message validation:
npm install husky --save-dev
npx husky add .husky/commit-msg 'npx commitlint --edit $1'Benefits
1. Automated Changelogs: Generate from commit history 2. Semantic Versioning: Auto-determine version bumps 3. Better History: Clear, searchable commit messages 4. Team Alignment: Consistent commit style 5. Code Review: Easier to understand changes
Resources
- Specification: https://www.conventionalcommits.org/
- Commitlint: https://commitlint.js.org/
- Commitizen: https://github.com/commitizen/cz-cli
- Semantic Release: https://semantic-release.gitbook.io/
Monorepo Commit Conventions
Commit message conventions for monorepo and multi-package repositories. Covers scope strategy, changelog generation per package, affected-package detection, and CI integration.
---
Table of Contents
1. Scope Strategy 2. Scope Granularity Decision Table 3. Examples by Repo Structure 4. Changelog Generation per Package 5. Affected Package Detection 6. Breaking Changes Across Packages 7. CI Integration 8. Common Monorepo Tools 9. Do / Avoid 10. Checklist: Monorepo Commit Review
---
Scope Strategy
Monorepo commits must encode where the change happened so that tooling can route changelogs, trigger builds, and filter CI to the affected packages.
Three Scope Levels
| Level | Format | When to Use |
|---|---|---|
| Package-level | feat(packages/auth): ... | Distinct publishable packages |
| Directory-level | fix(apps/web): ... | Apps or services within the repo |
| Feature-level | feat(payments): ... | Cross-cutting features spanning packages |
Choosing a Scope Level
Use package-level scopes when:
- Packages are independently versioned and published
- Changelogs are generated per package
- CI pipelines run per package
Use directory-level scopes when:
- Repo has
apps/,packages/,services/top-level directories - Each directory maps to a deployable unit
- Teams own specific directories
Use feature-level scopes when:
- Changes span multiple packages but belong to one feature
- The repo does not publish packages independently
- Scopes map to product areas rather than file paths
---
Scope Granularity Decision Table
| Repo Structure | Recommended Scope | Example |
|---|---|---|
packages/auth, packages/ui, packages/api | Package name | feat(auth): add OAuth2 flow |
apps/web, apps/mobile, apps/admin | App name | fix(web): correct routing on 404 |
services/billing, services/notifications | Service name | perf(billing): cache invoice queries |
libs/shared, libs/utils | Lib name | refactor(shared): extract date helpers |
| Flat structure (no clear packages) | Feature area | feat(search): add autocomplete |
packages/ + apps/ hybrid | Full path prefix | fix(apps/web): correct CSP header |
Scope Naming Rules
- Lowercase, kebab-case:
feat(auth-service)notfeat(AuthService) - Match directory names exactly when using path-based scopes
- Keep scope stable across the project lifetime (renaming scopes breaks changelog history)
- Document the scope map in the repo's contributing guide or commitlint config
---
Examples by Repo Structure
Turborepo / pnpm Workspaces
feat(packages/auth): add OAuth2 PKCE flow
fix(packages/ui): correct button focus ring on Safari
chore(packages/config): update ESLint shared config
test(apps/web): add integration tests for checkout
ci(root): update GitHub Actions to Node 20
docs(packages/api): add OpenAPI schema for v2 endpointsNx Workspace
feat(libs/feature-dashboard): add analytics widget
fix(apps/admin): correct permission check on user list
refactor(libs/data-access-auth): simplify token refresh logic
build(workspace): update Nx to 17.xLerna Monorepo
feat(@acme/auth): add MFA enrollment endpoint
fix(@acme/ui): correct modal z-index stacking
chore(@acme/cli): bump commander to v12When packages are npm-scoped (@org/package), the scope in the commit can use the short name without the org prefix: feat(auth) instead of feat(@acme/auth), as long as the commitlint config maps auth to @acme/auth.
---
Changelog Generation per Package
Changesets (Recommended for Multi-Package)
npx changeset init
# After making changes, create a changeset
npx changeset
# Interactive prompt: select affected packages, bump type, summary
# On release branch
npx changeset version # Updates package.json versions + CHANGELOG.md per package
npx changeset publish # Publishes to npmChangeset files live in .changeset/ and describe the change independently from commit messages. This decouples changelog content from commit history.
semantic-release with monorepo plugins
// release.config.js (per package or root)
module.exports = {
branches: ['main'],
plugins: [
['@semantic-release/commit-analyzer', {
preset: 'conventionalcommits',
releaseRules: [
{ type: 'feat', release: 'minor' },
{ type: 'fix', release: 'patch' },
{ type: 'perf', release: 'patch' },
{ breaking: true, release: 'major' },
],
}],
['@semantic-release/release-notes-generator', {
preset: 'conventionalcommits',
}],
'@semantic-release/changelog',
'@semantic-release/npm',
'@semantic-release/github',
],
};For monorepo support, use semantic-release-monorepo or multi-semantic-release:
npx multi-semantic-releaselerna-changelog
npx lerna-changelog --from=v1.0.0 --to=v2.0.0Generates a changelog grouped by PR labels. Works best with Lerna but requires GitHub PR labels to classify changes.
Conventional Changelog (per package)
# Generate changelog for a specific package directory
npx conventional-changelog -p conventionalcommits -i packages/auth/CHANGELOG.md -s \
--commit-path packages/authThe --commit-path flag filters commits to those that touched the specified directory.
---
Affected Package Detection
From Commit Scope
Tools parse the commit scope to determine which packages were affected:
feat(auth): add OAuth2 flow -> packages/auth
fix(apps/web): correct routing -> apps/web
chore(root): update tsconfig -> root (all packages)From Changed Files
When scope is absent or insufficient, tools fall back to file path analysis:
# Nx: detect affected projects from git diff
npx nx affected:apps --base=main --head=HEAD
npx nx affected:libs --base=main --head=HEAD
# Turborepo: filter by changed packages
npx turbo run build --filter='...[HEAD^1]'
# pnpm: list changed packages
pnpm -r --filter '...[HEAD~1]' exec pwdCombining Scope and File Detection
The most reliable approach uses both:
1. Parse commit scope for explicit package targeting 2. Cross-reference with git diff --name-only for validation 3. Flag mismatches (scope says auth but files changed in billing)
---
Breaking Changes Across Packages
Single-Package Breaking Change
feat(auth)!: replace session tokens with JWT
BREAKING CHANGE: All consumers of @acme/auth must update their
token validation logic. Session-based auth is removed.Cross-Package Breaking Change
When a breaking change in one package forces changes in dependent packages:
feat(auth)!: change TokenPayload interface
BREAKING CHANGE: TokenPayload.userId is now a UUID string instead of
a number. Affected packages: @acme/api, @acme/admin, @acme/mobile.
Migration: Replace `user.id` (number) with `user.uuid` (string) in
all token consumers.Documenting Impact Scope
For cross-package breaks, list all affected packages in the commit body. This gives release tooling and human readers a clear blast radius.
Affected packages:
- @acme/auth (source of change)
- @acme/api (consumes TokenPayload)
- @acme/admin (consumes TokenPayload)
- @acme/shared-types (type definition updated)---
CI Integration
Run Tests Only for Affected Packages
# GitHub Actions with Nx
- name: Determine affected packages
run: echo "AFFECTED=$(npx nx show projects --affected --base=origin/main)" >> $GITHUB_ENV
- name: Test affected
run: npx nx affected -t test --base=origin/main# GitHub Actions with Turborepo
- name: Test changed packages
run: npx turbo run test --filter='...[origin/main]'Scope-Based Pipeline Routing
# GitHub Actions: trigger package-specific workflows based on paths
on:
push:
paths:
- 'packages/auth/**'
jobs:
test-auth:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- run: cd packages/auth && npm testCommit Scope Validation in CI
# Validate that the commit scope matches a known package
- name: Validate commit scope
run: |
SCOPE=$(echo "${{ github.event.head_commit.message }}" | grep -oP '\(\K[^)]+')
KNOWN_SCOPES="auth ui api config apps/web apps/admin root"
if [[ ! " $KNOWN_SCOPES " =~ " $SCOPE " ]]; then
echo "Unknown scope: $SCOPE"
exit 1
fi---
Common Monorepo Tools
| Tool | Scope Detection | Affected Packages | Changelog Per Package | Package Publishing |
|---|---|---|---|---|
| Nx | File paths + project graph | nx affected | Via plugins | Via plugins |
| Turborepo | File paths + turbo.json | --filter='...[ref]' | Via changesets | Manual or changesets |
| Lerna | Package directories | lerna changed | lerna-changelog | lerna publish |
| pnpm workspaces | Workspace protocol | --filter with git ranges | Via changesets | pnpm -r publish |
| Changesets | Explicit declaration | Changeset files | Built-in per package | changeset publish |
| Rush | Rush project config | rush change | rush publish | rush publish |
---
Do / Avoid
Do
- Define a scope map and enforce it with commitlint
- Use package-level scopes for independently published packages
- Generate changelogs per package using
--commit-pathor changesets - Include affected package lists in cross-package breaking changes
- Validate commit scopes against known packages in CI
- Use
rootorworkspacescope for changes that affect the entire repo (CI configs, root tsconfig, tooling)
Avoid
- Omitting scope entirely in monorepo commits (breaks per-package filtering)
- Using inconsistent scope formats (
authvspackages/authvs@acme/authin the same repo) - Committing cross-package changes without listing the impact scope
- Nesting scopes (
feat(packages/auth/middleware)) -- keep scopes to one level - Changing scope names after release tooling depends on them
- Using feature-level scopes in repos that need per-package changelogs
---
Checklist: Monorepo Commit Review
- [ ] Commit scope matches a package, app, or service directory name
- [ ] Scope is documented in the project's commitlint config or contributing guide
- [ ] Cross-package breaking changes list all affected packages in the body
- [ ] One logical change per commit (not mixing changes across unrelated packages)
- [ ] Changelog tooling can parse the scope to route entries to the correct package
- [ ] CI is configured to use scope or file paths for affected-package detection
- [ ] Root/workspace changes use a
rootorworkspacescope
---
Cross-References
- conventional-commits-guide.md -- Base format spec, type definitions, scope guidelines
- commit-message-antipatterns.md -- Generic messages and mixed-concern anti-patterns
- changelog-generation-guide.md -- Changelog tools, configuration, and CI integration