LabHub

Git 실전 · 이등분과 고고학 · 이론

1,000개 커밋에서 범인을 10번 만에 찾기

LabHub 에서 이어서 보기

한 줄 요약

"두 달 전엔 됐는데 지금은 안 된다" 에서 커밋 하나를 특정하는 데 필요한
검사 횟수는 커밋 수가 아니라 log₂(커밋 수) 입니다. 1,000개면 10번입니다.

왜 이게 필요했나

버그 리포트가 왔습니다. "예전엔 잘 됐는데요."

git log 를 열면 그 사이에 커밋이 800개 있습니다. 하나씩 확인하면
800번이고, 눈으로 훑으면 "관련 있어 보이는" 커밋에 편향됩니다. 그리고
경험상 범인은 대개 관련 없어 보이는 커밋입니다.

git bisect 는 이진 탐색을 자동으로 해 줍니다.

git bisect startgit bisect bad                 # 지금은 깨져 있다git bisect good v1.4.0         # 이 버전에서는 됐다# → git 이 중간 커밋으로 체크아웃한다# 확인 후git bisect good   또는   git bisect bad# 반복. 10번이면 끝난다.git bisect reset

자동화 — bisect run

검사를 스크립트로 쓸 수 있으면 사람이 앉아 있을 필요도 없습니다.

git bisect start HEAD v1.4.0git bisect run ./check.sh

check.sh종료코드로 말합니다.

| 종료코드 | 뜻 |
| --- | --- |
| 0 | good |
| 1–124, 126, 127 | bad |
| 125 | skip — 이 커밋은 판정 불가(빌드 실패 등) |

125가 중요합니다. 중간에 빌드가 깨진 커밋이 섞여 있을 때, 그걸 bad 로
판정하면 엉뚱한 곳으로 수렴합니다. 판정할 수 없으면 skip 을 돌려야 합니다.

#!/bin/bashmake build || exit 125          # 빌드 실패 = 판정 불가./run-test.sh || exit 1         # 테스트 실패 = badexit 0                          # 통과 = good

bisect 를 위한 전제

이등분이 잘 되려면 커밋 하나하나가 빌드되고 실행되는 상태여야 합니다.
"WIP", "작업 중", "일단 커밋" 같은 커밋이 잔뜩이면 skip 만 늘어납니다.
평소에 작고 완결된 커밋을 쌓는 습관이 여기서 값을 합니다.

log -S — 그 코드가 언제 들어왔나

특정 문자열이 추가되거나 삭제된 커밋만 찾습니다.

git log -S 'timeout=3' --oneline

"이 설정값이 언제 3으로 바뀌었지?" 에 한 번에 답합니다. 정규식으로
찾으려면 -G 를 씁니다.

git log -p -- path/to/file 로 파일 하나의 변경 이력만 볼 수도 있고,
--follow 를 붙이면 이름이 바뀐 이력까지 따라갑니다.

blame — 누가 아니라 왜

git blame 은 각 줄을 마지막으로 고친 커밋을 보여 줍니다. 목적은
책임자 찾기가 아니라 맥락 찾기 입니다. 그 줄이 왜 그렇게 쓰였는지는
커밋 메시지와 그 커밋의 다른 변경에 있습니다.

git blame -L 40,60 src/app.py        # 40~60행만git blame -w                         # 공백 변경 무시git blame -C                         # 다른 파일에서 옮겨온 코드도 추적

-w 가 특히 유용합니다. 포매터를 한 번 돌린 저장소에서는 모든 줄이
"포매팅 커밋" 으로 나오는데, -w 는 그걸 건너뛰고 실제 변경을 찾아 줍니다.

reflog — 잃어버린 것을 되찾기

git reflog 는 HEAD 가 움직인 모든 기록입니다. 리베이스를 잘못했거나
브랜치를 지웠어도, 커밋 자체는 한동안 살아 있습니다.

git reflog# a1b2c3d HEAD@{5}: rebase (finish): returning to refs/heads/main# 9f8e7d6 HEAD@{6}: commit: 잃어버린 작업git checkout -b rescue 9f8e7d6

"git 에서 커밋한 것은 웬만하면 안 사라진다" 는 말의 근거가 reflog 입니다.

현장에서 만나는 모습

다음 실습에서 할 것

40개짜리 이력을 직접 만들고 범인을 찾습니다. 그 이력에는 **판정할 수 없는
커밋이 하나** 섞여 있어서, 125 를 안 쓰면 bisect 가 엉뚱한 커밋을 확신 있게
지목합니다. 두 스크립트를 나란히 돌려 그 차이를 눈으로 봅니다.

그리고 125 를 제대로 쓰면 이번에는 bisect 가 **후보 두 개까지만 좁히고
멈춥니다.** 마지막 한 걸음은 사람이 정합니다 — 자동화가 끝나는 자리가
어디인지가 이 실습의 결론입니다.