git bisect で問題箇所を特定する

  • 376
    いいね
  • 2
    コメント
この記事は最終更新日から1年以上が経過しています。

以前は問題なく動いていたはずの機能が、最新版では動かなくなっている・・・。こんなときは、「どのコミットが問題を混入させてしまったのだろうか?」を知りたくなるでしょう。

これを手助けするのが git bisect コマンドです。git bisect コマンドは、二分探索によって問題箇所を特定します。

事前準備

最初に大事なことがひとつあります。それは、「問題がない(good)状態と問題がある(bad)状態を、確実に判定できるようにする」ことです。

当然のことではありますが、ここがあやふやだと、二分探索をしても問題箇所をうまく特定できません。

可能なら、「テストスクリプトを1つ実行するだけで判定」できるようにしたほうが良いです。このとき、テストスクリプトは、git リポジトリからチェックアウトした作業ツリーに対して実行できるようにします(例えばソースからのビルド処理もテストスクリプトに含めます)。また、テストスクリプトは、good なら 0 を、bad なら 1~127(ただし 125 は除く)を返すようにします。

テストスクリプトが用意できない場合は、手動でテストを行うこともできます。

git bisect の実行方法

good と bad の指定

まず、問題がない(good)時点と問題がある(bad)時点を指定します。

$ git bisect start <bad-commit> <good-commit>

たとえば、V1.0 タグの時点では good で、最新(HEAD)では bad である、とすると次のように指定します。

$ git bisect start HEAD V1.0

これを実行すると、bad と good の間にある適当な中間バージョンがチェックアウトされます。

テストスクリプトの指定

次に、テストスクリプトを指定します(テストスクリプトが用意できない場合は、次の「手動でテストする」に進んでください)。

$ git bisect run <テストスクリプトのファイル名>

これを実行すると、git が自動的に「テスト実行」と「中間バージョンのチェックアウト」を繰り返して、問題が混入した時点を見つけてくれます。処理が終わるまで特にすることはありませんので、コーヒーでも飲んで心を落ち着けながら待ちましょう。

無事終了すれば、問題が混入した時点のバージョンがチェックアウトされています。コミット内容を調べて問題を解決しましょう。

手動でテストする

テストスクリプトが用意できない場合、手動でテストを行います。

テストの結果、問題がない(good)なら以下を実行します。

$ git bisect good

テストの結果、問題がある(bad)なら以下を実行します。

$ git bisect bad

上記のどちらかを実行すると、git が自動的に bad と good の間にある中間バージョンをチェックアウトしてくれます。これに対して、ふたたび手動でテストを行います。

手動の「テスト実行」と git による「中間バージョンのチェックアウト」を繰り返すと、問題が混入した時点が特定できます。コミット内容を調べて問題を解決しましょう。

その他のコマンド

現在チェックアウトしているコミットを確認する

git bisect がチェックアウトしているコミットを見るには、次のコマンドが便利です。

$ git bisect view

デフォルトだと gitk で表示します。オプション -p をつけると、パッチ形式でコンソールに出力します。

二分探索の過程を確認する

git bisect のログを表示します。

$ git bisect log

もとの状態に戻す

git bisect を実行する前の状態に戻すには、以下を実行します。

$ git bisect reset

まとめ

git bisect を使う機会はそんなに多くはないと思いますが、こういうものがあるということを覚えておくと、いざというときに助かります。実際に使ってみると、きっと感動しますよ。