はんなりと、ゆるやかに

アジャイル、スクラムが好きが日々から学んだことをアウトプット

バグの混入コミットを発見するGitコマンド:bisect

開発をしているといつの間にかバグが混入することがありますよね。混入タイミングが分からない場合はとりあえず正しく動く時期のコミットを見つけて、バグが発生するまで地道に調べていくと思います。

そんなときに使えるコマンドが git bisect です。
git bisect はコミットログからバグが発生したコミットを見つける手助けをしてくれます。
git-scm.com

今回の検証に使ったgit version は 2.26.2 です。

サンプルコード

検証用にバグが混入しているリポジトリを用意しました。最新のコミットはテストコードが通りません。
github.com

基本的な使い方

バグが混入しているコミット正しく動いていたコミット間から混入したコミットを見つけます。正しく動いていたコミットは確実に動いていた時期のコミットを指定します(1週間前は確実に動いていたのになーって感じならその時期のコミットを指定します)。この2つのコミット間を二分探索で絞り込みながら見つけていきます。

1.調査開始

git bisect start コマンドを使って調査を開始します。開始時にバグが混入しているコミット正しく動いていたコミットを指定します。

以下のコマンドではgit bisect badで最新のコミットにバグが混入していることを指定し、git bisect good HEAD~8 で8個前のコミットでは確実に動いていたことを指定しています。

git bisect start
git bisect bad
git bisect good HEAD~8

また、以下のように書いても同じ意味です。

git bisect start HEAD HEAD~8

2.調査

「1.調査を開始する」を実行した後のworking treeは二分探索で絞り込まれたコミットの環境になっています。この環境で動作確認をして正しく動作すればgit bisect good、正しく動作しなければgit bisect badを入力します。入力後のworking treeは二分探索で絞り込まれた新たなコミットの環境になっています。

これを繰り返すと<コミットID> is the first bad commitのメッセージが出て初めてバグが混入したコミットを見つけられます。

3.調査完了

git bisect resetgit bisect start前のコミットに戻れます。

テストコードがあれば自動探索できる

バグかどうかを発見できるテストコードなどがあれば、git bisect run コマンドで自動探索できます。
*1

たとえば以下のようにgit bisect run コマンドの引数でdotnetのテストを実行すると自動で判断しながら特定のコミットを発見してれます。

git bisect start HEAD HEAD~8
git bisect run "C:\Program Files\dotnet\dotnet.exe" test

TortoiseGitでbisect

TortoiseGitでもgit bisectが使えます。基本はCUIと同じで、操作がGUIになるだけです。

1.調査開始

右クリックのメニューからBisect startを選択します。
f:id:iucstscui:20200506114031p:plain

バグが混入しているコミット正しく動いていたコミットを選択します
goodは「...」から正しく動いていた頃のログを選択します。
f:id:iucstscui:20200506114630p:plain

2.調査

working treeは二分探索で絞り込まれたコミットの環境になっているので動作確認をしてBisect goodBisect badを選択していきます。
f:id:iucstscui:20200506114753p:plain

これを繰り返すと<コミットID> is the first bad commitのメッセージが出て初めてバグが混入したコミットを見つけられます。

3.調査完了

Bisect resetBisect start前のコミットに戻れます。
f:id:iucstscui:20200506220251p:plain

まとめ

二分探索でバグが混入したコミットを見つけてくれるgit bisectコマンドを調べました。どのタイミングで混入したか分からないバグを探すときには便利なコマンドです。

*1:そもそも、テストコードがあればbisectコマンドが必要になる前にバグ混入に気づけると思いますが