chore: enforce single-purpose commits via pre-commit batch guard#77
Conversation
- the one-logical-change-per-commit rule existed in CLAUDE.md but had no mechanical enforcement; large batch commits slipped through unnoticed - native git pre-commit hook sees the true staged set, unlike a PreToolUse hook which fires before chained 'git add && git commit' stages anything, and also covers manual commits - thresholds (>10 files or >300 non-test lines) align with the existing PR escalation gate; merge commits exempt; ALLOW_BATCH_COMMIT=1 bypass requires prior user approval - session-init.sh sets core.hooksPath idempotently so the guard activates on every clone without manual setup
Qodo reviews are paused for this user.Troubleshooting steps vary by plan Learn more → On a Teams plan? Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center? |
There was a problem hiding this comment.
This PR introduces a mechanical enforcement mechanism for the single-purpose-per-commit rule through a native git pre-commit hook. The implementation is mostly sound with clear thresholds and exemptions.
Critical Issue Identified:
- The pre-commit hook lacks error handling for git operations that could fail outside a repository context, which could cause unexpected behavior.
Recommendation: Address the identified issue before merging to ensure the hook behaves correctly in all scenarios.
You can now have the agent implement changes and create commits directly on your pull request's source branch. Simply comment with /q followed by your request in natural language to ask the agent to make changes.
There was a problem hiding this comment.
Code Review
This pull request introduces a git pre-commit hook to enforce a "single purpose per commit" rule by blocking commits with more than 10 staged files or 300 non-test lines. It also updates the session initialization script to automatically configure the git hooks path and documents this rule in CLAUDE.md. The review feedback highlights potential issues in the pre-commit hook script, specifically regarding the pipefail behavior when grep finds no matches and the use of a literal tab character in the regex, suggesting a refactored awk command to address both concerns.
Important
The consumer version of Gemini Code Assist on GitHub is being sunset. Starting June 18, 2026, new organization installations will be blocked, and all code review activity will officially cease on July 17, 2026.
For more details on the timeline and next steps, please review the Help Documentation.
…view) - the grep pattern embedded a literal tab character that editors with expandtab could silently convert to spaces, breaking test exclusion - awk regex accepts \t as an escape, eliminating the fragility and the grep process; also sidesteps the pipefail exit-1 edge when a commit stages only test files - re-verified all 7 hook cases incl. path-root e2e/ exclusion and --allow-empty commit
Summary
scripts/git-hooks/pre-commit) blocking staged changes > 10 files or > 300 non-test lines; merge commits exempt;ALLOW_BATCH_COMMIT=1bypass requires prior user approvalgit add && git commithas nothing staged at PreToolUse time, and git hooks also cover manual commitssession-init.shsetscore.hooksPathidempotently, so the guard activates on every clone without manual setupChanged Files
scripts/git-hooks/pre-commit.claude/hooks/session-init.shcore.hooksPathsetup at session startCLAUDE.mdTest Plan
Verified in a throwaway git repo with
core.hooksPathpointed at the new hook:tests/pass (test exclusion works)ALLOW_BATCH_COMMIT=1bypass works and prints warningbackend//frontend/not scaffolded) — no regression surface🤖 Generated with Claude Code