Git Commit with Conventional Commits
Create standardized, semantic git commits scoped to this session's work. Analyze the diff for type, scope, and message — but stage and commit only in-scope paths.
Workflow
1. Establish session scope
Derive in-scope paths from this conversation before touching git:
- Files created, edited, renamed, or deleted in this session
- Paths the user explicitly named as part of this commit
- Paths tied to the issue or feature this session is working on (when stated)
Scope unclear — stop and ask the user which files or work belong in this commit. Do not stage or commit until scope is confirmed. Triggers:
- No in-scope paths can be derived (clean session, or commit requested with no prior work in the thread)
- The user's request is vague ("commit my changes", "commit everything") and multiple unrelated changes exist in the working tree
- In-scope paths are ambiguous (e.g. overlapping features, shared files, unclear boundaries)
Done when: a concrete list of in-scope paths exists, confirmed by derivation or by the user.
2. Partition working tree changes
git status --porcelain
git diff --staged # if anything is already staged
git diff # unstaged working tree
Classify every dirty path as in-scope or out-of-scope against the list from step 1.
- Out-of-scope paths are almost certainly from another concurrent session — do not stage or commit them
- Report out-of-scope paths to the user; they can expand scope explicitly if needed
- If a file is in-scope but also contains hunks from outside this session, use
git add -pfor that file or ask the user
Done when: every dirty path is classified and out-of-scope paths are surfaced (if any).
3. Stage in-scope files only
git add path/to/in-scope-file1 path/to/in-scope-file2
git add -p path/to/mixed-file # when only some hunks belong to this session
Use path-specific git add only — never git add -A or git add . when out-of-scope dirty files exist.
Stage only paths destined to pass the private-data gate (step 4).
Done when: the staged diff contains only in-scope changes.
4. Private-data gate
Scan what will be committed — staged diff only:
git diff --cached --name-only
git diff --cached
Read references/private-data.md. Classify every staged path against secrets, PII, and sensitive-path signals. Merge optional CLI results (gitleaks, detect-secrets) when on PATH.
When findings exist — halt. List every flagged file with signal types (path:line, category, context hint — never the value). Present a structured-choices gate per that reference:
unstage_conflicts— unstage flagged paths, return to step 3 or stop if nothing remains (Recommended unless only low-confidence doc/PII hits)proceed— user accepts risk; continueabort— exit without committing
Re-run this step after re-staging following unstage_conflicts.
Done when: staged diff has zero unresolved findings, or user chose proceed via gate.
Versioned CHANGELOG.md sections (## YYYY-MM-DD · vX.Y.Z) are written by changelog-generator — apply's Changelog group, or when the user asks for a changelog. If this session already edited CHANGELOG.md, it is an in-scope path in steps 1–3 like any other file.
5. Generate commit message
Analyze the staged diff (not the full working tree) to determine:
- Type: What kind of change is this?
- Scope: What area/module is affected?
- Description: One-line summary (present tense, imperative mood, <72 chars)
6. Execute commit
# Single line
git commit -m "<type>[scope]: <description>"
# Multi-line with body/footer
git commit -m "$(cat <<'EOF'
<type>[scope]: <description>
<optional body>
<optional footer>
EOF
)"
Done when: commit succeeds and git status shows no staged in-scope changes remaining (out-of-scope dirt may still exist — that is expected).
Safety
- Session scope only — never pick up concurrent-session dirt (steps 1–3).
- Private-data gate blocks commit until resolved or user proceeds via gate (step 4).
- No git config updates, destructive commands, hook skips, or force push to main/master unless the user explicitly requests.
- Failed hooks: fix and create a new commit — do not amend unless the user asks.