Git Commit Best Practices (limps)
Purpose
Guide the creation of clear, meaningful Git commits that follow conventional commit standards and repository-specific conventions. Ensures commits are atomic, well-documented, and integrate with automated tooling (release-please, changelog generation).
Scope
- •If
$ARGUMENTSis "review-commits" or a commit range (e.g.,HEAD~5..HEAD,main..HEAD), review existing commits and suggest improvements. - •If
$ARGUMENTSis a scope (paths or component), provide commit guidance for those changes. - •If no arguments provided, guide commit message creation for staged changes.
Detecting Breaking Changes
When reviewing commits, detect breaking changes by:
- •Parse commit messages:
git log --format="%H%n%s%n%b" <range>(includes full body) - •Search for footer: Look for
BREAKING CHANGE:orBREAKING CHANGEin commit body (case-insensitive) - •Extract description: Everything after
BREAKING CHANGE:until:- •Next footer (e.g.,
Closes #123,Fixes #456) - •End of commit message
- •Empty line followed by non-footer text
- •Next footer (e.g.,
- •Example commands:
- •Simple:
git log --format=%B main..HEAD | grep -A 10 -i "BREAKING CHANGE" - •More robust:
git log --format="%H%n%s%n%b%n---" <range>then parse each commit separately
- •Simple:
- •Edge cases:
- •Multi-line breaking changes: Extract until next footer or end
- •Breaking change in subject: Look for
!after type/scope:feat!: breaking change - •Merge commits: Check merge commit message for breaking changes
Conventional Commit Format
Structure
<type>(<scope>): <subject> <body> <footer>
Types
- •
feat: New feature (triggers minor version bump) - •
fix: Bug fix (triggers patch version bump) - •
docs: Documentation changes only - •
style: Code style changes (formatting, whitespace, no logic change) - •
refactor: Code refactoring (no feature change or bug fix) - •
perf: Performance improvements - •
test: Adding or updating tests - •
chore: Maintenance tasks (deps, config, build) - •
ci: CI/CD changes - •
build: Build system changes - •
revert: Revert a previous commit
Scope (Optional but Recommended)
- •Single scope (most common): Package name (
limps,limps-headless) or component (cli,server,tools,resources,rlm,indexer) - •Multiple scopes: Use comma-separated for cross-package changes:
feat(limps,limps-headless): ... - •When to use multiple: Only when change affects multiple packages/components in same commit
- •Area scopes:
config,mcp,extensions,watcher(use when change is area-specific, not package-specific)
Subject Line Rules
- •Imperative mood: "add feature" not "added feature" or "adds feature"
- •Lowercase (except proper nouns, acronyms)
- •No period at the end
- •50 characters or less (ideally)
- •Clear and specific: Describe what the commit does, not why (why goes in body)
Body (Optional but Recommended for Complex Changes)
- •Separated by blank line from subject
- •72 characters per line (wrap if needed)
- •Explain what and why (not how - code shows how)
- •Reference related issues, plans, or agents
- •Note breaking changes if applicable
Footer (Optional)
- •Breaking changes:
BREAKING CHANGE: <description> - •Issue references:
Closes #123,Fixes #456,Related to #789 - •Plan/Agent references:
Plan: NNNN-plan-name,Agent: 008
Examples
Simple Feature
feat(limps): add config migration utility Adds utility to migrate config files between versions, handling backward compatibility and preserving user settings. Related to plan NNNN-plan-name
Bug Fix with Issue Reference
fix(server): handle missing config gracefully Previously, missing config files would crash the server. Now returns helpful error message and exits cleanly. Fixes #42
Breaking Change
refactor(config): restructure config schema BREAKING CHANGE: Config file format changed from JSON to YAML. Existing configs must be migrated using `limps config migrate`. Migration guide: docs/config-migration.md
Multi-Package Change
feat(limps,limps-headless): add extension system Adds extension loader and context system to both packages. Extensions can register custom tools and resources. Plan: NNNN-plan-name Agent: 007
Documentation Only
docs: update CLAUDE.md with extension system details Adds documentation for extension development and integration.
Atomic Commits
Principles
- •One logical change per commit: Each commit should represent a complete, working change
- •Buildable and testable: Each commit should leave the repo in a valid state
- •Reviewable: Changes should be grouped logically for code review
When to Split Commits
- •Different types of changes (e.g., refactor + feature)
- •Unrelated files or subsystems
- •Formatting/style changes separate from logic changes
- •Test changes separate from implementation
When to Combine Commits
- •Related changes that depend on each other
- •Small, related fixes in the same file
- •Documentation updates that accompany code changes
Repository-Specific Guidelines
Monorepo Considerations
- •Specify package scope when changes are package-specific:
feat(limps): ... - •Use root-level scope for cross-package changes:
feat: ...orfeat(limps,limps-headless): ... - •Workspace-aware: Consider impact on other packages
Plan/Agent Integration
- •Reference plans/agents in commit body when applicable:
- •
Plan: NNNN-plan-name - •
Agent: 008-complex-parsing
- •
- •Use agent titles in subject when committing agent work:
- •
feat(limps-headless): implement complex parsing logic - •Body:
Agent: 008-complex-parsing
- •
Release-Please Integration
- •Type matters:
feat→ minor bump,fix→ patch bump - •Breaking changes: Use
BREAKING CHANGE:footer for major bumps - •Scope helps: Package-scoped commits help release-please target correct package
Changelog Generation
- •Commits with conventional format automatically appear in CHANGELOG.md
- •Body content may be included in changelog entries
- •Reference issues/PRs for better changelog links
Workflow
Before Committing
- •Review staged changes:
git diff --cached - •Check for unrelated changes: Split if needed
- •Verify tests pass:
npm test(or workspace-specific:npm test --workspace <name>) - •Check formatting:
npm run format:check(repo-specific command)- •Note: These commands are limps-specific; adapt for other repos
Creating the Commit
- •Determine type: What kind of change is this?
- •Identify scope: Which package/component?
- •Write subject: Clear, imperative, concise
- •Add body (if needed): Explain context, why, related items
- •Add footer (if needed): Issues, breaking changes, plans
After Committing
- •Review commit:
git log -1to verify format - •Amend if needed:
git commit --amend(before pushing)
Reviewing Commits
When reviewing commits (e.g., review-commits argument or commit range):
- •Parse commits:
git log --format="%H%n%s%n%b%n---" <range>to get full commit messages - •Check format: Does it follow conventional commits? (
<type>(<scope>): <subject>) - •Evaluate atomicity: Should this be split or combined?
- •Assess clarity: Is the message clear and informative?
- •Verify completeness: Does it reference related issues/plans?
- •Check breaking changes: Look for
BREAKING CHANGE:footer or!in type - •Suggest improvements: Provide specific recommendations with examples
Review Output Format
When reviewing commits, use this structure:
## Commit Review: <commit-range> ### Summary - Total commits: X - Format compliance: Y compliant, Z need improvement - Breaking changes: Found in commits [list] ### Findings by Commit #### Commit <hash>: <subject> - ✅ Format: Conventional commit format - ⚠️ Issues: [if any] - 🔴 Critical: [if any] - Suggestions: [specific improvements] ### Overall Recommendations - [Action items]
Common Mistakes to Avoid
❌ Too vague: fix: update code
✅ Specific: fix(server): handle undefined config paths
❌ Past tense: feat: added new feature
✅ Imperative: feat: add new feature
❌ Too long subject: feat(limps): implement comprehensive configuration management system with validation and migration support
✅ Concise: feat(limps): add config validation and migration
❌ Multiple unrelated changes: One commit with formatting + feature + test ✅ Separate commits: One for formatting, one for feature, one for test
❌ Missing context: fix: bug fix
✅ With context: fix(indexer): prevent SQL injection in search queries
Output Format
When providing commit guidance:
## Suggested Commit Message <type>(<scope>): <subject> <body> ## Rationale - Why this type/scope - What makes it atomic - Related items (issues, plans, agents) ## Checklist - [ ] Subject is imperative and clear - [ ] Scope is appropriate - [ ] Body explains context (if needed) - [ ] Footer references issues/plans (if applicable) - [ ] Commit is atomic - [ ] Tests pass
Notes
- •Prefer
git commitwith message over-mfor complex commits (opens editor) - •Use
git commit --amendto fix commit messages before pushing - •Use
git rebase -ito clean up commit history (before pushing) - •Conventional commits enable automated tooling (release-please, changelog)
- •Clear commits make code review and debugging easier
- •Merge commits: Review merge commit messages; they should describe what's being merged
- •Squash commits: When squashing, combine commit messages meaningfully
- •Revert commits: Use
revert: <original-subject>format:revert: feat(limps): add feature