Skip to content

CONVENTIONAL_COMMITS

scheilch edited this page Mar 8, 2026 · 2 revisions

Conventional Commits Guide

📝 Why?

Conventional Commits enable:

  • Auto-Changelog: Release notes generated from commits
  • Semantic Versioning: feat = Minor, fix = Patch, BREAKING: = Major
  • Better History: Commits are searchable by type
  • CI/CD Integration: Automatic releases

🎯 Format

<type>(<scope>): <subject>

[optional body]

[optional footer]

Type (REQUIRED):

  • feat - New feature (↑ Minor Version)
  • fix - Bug fix (↑ Patch Version)
  • docs - Documentation only
  • style - Formatting (no code change)
  • refactor - Code refactoring (no feature/fix)
  • perf - Performance improvement
  • test - Add/modify tests
  • build - Build system (npm, Docker, etc.)
  • ci - CI/CD Workflows
  • chore - Maintenance (Dependencies, etc.)
  • revert - Revert a commit

Scope (optional):

Area of change:

  • devices - Device Discovery/Management
  • api - REST API Endpoints
  • frontend - React UI
  • backend - Python Backend
  • docker - Docker/Container
  • workflow - GitHub Actions

Subject (REQUIRED):

  • Short description (max 50 characters)
  • Lowercase (except proper nouns)
  • No period at the end
  • Imperative mood ("add" not "added")

Body (optional):

  • Detailed description
  • Why was the change made?
  • What was changed?

Footer (optional):

  • BREAKING CHANGE: for breaking changes (↑ Major Version)
  • Fixes #123 for issue references
  • Co-authored-by: for co-authors

✅ Good Examples

# Add a feature
feat(devices): add SSDP auto-discovery

Implements UPnP device discovery using multicast requests.
Devices are cached for 10 minutes to reduce network load.

Fixes #42

# Bug fix
fix(api): handle null response in device sync

Previously crashed when device returned empty response.
Now returns 404 with proper error message.

# Performance
perf(docker): optimize arm64 build time

Switch to platform-specific rollup binaries reduces
build time from 30min to 10min on ARM64 QEMU.

# Breaking Change
feat(api)!: change device ID format to UUIDs

BREAKING CHANGE: Device IDs changed from MAC addresses to UUIDs.
Clients must migrate existing device references.

Migration: GET /api/devices returns new IDs.

# Documentation
docs(readme): add Codecov setup instructions

# Test
test(backend): add regression test for XML namespace bug

# CI/CD
ci(workflow): add security scanning with bandit

# Dependency Update
chore(deps): update fastapi to 0.110.0

❌ Bad Examples

# ❌ No type
Updated README

# ❌ Type in uppercase
FEAT: add discovery

# ❌ Period at the end
feat: add discovery.

# ❌ Not imperative
feat: added discovery

# ❌ Too long (>72 characters)
feat(devices): add SSDP auto-discovery feature with caching and timeout handling

# ❌ Too vague
fix: bug
chore: stuff
feat: changes

# ✅ BETTER
feat(devices): add SSDP auto-discovery
fix(api): handle null device response
chore(deps): update fastapi to 0.110.0

🛠️ Tools & Validation

1. Automatic Validation (Pull Requests)

The workflow .github/workflows/commitlint.yml checks:

  • ✅ PR Title must follow Conventional Commits
  • ✅ All commits in PR must be valid
  • ❌ PR is blocked on invalid commits

2. Local Validation (optional)

Install commitlint locally:

npm install -g @commitlint/cli @commitlint/config-conventional

# Test a commit message
echo "feat(devices): add discovery" | commitlint

# Validate last commit
git log -1 --pretty=format:"%s" | commitlint

3. Git Hooks (optional)

Automatically check on every commit:

# Install husky + commitlint
npm install --save-dev @commitlint/cli @commitlint/config-conventional husky

# Setup hook
npx husky install
npx husky add .husky/commit-msg 'npx commitlint --edit $1'

🔧 Fix Commits After the Fact

Rename the last commit:

git commit --amend -m "feat(devices): add SSDP discovery"
git push --force-with-lease

Rename multiple commits:

# Interactive rebase (e.g., last 3 commits)
git rebase -i HEAD~3

# Editor opens:
# Change "pick" to "reword" for the commits you want to rename
# Save & close

# For each "reword" commit the editor opens
# → Enter the new commit message in Conventional format

# Force push
git push --force-with-lease

Squash multiple commits:

git rebase -i HEAD~5

# Change all except the first to "squash"
# Write a new Conventional Commit message
git push --force-with-lease

📊 Impact on Releases

Semantic Versioning:

feat:      → v1.1.0 (Minor ↑)
fix:       → v1.0.1 (Patch ↑)
BREAKING:  → v2.0.0 (Major ↑)
docs/test: → v1.0.0 (no change)

Changelog Generation:

For release v1.2.0, commits are grouped:

## 🚀 Features
- feat(devices): add SSDP auto-discovery (#42)
- feat(api): add manual device registration

## 🐛 Bug Fixes
- fix(api): handle null response in device sync
- fix(docker): resolve ARM64 build timeout

## 📚 Documentation
- docs(readme): add Codecov setup guide

## ⚡ Performance
- perf(docker): optimize ARM64 build time

## 🔧 Maintenance
- chore(deps): update fastapi to 0.110.0
- ci(workflow): add security scanning

🎓 Best Practices

  1. One commit = One logical change

    • feat(api): add device endpoint
    • feat: add endpoint, fix bug, update docs (3 commits!)
  2. Commit messages are documentation

    • Subject: What was done?
    • Body: Why was it done?
  3. Use scopes

    • Helps with filtering: git log --grep="^feat(devices)"
    • Shows affected area in changelog
  4. Mark breaking changes

    • feat!: or BREAKING CHANGE: in footer
    • Users need to know that an update is breaking
  5. Issue references

    • Fixes #123 closes the issue automatically
    • Refs #42 links only

📖 Further Resources


✅ Workflow Summary

graph TD
    A[Write Code] --> B[Commit with Conventional Format]
    B --> C{Format Correct?}
    C -->|No| D[PR Check fails]
    D --> E[Rename commit]
    E --> B
    C -->|Yes| F[PR merged]
    F --> G[Create Release Tag]
    G --> H[Auto-Changelog generated]
    H --> I[GitHub Release created]
Loading

Happy Committing! 🎉

Clone this wiki locally