git 디버깅 하기 (blame, bisect)
Git에는 버전 관리 기능 말고도 디버깅용 명령어도 있습니다. 누가 버그를 만들었는지 언제 어디서 생겼는지 찾아내는 데 도움이 됩니다.
git brame
git blame
은 파일의 각 라인을 누가 마지막으로 수정했는지 보여줍니다.
$ git blame <file>
-L
옵션을 사용하여 전체 파일이 아닌 원하는 라인 범위를 정할 수 있습니다.
$ git blame -L 3,10 main.go
^608a065 (yoongrammer 2020-11-21 12:02:45 +0900 3) import "fmt"
^608a065 (yoongrammer 2020-11-21 12:02:45 +0900 4)
af64134b (Tom 2020-11-21 12:06:08 +0900 5) func displayHello(str string) {
af64134b (Tom 2020-11-21 12:06:08 +0900 6) fmt.Println("Hello ", str)
af64134b (Tom 2020-11-21 12:06:08 +0900 7) }
af64134b (Tom 2020-11-21 12:06:08 +0900 8)
^608a065 (yoongrammer 2020-11-21 12:02:45 +0900 9) func main() {
af64134b (Tom 2020-11-21 12:06:08 +0900 10) displayHello("yoongrammer")
main.go 파일을 3라인에서 9라인까지 blame 명령으로 출력한 결과입니다.
첫 번째 항목은 그 라인을 마지막으로 수정한 커밋 SHA-1 값이고 두 번째 항목은 누가, 언제 그 라인을 커밋했는지 보여줍니다. 그 뒤에는 파일 라인 번호와 내용을 보여줍니다.
^608a065
값에 ^
표시는 해당 라인에서 처음 커밋이 후 변경된 적이 없다는 의미입니다.
git bisect
git bisect
은 이진 탐색 알고리즘을 사용해서 버그나 문제가 생긴 커밋을 찾아줍니다.
사용 예를 보면서 사용방법을 익혀보도록 하겠습니다.
출력이 원하는 결과가 아니라서 문제 커밋이 어느 것인지 git bisect
을 사용하여 찾아보도록 하겠습니다.
커밋 로그를 확인하면 아래와 같습니다.
$ git log --pretty=oneline
0c768c06620532bfd9f1ba97a10b4b111d1d3e6d (HEAD -> master) add START msg
d743d6b5b047306b275311eefa15b3aa8380fb31 add END msg
53811253a9e5fb06db281b4f7fb5f0c8af439008 change fmt.Println -> fmt.Print
af64134b1459da2810d56414c4b981146d212a99 add displayHello func
608a0655a6c8f0a5cccb2aa678414d8ff8673357 (tag: v1.0) add main.go
tag v1.0
커밋은 문제가 없다고 가정하겠습니다.
1. git bisect start
명령으로 이진 탐색을 시작합니다.
$ git bisect start
2. git bisect bad
명령으로 현재 커밋 부분에 문제가 있다고 표시를 합니다.
$ git bisect bad
현재 커밋 위치에 bad
브랜치가 생긴 것을 확인할 수 있습니다.
$ git log --pretty=oneline
0c768c06620532bfd9f1ba97a10b4b111d1d3e6d (HEAD -> master, refs/bisect/bad) add START msg
d743d6b5b047306b275311eefa15b3aa8380fb31 add END msg
53811253a9e5fb06db281b4f7fb5f0c8af439008 change fmt.Println -> fmt.Print
af64134b1459da2810d56414c4b981146d212a99 add displayHello func
608a0655a6c8f0a5cccb2aa678414d8ff8673357 (tag: v1.0) add main.go
3. v1.0 tag
에는 문제가 없기 때문에 git bisect good <커밋 해시값>
명령으로 문제가 없다고 표시합니다.
(커밋 해시값으로 tag 값(v1.0
)을 사용했지만 해시값(608a0
)을 사용해도 됩니다.)
$ git bisect good v1.0
Bisecting: 1 revision left to test after this (roughly 1 step)
[53811253a9e5fb06db281b4f7fb5f0c8af439008] change fmt.Println -> fmt.Print
bad(0c768)
와 good(608a0)
사이에 커밋은 전부 3개(d743d
, 53811
, af641
)이고 git은 이진 검색으로 인해 그 중간 커밋(53811
)으로 checkout 해줍니다.
$ git log --pretty=oneline
53811253a9e5fb06db281b4f7fb5f0c8af439008 (HEAD) change fmt.Println -> fmt.Print
af64134b1459da2810d56414c4b981146d212a99 add displayHello func
608a0655a6c8f0a5cccb2aa678414d8ff8673357 (tag: v1.0, refs/bisect/good-608a0655a6c8f0a5cccb2aa678414d8ff8673357) add main.go
HEAD
에 위치가 53811
커밋으로 checkout 된 것을 확인할 수 있습니다.
현재 커밋에서 테스트를 해보고 문제가 없다면 git bisect good
문제가 있다면 git bisect bad
를 반복하여 HEAD
위치를 이동시켜 점점 범위를 줄여가며 문제 커밋을 찾으면 됩니다.
4. 현재 커밋에서 문제가 있었기 때문에 bad
로 표시해줍니다.
$ git bisect bad
Bisecting: 0 revisions left to test after this (roughly 0 steps)
[af64134b1459da2810d56414c4b981146d212a99] add displayHello func
bad(53811) 위치와
good(608a0)
위치 사이는 af641
이기 때문에 HEAD
위치가 af641
커밋으로 checkout 된 것을 확인할 수 있습니다.
$ git log --pretty=oneline
af64134b1459da2810d56414c4b981146d212a99 (HEAD) add displayHello func
608a0655a6c8f0a5cccb2aa678414d8ff8673357 (tag: v1.0, refs/bisect/good-608a0655a6c8f0a5cccb2aa678414d8ff8673357) add main.go
5. 테스트 결과 현재 커밋에서는 문제가 없기 때문에 good
으로 표시해 줍니다.
$ git bisect good
53811253a9e5fb06db281b4f7fb5f0c8af439008 is the first bad commit
commit 53811253a9e5fb06db281b4f7fb5f0c8af439008
Author: Tom <Tom@example.com>
Date: Sat Nov 21 12:20:29 2020 +0900
change fmt.Println -> fmt.Print
:100644 100644 db5bd75d635df2df4365c30bf672845a0f607e04 90c7cc25506487629f246c711b1c6dc4151e00b9 M main.go
문제 커밋(53811
)을 찾으면 위와 같이 출력이 됩니다.
6. 문제 커밋을 찾았으니까 git bisect reset
명령을 실행시켜서 이진 탐색을 시작하기 전으로 HEAD를 돌려놓습니다.
$ git bisect reset
Previous HEAD position was af64134 add displayHello func
Switched to branch 'master'
$ git log --pretty=oneline
0c768c06620532bfd9f1ba97a10b4b111d1d3e6d (HEAD -> master) add START msg
d743d6b5b047306b275311eefa15b3aa8380fb31 add END msg
53811253a9e5fb06db281b4f7fb5f0c8af439008 change fmt.Println -> fmt.Print
af64134b1459da2810d56414c4b981146d212a99 add displayHello func
608a0655a6c8f0a5cccb2aa678414d8ff8673357 (tag: v1.0) add main.go
git bisect
명령을 사용하면 쉽게 문제가 발생한 커밋을 찾을 수 있습니다.
요약하면 아래와 같습니다.
1. git bisect start
로 이진탐색을 시작합니다.
2. git bisect good
, git bisect bad
를 반복하여 문제 커밋을 찾을 때까지 반복합니다.
3. 문제 커밋을 찾았다면 git bisect reset
을 합니다.