Git Commit
Write clear, atomic commits. Detect and match project conventions first; use Conventional Commits as fallback. Every commit = one complete, working change.
Feature Branch Workflow
Philosophy: Commit early, commit often.
Feature branch: Create → [Change → Test → COMMIT]* → PR → Merge
Why frequent commits matter:
Benefit Description
Easy rollback Revert to last working state in seconds
Safety checkpoints Never lose more than one small step
Better debugging git bisect works with granular history
Collaboration Others see incremental progress
Automation Enables auto-changelogs and semantic versioning
Anti-pattern: One giant commit at end of feature (47 files, 2800+ lines). Split into logical increments instead.
Quick Start
Pre-Commit Checklist:
-
Code builds and tests pass
-
ONE logical change (describable in one sentence)
-
Checked project conventions (Step 1)
Workflow
Step 1: Detect Conventions (REQUIRED)
ls .commitlintrc* commitlint.config.* .czrc .cz.json 2>/dev/null git log --oneline -15
Finding Action
Config file exists Follow those rules exactly
feat: , fix: pattern Use Conventional Commits
[JIRA-123] pattern Match ticket prefix format
Component: message pattern Match component prefix format
No clear pattern Use Conventional Commits (Step 2)
Step 2: Format Message
<type>(<scope>)!: <subject> ← 50 chars ideal, 72 max ← blank line <body> ← wrap at 72 chars, optional ← blank line <footer> ← optional (Closes #123, BREAKING CHANGE)
Subject rules: Imperative mood (add not added ), lowercase after colon, no trailing period, no filler words.
Types:
Type Purpose SemVer Example
feat
New feature MINOR feat(auth): add OAuth
fix
Bug fix PATCH fix(cart): prevent neg qty
docs
Documentation
docs(api): add examples
style
Formatting
style: fix indentation
refactor
Code restructure
refactor: extract helper
perf
Performance
perf(db): add index
test
Tests
test(auth): add edge cases
build
Build/deps
build: update webpack
ci
CI config
ci: add deploy workflow
chore
Maintenance
chore: update gitignore
revert
Revert previous commit
revert: let us not...
Breaking changes: Add ! after type/scope, explain in body/footer.
feat(api)!: require API key for all endpoints
BREAKING CHANGE: Anonymous access removed. All requests need X-API-Key header.
Step 3: Body (When Needed)
Required Optional
Breaking change (impact/migrate) Self-explanatory from diff
Non-obvious fix (root cause) Simple docs/style/chore
Complex feature (design decision) Tests with descriptive names
Body content: WHY (motivation), WHAT problem, HOW users affected. Not: Which files (diff shows), line-by-line explanation (code comments).
Step 4: Footer
Closes #123 # Issue reference Fixes #456 # Also closes issue Refs: #789 # Reference without closing BREAKING CHANGE: <description> # If not in body Co-authored-by: Name <email@example.com> # Co-authorship Reviewed-by: Name # Use hyphens in tokens
Commit Granularity
Atomic Commit = Smallest Complete Change
-
ONE purpose - single feature/fix/refactor
-
Self-contained - doesn't depend on uncommitted work
-
Leaves code working - builds pass, tests pass
-
Revertable alone - without breaking other features
What Goes Together vs Separate
Together (same commit) Separate (different commits)
Feature + its unit tests Feature + unrelated formatting
Bug fix + regression test Bug fix + dependency update
API change + docs update Refactor + new feature
Refactor + affected tests Multiple unrelated fixes
When to Commit (Triggers)
Trigger Action
Function works and tested COMMIT now
Test passes (red → green) COMMIT now
Bug fixed and verified COMMIT before next task
About to refactor COMMIT working state first
Starting new sub-task COMMIT current progress
End of session / before pull COMMIT if working
Key: Before starting new task, commit all current task changes.
When NOT to Commit
Situation Why
Code doesn't build Breaks bisect, blocks others
Tests failing* Not a valid checkpoint
"I think this works" (untested) Verify first, commit second
Mid-debugging / mid-fix Wait until fix is complete
Uncertain about approach Prototype first, commit when solid
CI still running / red Wait for green, then commit fix
*Exception: TDD RED commits (test-only commits that intentionally fail) are valid.
"Commit often" means verified working increments, not untested guesses.
❌ BAD: Commit-and-pray workflow ───────────────────────────────
- Write fix
- "Looks right to me" → commit
- Push → CI fails
- "Oops, forgot X" → commit again
- Push → CI fails again
- Repeat 3 more times... Result: 5 broken commits in history
✓ GOOD: Verify-then-commit workflow ───────────────────────────────
- Write fix
- Run tests locally → fails
- Fix the issue
- Run tests locally → passes
- Commit
- Push → CI passes Result: 1 clean commit
Rule: If CI or local tests are red, you're not done. Fix first, verify, then commit.
TDD Pattern
test(auth): add failing test for validation # RED feat(auth): implement validation # GREEN refactor(auth): extract to helper # REFACTOR
Examples
See references/examples.md for comprehensive examples. Quick reference:
Feature with context
feat(auth): add password strength indicator
Users lacked feedback on password quality during signup. Add real-time strength meter, requirements checklist, submission block.
Closes #234
Bug fix with root cause
fix(api): handle null response from payment gateway
Gateway returns null on timeout. Add null check with retry logic.
Fixes #567
Simple changes (no body needed)
docs(readme): add Docker installation steps test(utils): add edge case tests for date parser chore(deps): update lodash to 4.17.21
Bad Problem Good
fix bug
No context fix(cart): prevent duplicate items
update code
Meaningless refactor(api): simplify errors
WIP
Incomplete Finish work, then commit
misc fixes
Multiple changes Split into separate commits
Integration
When Skill Why
Before committing code-quality
Ensure checks pass
After committing docs-check
Check if docs need update
After PR review pr-review → git-commit
Resolve then commit
References
- references/examples.md
- Extended examples by scenario
Output
Git commits created via standard git commands. No files saved. Commit history visible via git log .