프로그래밍/Git, IDE, 툴 관련

Git bisect 사용법

포도알77 2026. 7. 8. 11:32

Git bisect 사용법

git bisect는 특정 버그나 동작 변화가 처음 나타난 커밋을 이분 탐색 방식으로 좁혀 가는 Git 명령이다. 2026년 7월 8일 확인 기준 Git 공식 문서는 이 명령을 "버그를 도입한 커밋을 찾기 위한 binary search"로 설명한다.

실무에서는 "어느 커밋부터 테스트가 깨졌는지", "어느 시점부터 성능이 느려졌는지", "어느 변경에서 동작이 바뀌었는지"를 빠르게 좁히는 데 쓴다. 이 글은 Git 공식 문서를 기준으로 start, good/bad, skip, run, reset, 그리고 --first-parent 같은 선택 기준을 정리한다.

Git bisect는 언제 쓰면 될까?

전제는 단순하다. 현재 상태 중 하나는 문제가 있고, 과거 상태 중 하나는 문제가 없다는 사실을 알고 있어야 한다. Git 공식 문서도 먼저 "bad" 커밋 하나와 버그가 들어오기 전의 "good" 커밋 하나를 알려 주면, 그 사이의 커밋을 Git이 중간 지점부터 골라 준다고 설명한다.

그래서 재현 가능한 회귀 버그, 테스트 통과 여부, 특정 속성의 존재 여부처럼 각 커밋을 두 상태로 판정할 수 있을 때 가장 잘 맞는다. 반대로 결과가 들쭉날쭉하거나, 특정 시점이 good인지 bad인지 안정적으로 분류되지 않으면 bisect 결과 해석도 어려워진다.

가장 기본 흐름은 무엇일까?

가장 기본적인 흐름은 시작점 지정, 각 커밋 판정, 종료 후 원복의 세 단계다. Git 공식 문서 예시는 현재 커밋을 bad, 과거의 알려진 정상 버전을 good으로 지정한 뒤, Git이 제안하는 커밋을 하나씩 테스트하라고 안내한다.

git bisect start
git bisect bad
git bisect good v1.0.0

이후 Git이 체크아웃한 중간 커밋을 빌드하거나 테스트한 다음, 문제가 있으면 git bisect bad, 없으면 git bisect good을 반복한다. 모든 후보가 좁혀지면 Git이 첫 번째 bad 커밋을 알려 준다.

종료할 때 왜 git bisect reset이 중요할까?

Bisect 도중에는 여러 커밋을 계속 체크아웃하므로, 끝난 뒤 원래 작업 위치로 돌아오는 정리 단계가 필요하다. 공식 문서에 따르면 git bisect reset은 bisect 시작 전 체크아웃돼 있던 원래 HEAD로 돌아가면서 bisection 상태를 정리한다.

원하면 git bisect reset <commit>처럼 다른 커밋으로 끝낼 수도 있다. 예를 들어 찾은 첫 bad 커밋 위에 그대로 머물고 싶다면 그 커밋을 인자로 줄 수 있다.

good/bad 대신 다른 용어를 쓸 수 있을까?

그럴 수 있다. 공식 문서는 버그 도입 시점뿐 아니라 어떤 속성이 처음 나타난 시점도 찾을 수 있다고 설명하면서 good/bad 대신 old/new를 지원한다고 안내한다.

예를 들어 버그 수정이 처음 들어간 커밋을 찾고 싶다면 현재 상태를 new, 과거 상태를 old로 두는 방식이 더 자연스럽다. 문서는 git bisect start --term-old broken --term-new fixed처럼 사용자 정의 용어도 허용한다.

테스트할 수 없는 커밋이 나오면 어떻게 해야 할까?

중간 커밋이 빌드조차 되지 않거나, 현재 추적 중인 문제와 무관한 이유로 테스트가 불가능할 수 있다. 이럴 때 공식 문서는 git bisect skip을 사용하라고 안내한다.

다만 문서에는 중요한 제한도 있다. 찾으려는 커밋 바로 옆 커밋을 skip하면, Git은 둘 중 정확히 어느 커밋이 첫 bad인지 단정하지 못할 수 있다. 여러 커밋을 건너뛰어야 한다면 git bisect skip v2.5..v2.6처럼 범위 지정도 가능하다.

git bisect run은 언제 유용할까?

각 단계의 판정을 스크립트로 자동화할 수 있다면 git bisect run이 가장 직접적이다. 공식 문서에 따르면 이 명령에 넘긴 스크립트는 현재 소스가 good/old이면 종료 코드 0, bad/new이면 1 이상 127 이하의 값으로 끝나야 하며, 125는 테스트 불가를 의미한다.

git bisect start HEAD v1.0.0 --
git bisect run sh -c "make test"

공식 예시는 빌드 실패 시 125를 반환해서 해당 커밋을 skip 처리하는 스크립트도 보여 준다. 테스트가 명확하고 반복 가능하다면 수동 판정보다 자동 bisect가 훨씬 일관된 결과를 낸다.

판정 속도를 줄이는 방법은 무엇일까?

문서에는 git bisect start에 추가 정보를 더 주면 탐색 범위를 더 줄일 수 있다고 나온다. 대표적인 방법은 pathspec을 함께 넘겨 특정 디렉터리나 파일 집합으로 범위를 제한하는 것이다.

예를 들어 문제가 특정 서브시스템에만 있다고 강하게 의심된다면 관련 경로만 대상으로 시작할 수 있다. 또 known good 커밋을 하나만 주는 대신 여러 개를 넘기면 Git이 처음부터 후보 범위를 더 좁게 잡을 수 있다.

--first-parent는 언제 고려해야 할까?

공식 문서는 --first-parent가 merge commit을 만났을 때 첫 번째 부모만 따라가도록 만든다고 설명한다. 이 옵션은 병합된 브랜치 안쪽의 깨진 커밋 때문에 오탐이 생기는 상황을 줄이는 데 유용하다.

문서 설명대로라면 회귀가 merge를 통해 들어왔을 때, merge commit 자체가 문제 도입 지점으로 식별되고 병합 브랜치의 조상은 무시된다. 따라서 "어느 merge가 메인 라인에 문제를 들여왔는지"를 찾는 작업이라면 기본 bisect보다 더 실무적인 선택이 될 수 있다.

--no-checkout은 어떤 경우에 맞을까?

--no-checkout은 각 단계에서 working tree를 실제로 체크아웃하지 않고, 대신 BISECT_HEAD 참조만 갱신하게 한다. 공식 문서는 체크아웃된 트리가 필요 없는 검사라면 이 옵션이 유용할 수 있다고 설명한다.

예를 들어 객체 그래프 무결성처럼 워킹 디렉터리를 만들지 않아도 되는 검사를 자동화할 때가 해당한다. 일반적인 애플리케이션 빌드나 테스트처럼 파일 체크아웃이 필요한 경우에는 기본 동작이 더 자연스럽다.

FAQ

Q. 현재 커밋이 꼭 bad여야 하나?

그럴 필요는 없다. 중요한 것은 bad 상태와 good 상태를 구분할 수 있는 양 끝점을 잡는 것이다. 공식 문서도 git bisect start <bad> <good> 형태와, start 후 별도로 bad와 good을 지정하는 형태를 모두 보여 준다.

Q. 버그가 아니라 특정 기능이 처음 들어온 커밋도 찾을 수 있나?

가능하다. 공식 문서는 이런 일반화된 사용을 위해 old/new 용어와 사용자 정의 용어를 지원한다고 설명한다. 즉 "고장"이 아니라 "속성 변화"를 찾는 도구로도 쓸 수 있다.

Q. bisect 중 다른 커밋을 잠깐 봤다가 다시 돌아올 수 있나?

가능하다. 공식 문서에는 자동으로 다음 단계를 진행하지 못한 뒤 이어서 계속해야 할 경우 git bisect next를 사용할 수 있다고 나온다. 다만 작업이 끝나면 결국 git bisect reset으로 상태를 정리하는 편이 안전하다.

정리

git bisect는 재현 가능한 good/bad 기준만 있다면 회귀 원인을 가장 체계적으로 좁히는 Git 기본 도구다. 기본 흐름은 start, good/bad, 필요 시 skip 또는 run, 종료 후 reset으로 이해하면 충분하다.

대부분의 팀에서는 먼저 수동으로 재현 조건을 안정화한 뒤, 가능하면 git bisect run으로 자동화하는 편이 효율적이다. merge 단위 원인 추적이라면 --first-parent, 체크아웃이 필요 없는 검사라면 --no-checkout을 함께 고려하면 된다.

참고 자료

반응형

'프로그래밍 > Git, IDE, 툴 관련' 카테고리의 다른 글

Git switch 사용법  (0) 2026.07.03
Git stash 사용법  (1) 2026.06.30
Git restore 사용법  (0) 2026.06.26
Git clean 사용법  (0) 2026.06.18
Git fetch.prune 사용법  (0) 2026.06.14
페이스북으로 공유카카오톡으로 공유카카오스토리로 공유트위터로 공유URL 복사