git bisect란 — 이진 탐색으로 범인 커밋 찾기
"어제까지 잘 되던 기능이 오늘 깨졌다. 그런데 그동안 커밋이 200개다." 이럴 때 커밋을 하나씩 되짚는 대신, git bisect는 **이진 탐색(binary search)**으로 버그가 처음 들어온 커밋을 빠르게 찾아 줍니다.
원리는 단순합니다. "정상(good)"인 커밋과 "고장(bad)"난 커밋을 알려주면, Git이 그 사이 중간 커밋으로 체크아웃해 줍니다. 당신은 테스트해서 good/bad만 답하면, Git이 다시 남은 절반의 중간으로 이동합니다. 커밋 1,000개도 약 10번(log₂1000 ≈ 10)이면 좁혀집니다.
회귀(regression)의 정확한 도입 지점을 알면 원인 분석이 극적으로 쉬워집니다. 200줄짜리 머지 커밋이 아니라 "이 한 줄을 바꾼 커밋"으로 특정되기 때문입니다.
수동 bisect — 기본 흐름
# 1. 세션 시작
git bisect start
# 2. 현재 커밋이 고장 상태라고 표시
git bisect bad
# 3. 확실히 정상이던 지점 표시 (태그·커밋 해시·상대참조 모두 가능)
git bisect good v1.4.0이 시점에 Git이 중간 커밋으로 자동 체크아웃하고 남은 후보 수를 알려 줍니다.
Bisecting: 63 revisions left to test after this (roughly 6 steps)
[a1b2c3d...] Refactor payment handler이제 이 커밋을 빌드·테스트한 뒤 결과를 답합니다.
# 여기서 재현되면
git bisect bad
# 여기서 정상이면
git bisect goodGit이 다시 절반으로 좁혀 다음 커밋으로 이동합니다. 반복하면 최종적으로 범인을 지목합니다.
b9f0e1a2c3... is the first bad commit
commit b9f0e1a2c3...
Cache user session in memory세션 종료 — reset 필수
탐색이 끝나면(또는 중단하려면) 반드시 원래 브랜치로 복귀합니다.
git bisect reset # 원래 HEAD로 복귀
git bisect reset <커밋> # 특정 커밋으로 복귀하며 종료git bisect는 탐색 중 여러 커밋을 오가며 detached HEAD 상태로 만듭니다. reset을 하지 않으면 중간 커밋에 머문 채 작업하게 되니, 끝나면 습관적으로 git bisect reset을 실행하세요.
자동화 — git bisect run
가장 강력한 기능입니다. good/bad를 판정하는 명령이나 스크립트를 넘기면, Git이 끝까지 전자동으로 탐색합니다.
판정 규칙은 **종료 코드(exit code)**로 결정됩니다.
| 종료 코드 | 의미 |
|---|---|
0 | good (정상) |
1~124, 126, 127 | bad (고장) |
125 | skip (이 커밋은 테스트 불가) |
128+ | 탐색 중단 |
git bisect start
git bisect bad
git bisect good v1.4.0
# 테스트가 통과하면 exit 0(good), 실패하면 exit 1(bad)
git bisect run npm test -- payment.spec.jsGit이 알아서 각 후보 커밋을 체크아웃하고 명령을 돌려, 최종 first bad commit을 출력한 뒤 멈춥니다. 커피 한 잔 마시고 오면 끝나 있습니다.
커스텀 판정 스크립트
빌드가 필요하거나 특정 조건을 검사해야 하면 스크립트를 씁니다. 종료 코드 규칙만 지키면 됩니다.
#!/usr/bin/env bash
# bisect-test.sh
# 컴파일 자체가 안 되는 커밋은 판정에서 제외(skip)
make build || exit 125
# 특정 증상 재현 여부로 good/bad 판정
if ./run-app --check-feature; then
exit 0 # good
else
exit 1 # bad
fichmod +x bisect-test.sh
git bisect run ./bisect-test.shexit 125(skip)는 "이 커밋은 빌드 깨짐 등으로 good/bad를 판정할 수 없음"을 뜻해, Git이 근처 다른 커밋으로 우회합니다.
skip과 로그
특정 커밋을 수동으로 건너뛰거나, 진행 기록을 남길 수 있습니다.
git bisect skip # 현재 커밋 판정 불가 → 건너뜀
git bisect skip <커밋1> <커밋2>
git bisect log > bisect.log # 지금까지의 good/bad 기록 저장
git bisect replay bisect.log # 기록을 그대로 재실행bisect visualize(또는 view)로 남은 탐색 범위를 gitk/로그로 볼 수도 있습니다.
용어 커스터마이즈 — good/bad 대신
"성능 저하"처럼 good/bad가 어색할 때 용어를 바꿀 수 있습니다.
git bisect start --term-old=fast --term-new=slow
git bisect slow # 현재가 느림
git bisect fast v1.4.0
git bisect run ./perf-check.sh실전 팁
- 재현 절차를 먼저 자동화하세요.
bisect run에 넘길 한 줄 명령이 있으면 탐색이 몇 배 빨라집니다. - good 지점을 넉넉히 잡으세요. 확실히 정상이던 오래된 태그를 good으로 두면 안전합니다. good이 사실은 이미 고장이었다면 결과가 틀어집니다.
- 테스트 격리: 각 커밋마다 의존성 설치나 캐시가 필요하면 스크립트 안에 포함하세요(
npm ci등). 안 그러면 이전 커밋의 잔재로 오판할 수 있습니다. - 머지 커밋 주의: first bad commit이 머지 커밋이면, 그 브랜치 내부를 다시 bisect해 세부 커밋으로 좁힐 수 있습니다.
버그가 언제 들어왔는지 모를 때, 로그를 눈으로 훑는 것은 선형 탐색입니다. git bisect run으로 판정만 자동화하면, 수백 개 커밋 속 범인을 로그 시간에 정확히 지목할 수 있습니다.
이 가이드는 AI 도구를 활용해 초안을 구성하고 사람이 명령어·문맥을 검토해 발행했습니다. 운영체제와 도구 버전에 따라 결과가 달라질 수 있으므로 적용 전 공식 문서를 함께 확인하세요. 오류를 발견하시면 이메일로 제보해 주세요.
질문 & 답변 (Q&A)
이 가이드에 대해 궁금한 점을 질문해보세요. 확인 후 답변드립니다.