kmsheng
7 min readMar 31, 2019

如何使用 git bisect 快速找出有 bug 的 commit ?

在知道 git bisect 的用法之前如果要找出有 bug 的 commit,往往是 checkout 回之前的 commit,測試程式碼,再 checkout 到更早之前的 commit,測試程式碼,一直試到這個 commit 沒問題,才知道程式是在下一個 commit 開始壞掉的,這樣的找法實在很沒效率。

git 提供你一個更快速的方法,使用 git bisect 做二分搜尋法來找出有問題的 bug commit。你必須先告訴 git 一個已知是壞掉的 commit 當作是開頭,然後一個已知是正常的 commit 當作是結尾。 git bisect 會用這個範圍做二分搜尋法不斷地問你這個 commit 是好的還是壞的,一直問到找出有 bug 的 commit 為止。

以下指令將會使用 https://github.com/kmsheng/git-bisect-demo 這個 repo 說明,有興趣操作的讀者可以自行 clone 下來。有 bug 的 commit 是 02acafd feat: This is the commit that breaks add function,從這個 commit 開始 add 方法會丟出 error 不能使用。

把 check.js 複製到 git-bisect-demo repo 底下就可以檢查 add.js 有沒有爛掉了。

使用的方法大概是這樣,先執行 git bisect start 進入 bisect 模式,這時候再下 git status 可以發現已經進入 bisect 模式了,執行 git bisect reset可以取消退出。

$ git bisect start
$ git status
On branch master
Your branch is up to date with 'origin/master'.
You are currently bisecting, started from branch 'master'.
(use "git bisect reset" to get back to the original branch)
nothing to commit, working tree clean

Ok,我的 HEAD 現在是在 d6b143d add file multply.js,是爛的,所以我執行 git bisect bad 告訴 git 我當前的 commit 是爛的,請當做是執行 bisect 的開頭。( git bisect bad 後面沒有分支名稱或 hash,就表示使用當前所在的 commit )

然後我確定 commit fa38f8d add file add.js 是好的,所以可以當作 bisect 搜尋的結尾。執行 git bisect good fa38f8d

$ git bisect good e6910a1513e673e70deee47526793307f46e02abBisecting: 4 revisions left to test after this (roughly 2 steps)
[c56f1ef0689081bf621e69e74fcc1bb0e53668e4] docs: add comments for function add params

然後繼續執行 git bisect goodgit bisect bad 直到找出錯的 commit 為止 ( 畫面會出現 {hash} is the first bad commit )

$ git bisect good
02acafda466e88fa95a04b7a712b1d50869d9f59 is the first bad commit
commit 02acafda466e88fa95a04b7a712b1d50869d9f59
Author: kmsheng <kmsh3ng@gmail.com>
Date: Sun Mar 31 18:56:16 2019 +0800
feat: This is the commit that breaks add function.:100644 100644 047e14165724dba2831d6b68d8dacaf2e43d5e20 6ef896f4d49969a37f90d735b2ac8b035af479c1 M add.js

git 在 bisect 模式可以允許你跳過不需要檢查的 commit,例如我有很多 commit 是排版或是改文件的,可以執行 git bisect skip {hash} 來跳過這些 commit。

有的時候我們不是要檢查程式是否有 bug,而是程式的行為是否有改變,這個時候用 good 或 bad 來形容就怪怪的,所以 git 也允許你使用 old 與 new。

例如 git bisect oldgit bisect new,或者,你也可以定義自己想要的關鍵字。

git bisect start --term-old fast --term-new slow

定義完忘記,還可以執行 git bisect terms 來看看目前定義的關鍵字是什麼

$ git bisect terms
Your current terms are fast for the old state
and slow for the new state.

git bisect 支援印出 log,使用的指令是 git bisect log

例如:

$ git bisect log
git bisect start
# bad: [41d0e0c26061f24b085cba44372d770fe47efd9e] docs: add references to README.md
git bisect bad 41d0e0c26061f24b085cba44372d770fe47efd9e
# good: [e6910a1513e673e70deee47526793307f46e02ab] add file add.js
git bisect good e6910a1513e673e70deee47526793307f46e02ab

可以把存到一個檔案,再利用 git bisect replay 重新回到修改後的 bisect 狀態。如果之前有選錯 good 或 bad,也可以修改 log 上面的 good 或 bad 修正。

$ git bisect log > bisect.log

透過 git bisect replay 指令還原 bisect 的狀態:

$ git bisect replay bisect.log
Previous HEAD position was 0c2623b docs: add comments for function add
Switched to branch 'master'
Your branch is up to date with 'origin/master'.
Bisecting: 4 revisions left to test after this (roughly 2 steps)
[0c2623b6ac03eb34a74825dad4399e296f030691] docs: add comments for function add

除了可以手動執行 node check.js 檢查之外,也可以使用 git bisect run 搭配程式路徑自動檢查 commit 是不是好的。

Exit code 為 0 時視為程式正常、125 時執行 git bisect skip、1 ~ 127 視為程式爛掉。

$ git bisect start
$ git bisect bad d6b143d
$ git bisect good e6910a1
$ git bisect run bash -c 'node ./check.js'

References:

https://git-scm.com/docs/git-bisect

Sign up to discover human stories that deepen your understanding of the world.

Free

Distraction-free reading. No ads.

Organize your knowledge with lists and highlights.

Tell your story. Find your audience.

Membership

Read member-only stories

Support writers you read most

Earn money for your writing

Listen to audio narrations

Read offline with the Medium app

No responses yet

Write a response