잘 돌아가던 서비스에 갑자기 치명적인 버그가 발생했습니다. 수만 줄의 코드 중에서 어느 파일의 어느 줄 때문에 문제가 생겼는지, 그리고 도대체 언제, 누가 이 코드를 작성했는지 알아내야만 신속하게 장애를 해결할 수 있습니다. Git은 코드가 엉망이 되었을 때 탐정처럼 단서를 찾아주는 훌륭한 디버깅 전용 명령어들을 내장하고 있습니다.
이번 포스팅에서는 특정 코드 라인의 작성자와 커밋을 찾아내는 git blame과, 방대한 커밋 히스토리 속에서 이진 탐색(Binary Search) 알고리즘을 활용해 버그가 처음 발생한 지점을 기가 막히게 찾아내는 git bisect의 활용법을 완벽히 마스터해 보겠습니다.

1. 코드 라인별 책임자 추적: git blame
특정 파일의 코드를 열어보았을 때, 도대체 이 기괴한 로직을 누가 언제 작성했는지 궁금하다면 git blame 명령어를 사용합니다. Blame은 '비난하다, 책임을 묻다'라는 뜻을 가지고 있지만, 실제로는 버그를 만든 사람을 비난하기 위함이 아니라 해당 코드를 작성한 의도를 가장 잘 아는 사람에게 질문하기 위해 사용됩니다.
# 특정 파일(index.html)의 라인별 커밋 기록 조회
$ git blame index.html
^ca82a6d (Hong Gil Dong 2023-10-02 14:23:01 +0900 1) <!DOCTYPE html>
^ca82a6d (Hong Gil Dong 2023-10-02 14:23:01 +0900 2) <html>
b2a1f0e2 (Kim Chul Soo 2023-10-05 10:11:35 +0900 3) <head>
b2a1f0e2 (Kim Chul Soo 2023-10-05 10:11:35 +0900 4) <title>로그인 페이지</title>
...
명령어를 실행하면 파일의 각 줄(Line) 맨 앞에 해당 줄을 가장 마지막으로 수정한 커밋의 해시값, 작성자의 이름, 수정된 날짜 및 시간이 차례대로 출력됩니다. 이를 통해 문제의 코드가 언제 병합되었는지 파악하고, 해당 커밋 해시(b2a1f0e2)를 git show 명령어로 조회하여 전체적인 수정 의도(커밋 메시지)를 파악할 수 있습니다.
특정 라인 범위만 조회하기
수천 줄이 넘는 파일 전체를 조회하는 것은 비효율적이므로, -L 옵션을 사용하여 확인하고 싶은 특정 라인의 범위를 지정할 수 있습니다.
# index.html 파일의 10번째 줄부터 20번째 줄까지만 Blame 정보 조회
$ git blame -L 10,20 index.html
2. 이진 탐색으로 버그의 시작점 찾기: git bisect
버그가 발생했다는 사실은 알겠는데, 최근 한 달 동안 수백 개의 커밋이 쌓여서 도대체 어떤 커밋부터 이 버그가 시작되었는지 알 수 없는 캄캄한 상황이 있습니다. 이때 git bisect를 사용하면 전체 커밋을 반씩 쪼개어가며 탐색하는 이진 탐색(Binary Search) 방식으로 버그를 유발한 최초의 커밋을 단숨에 찾아냅니다.
git bisect 사용 프로세스
Bisect를 시작하려면 버그가 존재하는 '현재의 나쁜 상태(bad)'와 버그가 없었던 '과거의 좋은 상태(good)' 커밋 해시값 두 개를 먼저 Git에게 알려주어야 합니다.
# 1. Bisect 이진 탐색 모드 시작
$ git bisect start
# 2. 현재 상태(HEAD)는 버그가 있으므로 'bad'로 지정
$ git bisect bad
# 3. 한 달 전(예: 해시값 1a2b3c4)에는 버그가 없었으므로 'good'으로 지정
$ git bisect good 1a2b3c4
Bisecting: 50 revisions left to test after this (roughly 6 steps)
[8d7e6f5] 로그인 로직 리팩토링
위와 같이 범위를 지정해주면, Git은 good과 bad 커밋의 정확히 중간 지점에 있는 커밋(8d7e6f5)으로 브랜치를 자동 전환(Checkout)시킵니다. 이제 개발자는 이 상태에서 프로그램을 직접 실행해 보거나 테스트 코드를 돌려 버그가 존재하는지 확인하기만 하면 됩니다.
# 4-1. 테스트 결과, 여전히 버그가 존재한다면 이 커밋도 'bad'
$ git bisect bad
Bisecting: 25 revisions left to test after this (roughly 5 steps)
# 4-2. 테스트 결과, 버그가 발생하지 않고 정상이라면 이 커밋은 'good'
$ git bisect good
Bisecting: 12 revisions left to test after this (roughly 4 steps)
이렇게 bad와 good을 판별해 주면, Git은 남은 절반의 커밋들 중 다시 중간 지점으로 이동합니다. 이 과정을 몇 번 반복하면, 수백 개의 커밋도 단 7~8번의 확인만으로 최초의 원인 커밋을 족집게처럼 찾아낼 수 있습니다.
# 5. 최초 원인 커밋 발견!
a9b8c7d is the first bad commit
commit a9b8c7d
Author: Hong Gil Dong <hong@example.com>
Date: Mon Oct 10 11:22:33 2023 +0900
feat: 새로운 장바구니 할인 로직 추가
# 6. 원인을 찾았으므로 Bisect 모드를 종료하고 원래 브랜치(master)로 복귀
$ git bisect reset
1. 전통적이고 체계적인 전략: Git Flow
Git Flow는 2010년 Vincent Driessen이 제안한 모델로, 규모가 크고 배포 주기가 명확히 정해져 있는 정통 소프트웨어 개발(예: 패키지 소프트웨어, 버전별 정기 배포 서비스)에 매우 적합한 전략입니다. 총 5가지 종류의 브랜치를 엄격하게 나누어 운영합니다.
Git Flow의 5가지 브랜치
- master (main): 제품으로 배포되는 가장 안정적인 코드가 있는 메인 브랜치입니다. 이곳에 직접 코드를 작성하는 일은 없으며, 배포 시 버전을 나타내는 Tag가 부착됩니다.
- develop: 다음 버전을 배포하기 위해 개발 내역들이 모이는 중심 브랜치입니다. 모든 새로운 기능들은 이 브랜치로 병합됩니다.
- feature: 새로운 기능 개발이나 버그 수정을 위해
develop브랜치에서 파생되는 브랜치입니다. 작업이 완료되면 다시develop으로 병합됩니다. (보통feature/login형태로 이름 짓습니다) - release:
develop브랜치에 이번 버전에 포함될 기능들이 다 모이면 배포 준비를 위해 파생되는 브랜치입니다. 이곳에서는 새로운 기능을 추가하지 않고 오직 QA(품질 검사)와 버그 수정만 진행합니다. 검증이 끝나면master와develop양쪽으로 병합됩니다. - hotfix: 배포된
master브랜치에서 예상치 못한 치명적인 버그가 발생했을 때 급하게 수정하기 위해 파생되는 브랜치입니다. 수정 완료 후 즉시master와develop에 병합하여 서비스 장애를 해결합니다.
Git Flow는 규칙이 매우 촘촘하여 대규모 팀이 안정적으로 버전을 관리하기에는 최고지만, 지속적 배포(CI/CD) 환경에서는 과정이 너무 무겁고 복잡하여 오히려 개발 속도를 저하시키는 단점이 있습니다.
2. 가볍고 빠른 애자일 전략: GitHub Flow
GitHub Flow는 Git Flow의 복잡성을 걷어내고, 웹 서비스나 SaaS처럼 하루에도 몇 번씩 배포가 이루어지는 지속적 배포(CD) 환경에 맞게 단순화된 전략입니다. GitHub 측에서 제안한 모델로, 규칙이 단순하여 스타트업이나 애자일 조직에서 크게 사랑받고 있습니다.
GitHub Flow의 핵심 규칙
- master 브랜치는 항상 배포 가능한 상태여야 한다.:
master브랜치의 코드는 완벽하게 테스트가 끝난 상태여야 하며, 언제든지 프로덕션 서버에 올라가도 문제가 없어야 합니다. - 새로운 작업은 master에서 명시적인 브랜치를 따서 진행한다.: 기능 추가든 버그 수정이든 무조건
master에서 새로운 브랜치를 생성합니다. (예:user-profile-update) - 원격 저장소에 수시로 Push 한다.: 로컬에서만 작업하지 말고 작업 브랜치를 수시로 원격 서버에 동기화하여 다른 사람들과 피드백을 주고받습니다.
- 피드백이나 도움이 필요할 때, 그리고 병합할 준비가 완료되었을 때 Pull Request를 생성한다.: 코드를 메인에 합치기 전에 반드시 코드 리뷰 과정을 거칩니다.
- 리뷰를 통과하고 master에 병합되면 즉시 배포한다.: 별도의
release브랜치 없이 병합 직후 자동화된 파이프라인을 통해 서비스에 배포됩니다.
3. 우리 팀에 맞는 전략 선택하기
정답인 브랜치 전략은 없습니다. 스마트폰 앱이나 엔터프라이즈 솔루션처럼 한 달에 한 번씩 버전을 묶어서 신중하게 릴리즈해야 한다면 Git Flow를 선택하는 것이 안전합니다. 반대로 웹사이트나 쇼핑몰처럼 기능이 만들어지는 즉시 사용자에게 지속적으로 배포하고 빠르게 반응해야 한다면 GitHub Flow가 훨씬 효율적입니다.
최근에는 이 둘의 장점을 섞어, master와 develop, feature 브랜치 정도만 운영하는 커스텀 전략을 구성하여 사용하는 팀도 많아지는 추세입니다.
'CI.CD > GIT' 카테고리의 다른 글
| [GIT] 오픈소스 기여(Fork, PR)와 대규모 다중 저장소(Submodule), 생산성 향상 팁 (0) | 2026.08.07 |
|---|---|
| [GIT] 커밋 정밀 조작(Amend, Cherry-pick)과 최후의 복구 도구(Reflog) (0) | 2026.08.07 |
| [GIT] 깔끔한 히스토리를 위한 Rebase와 안전한 작업 되돌리기 (0) | 2026.08.07 |
| [GIT] Git 브랜치(Branch) 완벽 이해와 병합 충돌(Conflict) 해결 (0) | 2026.08.07 |
| [GIT] 커밋 히스토리 관리 및 원격 저장소(GitHub) 협업 (0) | 2026.08.07 |