ACCID Commit Format
StableACCID (Atomic Conventional Consistent Immutable Durable) is a new standard for Git developer experience that combines the best practices of Conventional Commits and Atomic Commits.
ACCID provides a structured commit message format that delivers rich context about code changes while remaining human-readable and machine-parseable.
ACCID Principles
| Principle | Description |
|---|---|
| Atomic | Each commit represents a single logical change. No mixed concerns, no partial implementations. |
| Conventional | Follows structured format with standard types (feat, fix, etc.) for automated tooling and clear intent. |
| Consistent | Uniform format across all commits using URIs, types, and tags for predictable structure. |
| Immutable | Commits describe completed work, not meant to be squashed or rewritten (except in feature branches). |
| Durable | Rich context (URIs, issue IDs, tags) makes commits useful long-term for archaeology and debugging. |
Format Overview
#<issue_id> [<uri>] <type>: (tags) <summary>
- [<uri>] <change description> (tags)
- [<uri>] <change description> (tags)
(additional tags)
Footer: additional metadata Header Line
Complete Structure
#<issue_id> [<uri>] <type>: (tags) <summary> Components
| Component | Required | Description | Example |
|---|---|---|---|
#<issue_id> | Optional* | Issue/ticket identifier | #123, #JIRA-456 |
[<uri>] | Yes | Resource identifier (top-level) | [auth], [apps::gate] |
<type> | Yes | Conventional commit type | feat, fix, refactor |
(tags) | Optional | Additional context tags | (wip), (breaking) |
<summary> | Yes | Brief description (100-150 chars) | implement OAuth login |
* Required if configured in .repo.yml
Example Headers
# With issue ID
#123 [auth] feat: implement OAuth 2.0 login
# Without issue ID
[auth::services] refactor: extract AuthService
# With tags
#456 [api] feat: (breaking) migrate to REST v2
# Monorepo with app prefix
[apps::gate] fix: resolve session timeout
# Library with crate name
[libs::pixel] feat: add dark mode support URI - Resource Identifier
URIs identify what part of the codebase changed, not the file path. Think of them as logical identifiers.
URI Syntax
- Use
::to separate path segments - Use
:::for functions/methods - Skip common folders like
src/,app/ - No file extensions
- Similar to Rust module paths
Top-Level URI (Header)
Header URIs should be high-level:
[auth] # Authentication module
[apps::gate] # Gate application
[libs::pixel] # Pixel library
[docs] # Documentation
[.github] # GitHub workflows Detailed URI (Body)
Body URIs can be more specific:
# Short form (recommended)
[auth::services::AuthService]
# Full form (when needed for clarity)
[auth::services::auth_service::AuthService:::login]
# With wildcard
[auth::controllers::*] # Multiple controllers changed
[auth::_::AuthService] # Auto-determine path segment URI Examples by Language
TypeScript/JavaScript
# File: src/modules/auth/services/auth.service.ts
# Class: AuthService
# Method: login()
[auth::services::AuthService:::login]
# Or shorter:
[auth::services::AuthService] Rust
# Crate: my_app
# Module: auth::services
# Struct: AuthService
# Function: login
[my_app::auth::services::AuthService:::login]
# Crate name is mandatory for Rust Python
# File: src/auth/services/auth_service.py
# Class: AuthService
# Method: login()
[auth::services::AuthService:::login] Commit Types
| Type | Description | Example |
|---|---|---|
feat | New feature | feat: add OAuth login |
fix | Bug fix | fix: resolve memory leak |
refactor | Code refactoring | refactor: extract service |
perf | Performance improvement | perf: optimize query |
style | Code style/formatting | style: format with prettier |
test | Add/update tests | test: add auth tests |
docs | Documentation | docs: update API guide |
build | Build system/dependencies | build: upgrade deps |
ci | CI/CD changes | ci: add deploy workflow |
chore | Maintenance tasks | chore: update gitignore |
init | Initial commit/setup | init: project scaffold |
impl | Implementation progress | impl: partial OAuth flow |
Optional Tags
Opening Tags (in header)
| Tag | Meaning | Usage |
|---|---|---|
(wip) | Work in progress | Incomplete feature, don't merge yet |
(breaking) | Breaking change | Requires major version bump |
(cleanup) | Code cleanup | Removing unused code, tidying |
(housekeeping) | Maintenance | Routine maintenance tasks |
Closing Tags (before footer)
Additional context can be added as tags before the footer:
(experimental)
(requires-migration)
(db-schema-change) Body Format
Each change should be a bullet point with detailed URI:
- [<detailed_uri>] <description up to 250 chars> (tags) Example Body
- [auth::services::AuthService:::login] implement OAuth login flow
- [auth::controllers::AuthController] add /oauth/callback endpoint
- [auth::models::User] add oauth_provider and oauth_id fields (db-schema)
- [auth::tests] add OAuth integration tests Footer
Use Git trailer format for metadata:
Reviewed-by: Jane Doe <[email protected]>
Refs: #123, #456
Co-authored-by: John Smith <[email protected]> Complete Examples
Example 1: Simple Feature
#123 [auth] feat: implement OAuth 2.0 login
- [auth::services::AuthService] add OAuth provider integration
- [auth::controllers] add /oauth/callback endpoint
- [auth::models::User] add oauth_provider field
Implements standard OAuth 2.0 authorization code flow with PKCE. Example 2: Bug Fix
#456 [session] fix: resolve race condition in cleanup
- [session::services::SessionService:::cleanup] add mutex lock
- [session::tests] add concurrent cleanup test
Fixes intermittent session data corruption during cleanup. Example 3: Breaking Change
#789 [api] feat: (breaking) migrate to REST API v2
- [api::controllers::*] update all endpoints to /v2/
- [api::middleware] add version negotiation
- [api::docs] update API documentation
BREAKING CHANGE: All API endpoints moved to /v2/.
Clients must update base URL.
(requires-migration) Example 4: Multi-Module Change
#321 [*] chore: (cleanup) remove deprecated features
- [auth::legacy] remove old password auth (deprecated in v1.5)
- [api::v1] remove API v1 endpoints (deprecated in v2.0)
- [docs] remove references to deprecated features
(housekeeping) Example 5: Monorepo
[apps::gate] feat: add rate limiting middleware
- [apps::gate::middleware::RateLimiter] implement token bucket algorithm
- [apps::gate::config] add rate_limit configuration
- [apps::gate::tests] add rate limit tests Best Practices
1. Keep Summary Concise
# Good
[auth] feat: implement OAuth login
# Too verbose
[auth] feat: implement OAuth 2.0 login flow with Google provider support 2. Use Appropriate Detail Level
# Header - high level
[auth] feat: implement OAuth
# Body - detailed
- [auth::services::AuthService:::handleGoogleCallback] process callback 3. Group Related Changes
# Good - one commit for related changes
[auth] feat: implement OAuth
- [auth::services] add OAuth service
- [auth::controllers] add OAuth endpoints
- [auth::models] add OAuth fields
# Avoid - separate commits for each file
[auth] feat: add OAuth service
[auth] feat: add OAuth controller
[auth] feat: add OAuth model fields 4. Use Tags Meaningfully
# Good - clear intent
[api] feat: (breaking) change auth endpoint
# Avoid - tag spam
[api] feat: (wip) (experimental) (breaking) new feature Tools Support
AI Generation
Nanx AI can generate ACCID-format messages:
nanx r cgm # Generate ACCID commit
# Configure:
repo:
commit:
generate_message:
format: aacid Validation
Validate commit messages:
# In .repo.yml
commit:
template: aacid
require_issue_id: true # Enforce # Parsing
ACCID messages are machine-parseable for:
- Changelog generation
- Release notes automation
- Impact analysis
- Metrics and reporting
Migration from Conventional Commits
Conventional → ACCID
# Before (Conventional)
feat(auth): implement OAuth login
Add OAuth 2.0 support with Google provider.
Includes login endpoint and callback handler.
# After (ACCID)
[auth] feat: implement OAuth login
- [auth::services::AuthService] add OAuth provider integration
- [auth::controllers] add /oauth/callback endpoint
Implements OAuth 2.0 with Google provider. Why ACCID?
The Problem with Traditional Commits
Traditional commit messages often suffer from:
- ❌ Vague descriptions like "fix bug" or "update code"
- ❌ Mixing multiple unrelated changes in one commit
- ❌ Inconsistent formats across team members
- ❌ Missing context about what/where/why changes happened
- ❌ Difficult to parse for automated tooling
ACCID Advantages
- ✅ Atomic: Single logical change per commit makes bisecting and reverting clean
- ✅ Conventional: Standard types enable automated changelogs and semantic versioning
- ✅ Consistent: Uniform structure across entire team and codebase
- ✅ Immutable: Complete commits with full context, ready for main branch
- ✅ Durable: Rich metadata (URIs, issue IDs) valuable for years of maintenance
- ✅ Traceable: Issue IDs link commits to tickets and requirements
- ✅ Precise: URIs pinpoint exact modules/functions changed
- ✅ Scalable: Designed for monorepos and large projects
- ✅ Tooling-Ready: Machine-parseable for changelogs, metrics, impact analysis
Compared to Conventional Commits
| Feature | Conventional | ACCID |
|---|---|---|
| Scope | Module name | Full resource URI |
| Detail | Body free-form | Structured bullets with URIs |
| Issue linking | In footer | In header (#id) |
| Monorepo | Good | Excellent (app:: prefix) |