使用git bisect快速定位問題

weixin_33860722發表於2017-10-01

bisect的原理

我想大部分程式設計師都碰到過這樣一件尷尬的事情,版本某天突然出現了一個莫名其妙的Bug,但是難以定位問題出在哪裡。

在這樣情況下,通常的做法是找到N天前的某個確定沒有該Bug的版本,然後通過對比版本,來找到是哪一筆提交引發了這個問題,最後以這筆提交中的修改為線索來分析和解決問題。

這種方法存在一個問題,如果含有Bug的版本和正確的版本之前的有很多筆提交(如下圖所示),那麼每筆提交挨個確認會是一件很痛苦的事情。

92541-b849b98952e02354.png

熟悉演算法的人應該很快就想到了,這種情況我們應該使用二分查詢,git的開發者也想到了這一點,因此它提供了 bisect 命令來幫助我們快速進行版本比較。

bisect的工作過程

bisect的主要思路是,首先啟動一個查詢,並讓使用者標記最早的不帶bug的提交點(以下簡稱Good)和含有bug的提交點(以下簡稱Bad),這兩點中間即使待查詢的提交段,如下圖中紅色部分所示:

92541-7398b23a9b145c1d.png

接下來,git會自動找到待查段正中間的提交點。

92541-a3aed7405f7b61bd.png

此時,我們針對這個提交點對應的版本進行測試,並根據測試結果,將這個提交標記為Good或者Bad。

92541-9e9ae9274609b8e7.png

標記完成後,我們就得到了新的待查詢的段,git會自動找到新的待查段正中間的提交點,接下來我們繼續對新的提交點進行驗證,並標記。重複上面的過程,最終就能找到導致問題的那筆提交。

bisect的命令

使用bisect進行問題查詢主要依賴於下面的三個命令:

  1. git bisect start
    這個命令用來來啟動一個查詢,start後面可以加上good和bad的提交點,命令如下:
    git bisect start [rev bad] [rev good]
    如果不加good和bad的提交點,那麼git將會等到我們使用good和bad命令指定對應的提交點後開始進行查詢
  2. git bisect good
    用來標記一個提交點是正確的,後面可以加上rev來指定某個特定的提交點,如果不加,則預設標記當前的提交點。
  3. git bisect bad
    用來標記一個提交點是包含問題的,如果bad後可以加上rev來指定某個特定的提交點,如果不加,則預設標記當前的提交點。

使用bisect的流程如下

  1. git bisect start 啟動一個檢查。
  2. 重複使用 git bisect good/bad 來標記git提供的提交點測試結果(正確/錯誤)直到找到出問題的提交點。
    PS: 如果中途要退出本次查詢,使用git bisect reset 退回到git bisect start執行前的狀態。

bisect還有其他一些有用的命令

  • git bisect skip
    跳過某一個待檢查的提交點。有時因為種種原因(例如:該提交點無法單獨執行或者我們確認該點沒有問題等)我們需要跳過某些提交點,通過這個命令既可以達到這個目的。
  • git bisect reset
    退出當前的檢查,切換會git bisect start之前的分支
  • git bisect visualsize
    啟動gitk,檢視當前的bisect狀態
  • git bisect run <cmd>
    通過執行一個指令碼來自動測試每個提交點,代替手工測試。指令碼的返回值定義如下
    • 0:Good
    • 125:Skip
    • 1~125,126,127:Failed

相關文章