LabHub
배우기 러닝패스 코스

Git実戦

ルールをフックに掛けたのに、一語で素通りされた

LabHub 에서 이어서 보기

한국어 원문으로 표시합니다.

목표

저장소에 담아 공유되는 클라이언트 훅 셋을 만들고, 그것이 무엇을 막고 무엇을 못 막는지 직접 확인합니다.

왜 중요한가

훅은 "규칙을 자동화한다" 는 말로 소개되지만, 클라이언트 훅이 실제로 하는 일은 빠른 피드백입니다. 강제가 아닙니다. 이 차이를 모르고 규칙을 클라이언트에만 걸어 두면, 지켜지고 있다고 믿는 상태로 오래 갑니다. 이 실습은 그 믿음을 직접 깨 봅니다 — 규칙을 셋 만들고, 한 낱말로 전부 지나갑니다. 그리고 pre-commit 이 작업 트리를 읽으면 왜 안 되는지를, 인덱스에만 비밀이 있는 상태를 만들어 확인합니다. 커밋되는 것은 인덱스이지 작업 트리가 아니라는 사실은 훅을 쓰지 않더라도 알아 둘 값이 있습니다.

단계

  1. /root/gitx9/repo 를 만들고 core.hooksPath.githooks 로 지정합니다.
  2. .githooks/commit-msg 로 제목 형식을 강제하고, 거절당한 기록을 notes/reject.txt 에 남깁니다.
  3. .githooks/pre-commit 으로 100000 바이트를 넘는 파일을 막고 notes/bigfile.txt 에 남깁니다.
  4. 그 훅이 인덱스를 보게 고쳐 AKIA 로 시작하는 문자열을 막고, 작업 트리만 보면 왜 뚫리는지를 notes/index.txt 에 남깁니다.
  5. --no-verify 로 규칙을 어긴 커밋을 하나 만들고 notes/bypass.txt 에 남깁니다.
  6. /root/gitx9/clone 을 떠서 무엇이 따라오고 무엇이 안 따라오는지를 notes/share.txt 에 남깁니다.
  7. /root/gitx9/origin.git 을 만들고 .githooks/pre-pushmain 직접 push 를 막아 notes/prepush.txt 에 남깁니다.
  8. notes/report.md 에 클라이언트 훅과 서버 훅의 역할을 정리합니다.

참고

훅을 저장소 안에 두기로 한다

/root/gitx9/repo 를 만들고 core.hooksPath.githooks 로 지정합니다.

.git/hooks/ 는 clone 으로 따라오지 않습니다. git config core.hooksPath .githooks 로 훅을 찾는 자리를 저장소가 추적하는 디렉터리로 옮기세요. 디렉터리도 미리 만들어 둡니다. 저장소마다 user.emailuser.name 도 지정해야 커밋이 됩니다.

제목 형식을 강제한다

.githooks/commit-msg 로 제목 형식을 강제하고, 거절당한 기록을 notes/reject.txt 에 남깁니다.

commit-msg 훅은 메시지 파일 경로를 $1 로 받습니다. 첫 줄만 보고 <타입>(<범위>): <설명> 형식인지 grep -qE 로 검사하세요. 타입은 feat·fix·docs·refactor·test·chore·build 정도면 됩니다. 어긋나면 표준 오류로 무엇이 잘못됐는지 말하고 0이 아닌 값으로 끝내야 합니다. chmod +x 를 잊지 마세요.

큰 파일을 커밋 전에 막는다

.githooks/pre-commit 으로 100000 바이트를 넘는 파일을 막고 notes/bigfile.txt 에 남깁니다.

pre-commit 은 인자를 받지 않습니다. 무엇이 커밋되려는지는 git diff --cached --name-only --diff-filter=ACM 으로 스스로 알아내야 합니다. 크기가 100000 을 넘으면 어떤 파일이 몇 바이트인지 말하고 0이 아닌 값으로 끝내세요. 막히는 것을 직접 확인한 뒤에는 그 큰 파일을 스테이징에서 내려 두세요.

커밋되는 것은 작업 트리가 아니라 인덱스다

그 훅이 인덱스를 보게 고쳐 AKIA 로 시작하는 문자열을 막고, 작업 트리만 보면 왜 뚫리는지를 notes/index.txt 에 남깁니다.

인덱스에 올라간 blob 은 git ls-files -s -- <경로> 의 둘째 칸이고, 내용은 git cat-file -p <blob> 또는 git show :<경로> 로 읽습니다. 크기도 git cat-file -s <blob> 로 재세요. 그다음 파일에 AKIAIOSFODNN7EXAMPLE 를 써서 git add 하고, 작업 트리 쪽 파일만 깨끗하게 고친 뒤 커밋해 보세요. 작업 트리를 읽는 훅이라면 그대로 통과했을 커밋입니다.

한 낱말로 전부 지나간다

--no-verify 로 규칙을 어긴 커밋을 하나 만들고 notes/bypass.txt 에 남깁니다.

git commit --no-verifypre-commitcommit-msg 를 건너뜁니다. 제목 규칙을 어긴 커밋을 하나 만들어 이력에 남기세요. 그리고 이것이 결함이 아니라 설계라는 것, 그래서 강제력이 필요한 규칙은 어디에 걸어야 하는지를 함께 적습니다.

훅 파일은 따라오고 설정은 안 따라온다

/root/gitx9/clone 을 떠서 무엇이 따라오고 무엇이 안 따라오는지를 notes/share.txt 에 남깁니다.

git clone /root/gitx9/repo /root/gitx9/clone 을 하고, 그 안에서 세 가지를 보세요 — .githooks/ 에 무엇이 있는지, git config --local core.hooksPath 가 무엇을 내는지, .git/hooks/ 에 무엇이 있는지. 확인한 뒤 clone 에서도 core.hooksPath 를 켜세요.

보호 브랜치를 클라이언트에서 막아 본다

/root/gitx9/origin.git 을 만들고 .githooks/pre-pushmain 직접 push 를 막아 notes/prepush.txt 에 남깁니다.

pre-push 는 표준 입력으로 줄마다 로컬참조 로컬해시 원격참조 원격해시 를 받습니다. 원격참조refs/heads/main 인 줄이 있으면 막으세요. 원격은 git init --bare /root/gitx9/origin.git 으로 만들고 git remote add origin 으로 붙입니다. main push 가 막히는 것을 확인한 뒤 기능 브랜치만 올리세요.

어느 자리가 알려 주고 어느 자리가 막는가

notes/report.md 에 클라이언트 훅과 서버 훅의 역할을 정리합니다.

표 하나와 규칙 몇 줄이면 됩니다. 클라이언트 훅이 못 막는 세 가지를 반드시 적고, 그래서 같은 규칙을 두 자리에 거는 이유로 마무리하세요. 훅이 느리면 사람들이 우회를 습관으로 쓴다는 실무 조언도 값이 있습니다.