Skip to content

Commit Conventions

Overview

Consistent commit messages improve readability, enable automation, and make git history useful.

We follow Conventional Commits with audio-specific extensions.

Format

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

[optional body]

[optional footer]

Type (Required)

  • feat: New feature
  • fix: Bug fix
  • perf: Performance improvement
  • refactor: Code restructuring without behavior change
  • test: Adding or updating tests
  • docs: Documentation only
  • build: Build system, dependencies, cmake
  • ci: CI/CD configuration
  • style: Formatting, whitespace (not CSS)
  • chore: Maintenance tasks

Indicates what part of codebase is affected:

By module: - core: Core abstractions - dsp: DSP utilities - buffer: Buffer management - math: Math primitives - param: Parameter system - rt: Real-time utilities - platform: Platform abstraction - serial: Serialization - lifecycle: Plugin lifecycle - event: Event system

By area: - api: Public API changes - internal: Internal implementation - tests: Test infrastructure - examples: Example code - docs: Documentation

Subject (Required)

  • Use imperative mood ("add" not "added" or "adds")
  • Don't capitalize first letter
  • No period at the end
  • Limit to 50 characters
  • Be specific and descriptive

Body (Optional)

  • Explain why, not what (code shows what)
  • Wrap at 72 characters
  • Separate from subject with blank line
  • Reference issues: Fixes #123, Closes #456
  • Breaking changes: BREAKING CHANGE: description
  • Related PRs: Related to #789

Examples

Simple Feature

feat(buffer): add circular buffer implementation

Bug Fix with Issue Reference

fix(dsp): resolve phase cancellation in stereo processing

The stereo width calculation was inverting the phase incorrectly.
Changed to use proper mid/side encoding.

Fixes #42

Performance Improvement

perf(math): use SIMD for fast exp approximation

Replaced scalar loop with SSE intrinsics.
Benchmark shows 4x speedup on typical inputs.

Breaking Change

feat(api): change parameter range from 0-1 to -1 to 1

BREAKING CHANGE: All parameters now use bipolar range.
Migration guide in docs/migration/v2.md.
refactor(core): reorganize observer pattern implementation

- Move Subject/Observer to core_interfaces
- Add thread-safe notification queue
- Update docs with usage examples

Related to #15, #23

Build System

build(cmake): add vcpkg integration for dependencies

Documentation

docs(readme): add quick start guide for new contributors

Test Addition

test(buffer): add edge case tests for wraparound

Audio-Specific Guidelines

RT Safety Changes

feat(param): add lock-free parameter update queue

Enables RT-safe parameter changes from UI thread.
No allocations or locks in audio callback.

DSP Algorithms

feat(dsp): implement state variable filter

Based on Hal Chamberlin's design.
Includes LP, HP, BP, Notch modes.

Platform-Specific Fixes

fix(platform): correct CPU feature detection on ARM

NEON detection was failing on M1 Macs.
Now uses proper sysctl query.

Anti-Patterns

❌ Too Vague

fix: update code
chore: changes
feat: improvements

❌ Too Detailed (Put in Body)

feat: add new parameter class that supports ranges and also has automation and also validation

❌ Multiple Unrelated Changes

feat: add buffer + fix docs + update cmake
Should be 3 separate commits.

❌ Wrong Mood

feat: added feature    // ❌ past tense
feat: adds feature     // ❌ present tense
feat: add feature      // ✅ imperative

Tips

Commit Often

# Good: Small, focused commits
git commit -m "feat(buffer): add capacity check"
git commit -m "test(buffer): add capacity tests"
git commit -m "docs(buffer): document capacity behavior"

# Bad: One giant commit
git commit -m "feat(buffer): complete implementation"

Use git commit -v

Shows diff while writing message - helps write better descriptions.

Check Before Pushing

# Review commit history
git log --oneline -5

# Amend last commit if needed
git commit --amend

# Interactive rebase to clean up
git rebase -i HEAD~3

Automation

Generate Changelog

# All features since last tag
git log --oneline --grep="^feat"

# All fixes
git log --oneline --grep="^fix"

Lint Commits

# commitlint config (optional)
npm install --save-dev @commitlint/{cli,config-conventional}
echo "module.exports = {extends: ['@commitlint/config-conventional']};" > commitlint.config.js

Git Hooks

# .git/hooks/commit-msg
#!/bin/bash
if ! grep -qE "^(feat|fix|perf|refactor|test|docs|build|ci|style|chore)(\(.+\))?: .+" "$1"; then
    echo "ERROR: Commit message doesn't follow conventional commits"
    exit 1
fi

Squashing Commits

When merging PRs, decide:

Keep all commits when: - Each commit is valuable history - Commits are well-formed - Incremental changes matter

Squash commits when: - Many "fix typo" commits - Work-in-progress commits - Easier to review as single change

Template

Save as .gitmessage:

# <type>(<scope>): <subject>
#
# [optional body]
#
# [optional footer]
#
# Type: feat, fix, perf, refactor, test, docs, build, ci, style, chore
# Scope: module or area affected
# Subject: imperative mood, lowercase, no period, <50 chars
# Body: wrap at 72 chars, explain why not what
# Footer: Fixes #issue, BREAKING CHANGE, etc.

Use it:

git config commit.template .gitmessage

Resources