535 lines
11 KiB
Markdown
535 lines
11 KiB
Markdown
# Commit Message Guide
|
|
|
|
A comprehensive guide to writing clear, consistent, and maintainable commit messages using the Conventional Commits format.
|
|
|
|
---
|
|
|
|
## Why Good Commit Messages Matter
|
|
|
|
- **Documentation**: Git history becomes a changelog
|
|
- **Code Review**: Easier to understand what changed and why
|
|
- **Debugging**: Quickly find when bugs were introduced
|
|
- **Automation**: Enables automatic changelog generation and versioning
|
|
- **Professionalism**: Shows attention to detail and respect for maintainers
|
|
|
|
---
|
|
|
|
## Conventional Commits Format
|
|
|
|
```
|
|
<type>(<scope>): <subject>
|
|
|
|
[optional body]
|
|
|
|
[optional footer(s)]
|
|
```
|
|
|
|
### Components
|
|
|
|
**Type** (required): Category of change
|
|
**Scope** (optional): What section of codebase is affected
|
|
**Subject** (required): Brief description of change
|
|
**Body** (optional): Detailed explanation
|
|
**Footer** (optional): Issue references, breaking changes
|
|
|
|
---
|
|
|
|
## Types
|
|
|
|
### Primary Types
|
|
|
|
**feat**: New feature for the user
|
|
```
|
|
feat(auth): add OAuth2 support for Google and GitHub
|
|
```
|
|
|
|
**fix**: Bug fix for the user
|
|
```
|
|
fix(api): resolve memory leak in worker shutdown
|
|
```
|
|
|
|
**docs**: Documentation changes only
|
|
```
|
|
docs(readme): update installation instructions for v2.0
|
|
```
|
|
|
|
**style**: Code style changes (formatting, missing semicolons, etc.)
|
|
```
|
|
style(components): format code with Prettier
|
|
```
|
|
|
|
**refactor**: Code change that neither fixes bug nor adds feature
|
|
```
|
|
refactor(auth): extract middleware to separate module
|
|
```
|
|
|
|
**perf**: Performance improvement
|
|
```
|
|
perf(database): add index to user_id column
|
|
```
|
|
|
|
**test**: Adding or updating tests
|
|
```
|
|
test(auth): add OAuth flow integration tests
|
|
```
|
|
|
|
### Supporting Types
|
|
|
|
**build**: Changes to build system or dependencies
|
|
```
|
|
build(deps): upgrade React to v18.2.0
|
|
```
|
|
|
|
**ci**: CI configuration changes
|
|
```
|
|
ci(github): add automated release workflow
|
|
```
|
|
|
|
**chore**: Other changes that don't modify src or test files
|
|
```
|
|
chore(deps): update dev dependencies
|
|
```
|
|
|
|
**revert**: Revert a previous commit
|
|
```
|
|
revert: feat(auth): add OAuth2 support
|
|
|
|
This reverts commit abc123def456.
|
|
```
|
|
|
|
---
|
|
|
|
## Subject Line Rules
|
|
|
|
### The 7 Rules
|
|
|
|
1. **Limit to 50 characters** (hard limit: 72)
|
|
2. **Use imperative mood** ("Add" not "Added" or "Adds")
|
|
3. **Capitalize first word** after the colon
|
|
4. **Don't end with punctuation**
|
|
5. **Focus on WHAT changed** (body explains WHY)
|
|
6. **Be specific** but concise
|
|
7. **Start with type** (if using Conventional Commits)
|
|
|
|
### Examples
|
|
|
|
✅ **Good:**
|
|
```
|
|
feat(api): add user authentication endpoint
|
|
fix(ui): resolve button alignment on mobile
|
|
docs(contributing): clarify PR submission process
|
|
refactor(utils): simplify date formatting logic
|
|
```
|
|
|
|
❌ **Bad:**
|
|
```
|
|
Fixed stuff # Too vague
|
|
Added new feature to the authentication system that allows users to login with OAuth # Too long
|
|
updated code # Not specific, wrong tense
|
|
feat(api): add user authentication. # Don't end with period
|
|
Feat(api): add auth # Don't capitalize type
|
|
```
|
|
|
|
---
|
|
|
|
## Optional Scope
|
|
|
|
The scope provides context about what part of the codebase changed.
|
|
|
|
### Common Scopes
|
|
|
|
```
|
|
feat(auth): ... # Authentication
|
|
feat(api): ... # API layer
|
|
feat(ui): ... # User interface
|
|
feat(database): ... # Database
|
|
feat(docs): ... # Documentation
|
|
feat(tests): ... # Tests
|
|
fix(deps): ... # Dependencies
|
|
build(webpack): ... # Build tooling
|
|
```
|
|
|
|
### Project-Specific Scopes
|
|
|
|
Check the project's recent commits for conventions:
|
|
```bash
|
|
git log --oneline -20
|
|
```
|
|
|
|
### When to Omit Scope
|
|
|
|
Scope is optional. Omit when:
|
|
- Change affects multiple areas
|
|
- Project doesn't use scopes
|
|
- Scope would be too generic
|
|
|
|
```
|
|
feat: add dark mode support
|
|
docs: update README
|
|
```
|
|
|
|
---
|
|
|
|
## Body (Optional)
|
|
|
|
The body provides detailed explanation of WHAT and WHY (code shows HOW).
|
|
|
|
### Rules
|
|
|
|
- Separate from subject with blank line
|
|
- Wrap at 72 characters per line
|
|
- Explain motivation and context
|
|
- Contrast with previous behavior
|
|
- Use bullet points for multiple points
|
|
|
|
### Example
|
|
|
|
```
|
|
feat(api): add rate limiting to authentication endpoints
|
|
|
|
Users can now make up to 100 authentication attempts per hour
|
|
per IP address. This prevents brute force attacks while allowing
|
|
legitimate users to retry failed login attempts.
|
|
|
|
Implementation details:
|
|
- Uses Redis for distributed rate limiting
|
|
- Configurable via RATE_LIMIT_MAX environment variable
|
|
- Returns 429 status with Retry-After header when exceeded
|
|
- Resets hourly at top of the hour
|
|
|
|
Previous behavior allowed unlimited attempts, which was identified
|
|
as a security vulnerability in audit #456.
|
|
```
|
|
|
|
### When to Include Body
|
|
|
|
Include a body when:
|
|
- Change is complex or non-obvious
|
|
- Design decisions need explanation
|
|
- Previous behavior needs context
|
|
- Multiple related changes in one commit
|
|
- Security or performance implications
|
|
|
|
### When to Skip Body
|
|
|
|
Skip the body when:
|
|
- Change is self-explanatory
|
|
- Subject line tells the complete story
|
|
- Trivial changes (typos, formatting)
|
|
|
|
---
|
|
|
|
## Footer (Optional)
|
|
|
|
Footers provide metadata about the commit.
|
|
|
|
### Breaking Changes
|
|
|
|
Use `BREAKING CHANGE:` footer for breaking changes:
|
|
|
|
```
|
|
feat(api)!: change authentication endpoint path
|
|
|
|
BREAKING CHANGE: The authentication endpoint has moved from
|
|
/api/auth to /api/v2/auth. Update your API calls accordingly.
|
|
|
|
Migration guide available at docs/migration/v2.md
|
|
```
|
|
|
|
Note the `!` after the type indicates a breaking change.
|
|
|
|
### Issue References
|
|
|
|
Link issues using keywords for automatic closing:
|
|
|
|
```
|
|
fix(ui): resolve mobile layout issues
|
|
|
|
Fixes #123
|
|
Closes #456, #789
|
|
Relates to #234
|
|
```
|
|
|
|
**Closing Keywords:**
|
|
- `Closes #123`
|
|
- `Fixes #123`
|
|
- `Resolves #123`
|
|
- Also: close, fix, resolve (case insensitive)
|
|
|
|
### Co-authored-by
|
|
|
|
Credit co-authors:
|
|
|
|
```
|
|
feat(api): add GraphQL support
|
|
|
|
Co-authored-by: Jane Doe <jane@example.com>
|
|
Co-authored-by: John Smith <john@example.com>
|
|
```
|
|
|
|
### Other Footers
|
|
|
|
```
|
|
Reviewed-by: Name <email>
|
|
Signed-off-by: Name <email>
|
|
Acked-by: Name <email>
|
|
See-also: #123
|
|
```
|
|
|
|
---
|
|
|
|
## Complete Examples
|
|
|
|
### Example 1: Simple Feature
|
|
|
|
```
|
|
feat(ui): add dark mode toggle
|
|
|
|
Adds a toggle button in settings to switch between light and dark
|
|
themes. User preference is saved to localStorage and persists
|
|
across sessions.
|
|
|
|
Closes #234
|
|
```
|
|
|
|
### Example 2: Bug Fix
|
|
|
|
```
|
|
fix(api): prevent race condition in cache invalidation
|
|
|
|
The cache invalidation logic wasn't thread-safe, causing occasional
|
|
race conditions when multiple workers tried to invalidate the same
|
|
key simultaneously.
|
|
|
|
Solution:
|
|
- Added mutex locks around the critical section
|
|
- Implemented timeout for lock acquisition (5s)
|
|
- Added retry logic with exponential backoff
|
|
- Updated tests to verify thread-safety
|
|
|
|
Fixes #456
|
|
```
|
|
|
|
### Example 3: Breaking Change
|
|
|
|
```
|
|
feat(api)!: migrate to TypeScript and update endpoint contracts
|
|
|
|
BREAKING CHANGE: All API endpoints now return ISO 8601 date
|
|
strings instead of Unix timestamps. Update client code to parse
|
|
dates accordingly.
|
|
|
|
Additionally, authentication now requires JWT tokens in the
|
|
Authorization header instead of session cookies.
|
|
|
|
Migration guide: docs/migration/v3.md
|
|
|
|
Closes #567
|
|
```
|
|
|
|
### Example 4: Refactoring
|
|
|
|
```
|
|
refactor(auth): extract middleware to separate module
|
|
|
|
No functional changes, but auth logic is now easier to test and
|
|
maintain. Consolidated duplicate code from 5 route handlers into
|
|
reusable middleware functions.
|
|
|
|
Files affected:
|
|
- New: middleware/authenticate.js
|
|
- Updated: routes/*.js (5 files)
|
|
- Tests: tests/middleware/auth.test.js
|
|
|
|
Relates to #301 (technical debt epic)
|
|
```
|
|
|
|
### Example 5: Documentation
|
|
|
|
```
|
|
docs(api): add examples for authentication flows
|
|
|
|
Added code examples for:
|
|
- Basic authentication with username/password
|
|
- OAuth2 flow with Google
|
|
- API key authentication
|
|
- JWT token refresh
|
|
|
|
Examples include curl commands and JavaScript fetch() snippets.
|
|
|
|
Closes #678
|
|
```
|
|
|
|
### Example 6: Multiple Related Changes
|
|
|
|
```
|
|
fix(auth): resolve multiple OAuth edge cases
|
|
|
|
- Handle expired refresh tokens gracefully
|
|
- Prevent account linking when email doesn't match
|
|
- Add rate limiting to token refresh endpoint
|
|
- Log failed OAuth attempts for security monitoring
|
|
|
|
Each issue was related to OAuth implementation and fixing them
|
|
separately would have caused merge conflicts.
|
|
|
|
Fixes #123, #456, #789
|
|
```
|
|
|
|
---
|
|
|
|
## Tips for Writing Good Commit Messages
|
|
|
|
### Do:
|
|
|
|
✅ Write in imperative mood ("Add" not "Added")
|
|
```
|
|
feat: add user profile page
|
|
```
|
|
|
|
✅ Be specific about what changed
|
|
```
|
|
fix(api): resolve timeout in user search endpoint
|
|
```
|
|
|
|
✅ Explain WHY in the body
|
|
```
|
|
refactor(db): switch to connection pooling
|
|
|
|
The previous approach created a new connection for each request,
|
|
which caused performance issues under load. Connection pooling
|
|
reduces overhead and improves response times by 40%.
|
|
```
|
|
|
|
✅ Use the body for complex changes
|
|
✅ Reference issues and PRs
|
|
✅ Follow project conventions
|
|
|
|
### Don't:
|
|
|
|
❌ Use past tense
|
|
```
|
|
feat: added user profile page ❌
|
|
```
|
|
|
|
❌ Be vague
|
|
```
|
|
fix: bug fix ❌
|
|
update: changes ❌
|
|
```
|
|
|
|
❌ Write novels in the subject line
|
|
```
|
|
feat(api): add new user authentication endpoint with OAuth2 support for Google and GitHub that also includes rate limiting ❌
|
|
```
|
|
|
|
❌ Skip the type (if project uses Conventional Commits)
|
|
```
|
|
Add user profile page ❌
|
|
```
|
|
|
|
❌ Use abbreviations or jargon unnecessarily
|
|
```
|
|
fix(db): rm dup recs via opt idx ❌
|
|
```
|
|
|
|
❌ Combine unrelated changes in one commit
|
|
```
|
|
feat: add dark mode, fix typo in README, update dependencies ❌
|
|
```
|
|
|
|
---
|
|
|
|
## Real-World Examples from Popular Projects
|
|
|
|
### React
|
|
```
|
|
feat(react-dom): Add support for CSS Layers
|
|
|
|
Implements support for @layer, enabling better CSS encapsulation.
|
|
|
|
Fixes #24556
|
|
```
|
|
|
|
### Node.js
|
|
```
|
|
doc: add missing types to request and response
|
|
|
|
Added TypeScript type definitions for several Request and Response
|
|
methods that were previously missing from the declarations.
|
|
|
|
Fixes: #12345
|
|
Refs: #67890
|
|
```
|
|
|
|
### Kubernetes
|
|
```
|
|
fix: prevent pod creation with invalid security context
|
|
|
|
Adds validation to reject pods with both `runAsUser: 0` and
|
|
`allowPrivilegeEscalation: false`, which is an invalid combination.
|
|
|
|
Closes #12345
|
|
```
|
|
|
|
---
|
|
|
|
## Commit Message Checklist
|
|
|
|
Before committing, verify:
|
|
|
|
- [ ] Type is correct (feat, fix, docs, etc.)
|
|
- [ ] Subject line under 50 characters (max 72)
|
|
- [ ] Imperative mood ("Add" not "Added")
|
|
- [ ] First word capitalized
|
|
- [ ] No period at end
|
|
- [ ] Body explains WHY (if needed)
|
|
- [ ] Body wrapped at 72 characters
|
|
- [ ] Blank line between subject and body
|
|
- [ ] Issues referenced in footer
|
|
- [ ] Breaking changes noted with BREAKING CHANGE:
|
|
- [ ] Follows project conventions
|
|
|
|
---
|
|
|
|
## Tools & Automation
|
|
|
|
### Commitizen
|
|
|
|
Interactive tool for writing commits:
|
|
```bash
|
|
npm install -g commitizen
|
|
git cz
|
|
```
|
|
|
|
### Commitlint
|
|
|
|
Lint commit messages:
|
|
```bash
|
|
npm install --save-dev @commitlint/cli @commitlint/config-conventional
|
|
```
|
|
|
|
### Husky
|
|
|
|
Git hooks to enforce commit message format:
|
|
```bash
|
|
npm install --save-dev husky
|
|
npx husky add .husky/commit-msg 'npx --no -- commitlint --edit ${1}'
|
|
```
|
|
|
|
---
|
|
|
|
## Resources
|
|
|
|
**Specifications:**
|
|
- Conventional Commits: https://www.conventionalcommits.org/
|
|
- Git Commit Guidelines: https://git-scm.com/book/en/v2/Distributed-Git-Contributing-to-a-Project
|
|
|
|
**Tools:**
|
|
- Commitizen: https://github.com/commitizen/cz-cli
|
|
- Commitlint: https://commitlint.js.org/
|
|
|
|
**Further Reading:**
|
|
- "How to Write a Git Commit Message": https://chris.beams.io/posts/git-commit/
|
|
- Angular Commit Guidelines: https://github.com/angular/angular/blob/main/CONTRIBUTING.md#commit
|