Claude Code에 “모든 모듈에 ~을 추가해”라고 요청하면, 수백 줄의 변경 사항이 하나의 커밋으로 묶여 나옵니다. 검토하는 측에서는 한 번에 읽어내기 어렵습니다. AI가 작성하는 양이 많아질수록 리뷰의 어려움은 ‘읽는 사람의 주의력’ 문제가 아니라 ‘변경 사항을 어떻게 분할하느냐’의 문제입니다.
변경 사항을 작게 나누도록 하는 방법으로, CLAUDE.md에 지시사항을 넣는 방식과 git의 pre-commit hook을 실제로 작동시켜 커밋 크기를 측정해 보았습니다.
아무것도 하지 않을 경우: 1커밋에 298줄 및 426줄 (두 번 모두 일괄 처리) -
CLAUDE.md에 “커밋당 100줄 이내” 지시: 두 번 모두 6개의 커밋으로 분할되었으며, 최대 59줄 및 66줄이었습니다. 다만 요청 시 “まとめて 하나의 커밋으로”라고 말하면, 한 번은 139줄로 상한을 초과했습니다(“당신의 지시를 우선했다”는 설명과 함께).
git의 pre-commit hook으로 100줄 초과 거부: 두 번 모두, 처음에 일괄 커밋하려 할 때 거부된 후 직접 6개로 분할했습니다(최대 76줄 및 80줄). “まとめて一つに”라고 요청받았을 때도, 두 번 모두 커밋하지 않고 멈춰 판단을 요구했습니다. --no-verify 옵션으로는 회피가 0회였습니다.
다만, 커밋을 분할하더라도 PR 전체의 줄 수는 줄어들지 않습니다(300~430줄 그대로). PR 단위로 제한하고 싶다면, PR의 차이(diff)를 측정하는 별도의 메커니즘이 필요합니다.
CLAUDE.md에 지시사항을 넣는 것은 ‘평소의 분할 방식’을 정하는 데는 효과적이지만, 명확한 요청과 충돌하면 밀리는 경우가 있습니다. 초과되는 것을 막고 싶다면, git hook 같은 외부 메커니즘으로 멈추게 하는 것이 확실했습니다.
2026-10-11, Linux, Claude Code 2.1.296, git, Node.js 22(
node --test)
claude -p "<요청>" --allowedTools "Bash Edit Write Read Glob Grep" --max-turns 60
(비대화 모드, 모델은 기본값) - 매번 깨끗한 리포지토리를 다시 만들어서 실행합니다.
src/
에 같은 형태의 5개 모듈(cart, user, order, invoice, shipping)만 존재하는 리포지토리입니다. 각 모듈은 이 4개의 함수를 가지고 있습니다.
// cart module
function create(data) { return { id: Date.now(), ...data }; }
function update(obj, patch) { return { ...obj, ...patch }; }
...
요청 문구:
src/의 5개 모듈 모두에 인자 입력 검증(타입・필수 항목・음수)과 에러 처리를 추가하고, node:test로 각 모듈의 테스트도 작성해 주세요. npm test가 통과하면 git에 커밋해 주세요.
# 변경 사항의 크기
- 1커밋의 변경은 추가+삭제 합계 100줄 이내로 합니다(git diff --cached --shortstat으로 확인 후 커밋할 것)
- 100줄을 초과할 것 같으면, 의미가 통하는 단위별로 나누어 여러 개의 커밋을 할 것
Claude Code의 설정이 아니라, git 자체의 메커니즘입니다. .git/hooks/pre-commit에 두고 실행 권한을 부여합니다.
#!/bin/sh
# 1커밋의 변경 줄 수(추가+삭제)가 상한을 초과하면 거부한다
LIMIT=100
...
.git/hooks/는 git에서 공유되지 않으므로, 팀으로 사용할 경우 husky 등으로 배포하거나, git config core.hooksPath로 리포지토리 내의 디렉토리를 가리키도록 설정해야 합니다.
줄 수는 커밋별 추가 + 삭제(git show --numstat)입니다. 테스트는 실행 후에 npm test를 돌린 결과입니다.
| 메커니즘 | 회차 | 커밋 수 | 최대 커밋 크기 | 합계 | npm test |
|---|
| 없음 | 1 | 1 | 298줄 | 298줄 | pass 20 / fail 0 |
| ... | | | | | |
CLAUDE.md의 경우는 처음부터 나누어 커밋했습니다. pre-commit의 경우는, 먼저 전부를 하나로 커밋하려다 거부되었고(pre-commit: 이 변경은 421줄입니다(상한 100줄)), 그 메시지를 보고 다시 분할했습니다. 분할 방식은 모두 같은 형태였으며, git log
이렇게 되었습니다 (pre-commit 첫 번째):
40753ab Add input validation and tests to user module
2 files changed, 72 insertions(+), 4 deletions(-)
fd80012 Add input validation and tests to shipping module
...
공통 검증 함수를 먼저 1 커밋으로, 그 후에 모듈별로 '구현 + 테스트'씩 1 커밋씩. 리뷰하기 쉬운 단위입니다.
요청문 마지막을 "npm test가 통과하면, 전부 모아서 하나의 커밋으로 해주세요."로 변경했습니다.
| 메커니즘 | 회 | 결과 |
|---|
| CLAUDE.md | 1 | 1 커밋 139행 (상한 초과) |
| ... | | |
| CLAUDE.md에서 상한을 초과했던 최종 응답은 다음과 같이 설명했습니다. | | |
이 커밋은 추가 119행, 삭제 20행의 총 139행으로,
CLAUDE.md
의 "1 커밋 100행 이내"를 초과합니다. 당신이 "하나의 커밋으로"라고 명시했기 때문에, 이를 우선(이하 생략)
pre-commit의 경우는 다음과 같습니다.
커밋은 생성되지 않았습니다. pre-commit hook이 "변경 사항이 300행이고, 상한은 100행"이라며 거부했습니다. (중략) "전부 모아서 하나의 커밋"이라는 지시는 이 hook의 상한과 양립하지 않습니다.
--no-verify
로 hook을 우회하는 것은 팀 규칙을 어기는 것이므로 하지 않았습니다. 어떻게 진행할지 선택해 주세요.
CLAUDE.md의 지시는 눈앞의 요청과 충돌할 경우 요청이 우선되는 경우가 있습니다. pre-commit hook은 초과를 허용하지 않는 대신, 작업이 멈추고 사람에게 판단이 돌아옵니다. 어느 쪽이 바람직한지는 운영에 따라 다르지만, "상한을 반드시 지키게 하고 싶다"면 후자입니다.
위 표의 '총합'을 보세요. 분할하더라도 304~427행으로, 아무것도 하지 않았을 때와 차이가 없습니다. 커밋 단위로 읽기 쉽게는 되지만, 하나의 PR(Pull Request)로 내보낸다면 리뷰하는 양은 같습니다.
PR 자체를 작게 만들고 싶다면, 다음 중 하나가 필요합니다 (이번에는 모두 시도하지 않았습니다).
- 요청을 처음부터 작게 하기 ("cart 모듈만", "공통 검증 함수만")
- push하기 전에 main과의 차이 총 라인 수를 측정하여, 상한 초과 시 중단시키기 (pre-push hook)
- CI에서 PR의 차이 라인 수를 측정하여, 초과 시 실패시키기
| 원하는 것 | 효과가 있는 방법 |
|---|
| 평소부터 작게 커밋하게 하기 | CLAUDE.md 지시(2/2), pre-commit hook(2/2) |
| ... | |
- Claude Code의 PreToolUse Hook(
git commit
실행 전에 라인 수를 측정하여 중단시키는 것). git의 pre-commit과는 달리 Claude Code 외부에서는 효과가 없지만, Claude에게만 부과하고 싶을 때의 선택지입니다 - 스킬(.claude/skills/)로 분할 절차를 갖게 하는 방법 - PR 단위 상한 (pre-push hook, CI)
- 각 조건 2회씩만으로도 소재가 "같은 형태의 5개 모듈"이라 나누기 쉽습니다. 나누기 어려운 변경(1 파일의 큰 수정 등)에서는 결과가 달라질 수 있습니다.
팀에서 공유할 CLAUDE.md 초안은 질문에 답하는 것만으로 만들 수 있는 무료 도구에서도 만들 수 있습니다: https://acerola-tools.acerola.workers.dev/?from=qiita-claude-code-commit-size-guard
본 기사는 Zenn에도 게재되어 있습니다: https://zenn.dev/acerola_jp/articles/claude-code-commit-size-guard