Skip to content

chore: enforce single-purpose commits via pre-commit batch guard#77

Merged
singyichen merged 2 commits into
mainfrom
chore/commit-batch-guard
Jun 12, 2026
Merged

chore: enforce single-purpose commits via pre-commit batch guard#77
singyichen merged 2 commits into
mainfrom
chore/commit-batch-guard

Conversation

@singyichen

Copy link
Copy Markdown
Owner

Summary

  • The one-logical-change-per-commit rule existed in CLAUDE.md but had no mechanical enforcement — large batch commits could slip through
  • Adds a native git pre-commit hook (scripts/git-hooks/pre-commit) blocking staged changes > 10 files or > 300 non-test lines; merge commits exempt; ALLOW_BATCH_COMMIT=1 bypass requires prior user approval
  • Native git hook chosen over a Claude PreToolUse hook: chained git add && git commit has nothing staged at PreToolUse time, and git hooks also cover manual commits
  • session-init.sh sets core.hooksPath idempotently, so the guard activates on every clone without manual setup

Changed Files

File Change
scripts/git-hooks/pre-commit New batch-commit guard (thresholds, merge exemption, approved bypass)
.claude/hooks/session-init.sh Idempotent core.hooksPath setup at session start
CLAUDE.md Commit Convention gains "Single purpose per commit (enforced)" paragraph

Test Plan

Verified in a throwaway git repo with core.hooksPath pointed at the new hook:

  • Small commit (1 file) passes
  • 11 staged files blocked with exit 1 and actionable message
  • 301 non-test lines blocked
  • 301 lines under tests/ pass (test exclusion works)
  • ALLOW_BATCH_COMMIT=1 bypass works and prints warning
  • 12-file merge commit exempt
  • Dogfooded: this branch's own commit went through the active guard
  • No pytest/Playwright suites exist yet (backend//frontend/ not scaffolded) — no regression surface

🤖 Generated with Claude Code

- 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-code-review

Copy link
Copy Markdown

Qodo reviews are paused for this user.

Troubleshooting steps vary by plan Learn more →

On a Teams plan?
Reviews resume once this user has a paid seat and their Git account is linked in Qodo.
Link Git account →

Using GitHub Enterprise Server, GitLab Self-Managed, or Bitbucket Data Center?
These require an Enterprise plan - Contact us
Contact us →

@amazon-q-developer amazon-q-developer Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread scripts/git-hooks/pre-commit

@gemini-code-assist gemini-code-assist Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

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.

Comment thread scripts/git-hooks/pre-commit Outdated
…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
@singyichen singyichen merged commit 05f185b into main Jun 12, 2026
9 checks passed
@singyichen singyichen deleted the chore/commit-batch-guard branch June 12, 2026 09:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant