git bisect <subcommand> <options>
このコマンドは様々なサブコマンドと、それに関連した異なるオプションを取ります
git bisect help
git bisect start [<bad> [<good>...]] [--] [<paths>...]
git bisect bad [<rev>]
git bisect good [<rev>...]
git bisect skip [(<rev>|<range>)...]
git bisect reset [<commit>]
git bisect visualize
git bisect replay <logfile>
git bisect log
git bisect run <cmd>...
このコマンドは'git rev-list --bisect'を利用して、
与えられた過去の"正常な"コミットと、それより後に起きた"不正な"コミットを渡して
二分探索によりバグの発生した変更を探すのを手伝ってくれます。
ヘルプの使い方
"git bisect" は短い使い方の説明を得るのに使われ、
"git bisect help" または "git bisect -h" は長い使い方の説明を得るのに使われます。
基本的なbisectコマンド: start, bad, good
Linuxカーネルツリーを例にすると、
基本的なbisectコマンドの使い方は以下のようになります。
$ git bisect start
$ git bisect bad # 現在のバージョンは駄目
$ git bisect good v2.6.13-rc2 # タグ v2.6.13-rc2 は、テストが成功した
# 一番最後のバージョン
あなたがすくなくとも1つづつ失敗と成功のリビジョンを指定すると、
bisect コマンドはリビジョンツリーを分割し、下記のようなメッセージを出力します。
Bisecting: 675 revisions left to test after this
# 訳注:"分割中: テストするリビジョンは残り675件" という意味
メッセージ出力後、good と bad の中間に位置するリビジョンがチェックアウトされます。
そうしたら、ただちにカーネルをコンパイル、実行してみましょう。
もしカーネルが正しく動作したら、以下のコマンドを入力します。
$ git bisect good # これはOK
コマンドの出力は以下のようなものになるでしょう:
Bisecting: 337 revisions left to test after this
# 訳注:"分割中 : テストするリビジョンは残り337件" という意味
ツリーをコンパイル、テストし、成功か失敗に応じて、
"git bisect good" もしくは "git bisect bad" を発行し、
次の二分先を決定するというプロセスを繰り返します。
最終的に、これ以上リビジョンを分割出来ない状態になります。
そして、"refs/bisect/bad"には最初に悪い状態になったカーネルのリビジョンが残されているでしょう。
Bisect reset
bisectセッションの後に、二分された状態を元に戻し
最初のHEADに戻るためには、以下のコマンドを実行して下さい:
通常、これは`git bisect start`する前に取り出されていたコミット状態に
あなたのツリーを戻すでしょう。(また、新しい`git bisect start`した場合でも、
古い二分状態はクリーンアップされるでしょう.)
オプションの引数を指定する場合は、代わりに別のコミットに戻すことが出来ます。
$ git bisect reset <commit>
例を挙げると、git bisect reset HEAD は現在のbisectコミットを残したまま、
切り替えていったコミットを全て無効にします。
git bisect reset bisect/bad は最初にbadマークを付けたリビジョンをチェックアウトします。
Bisectの視覚化
'gitk'を使って現在の疑わしい候補の残りを見るには、
bisectを実行中に下のコマンドを実行して下さい。
view も`visualize`の同義語として使用することが出来ます。
もし'DISPLAY'環境変数が設定されていなければ、代わりに'git log'が使われます。
同様のことは -p や --stat をオプションとして与えることで出来ます。
Bisectのログとリプレイ
goodもしくはbadマークを付けた後、
何がどのように行われたかを見るには下記のコマンドを実行します:
もしあるリビジョンの状態指定に間違えを発見したら、このコマンドの出力をファイルに保存し、
間違えたエントリを削除して編集し、それから下記のコマンドを実行すると正しい状態へ戻ります。
$ git bisect reset
$ git bisect replay that-file
コミットテストを回避する
もしbisectの途中で、次に提案されたリビジョンがテストに良いものでないことが
分かっている場合(例えば、そのコミットの変更によりあなたの環境で動かなくなり、
それが追っているバグと関係がないということが分かっている時)、
その近くのコミットを見つけ代用したいとします。
例:
$ git bisect good/bad # 前回は good か bad
Bisecting: 337 revisions left to test after this
$ git bisect visualize # おっと、こいつはやりづらいな
$ git reset --hard HEAD~3 # 3つ前のバージョンで
# 試してみよう
それから指定されたリビジョンでコンパイルとテストを行い、
その後、いつも通りgoodまたはbadマークをリビジョンに設定します。
Bisect skip
近くのコミットを自分自身で選択する代わりに、このコマンドによってgitに頼むことが出来ます。
$ git bisect skip # このバージョンはテストすることが出来ない
しかし最初のbadコミットとの間に、badコミットや、
一つないしそれ以上のskipコミットがあると、
gitは結局の所、それは出来ないと伝えてくるかもしれません。
また、ある特定のコミット範囲をスキップすることが出来ます。
一つのコミットを指定する代わりに、"<commit1>..<commit2>"表記を使います。例:
$ git bisect skip v2.5..v2.6
これは、v2.5(含まない)からv2.6(含む)以外を
テストするようbisectプロセスに 伝えます。
もし最初のコミットもスキップする範囲に含めたい場合は、
下のコマンドを実行する必要があることに注意して下さい。
$ git bisect skip v2.5 v2.5..v2.6
これは、v2.5(含む)からv2.6(含む)をスキップするようbisectプロセスに 伝えます。
bisect start にたくさんのパラメータを与え、分割量を縮小する
もっとテストする回数を少なくすることが出来ます、
問題がツリー(訳注: ディレクトリツリーのこと) のどの部分で起きているかが分かっていれば、
bisect start コマンドを実行する際、ファイルパスをパラメータに渡すことが出来ます。
$ git bisect start -- arch/i386 include/asm-i386
もし事前に正しいコミットがもっと分かっていれば、分割領域を絞り込むことが出来ます。
bisect start コマンドを発行する際に指定するbadコミットの直後に、
全てのgoodコミットを指定するのです。
$ git bisect start v2.6.20-rc6 v2.6.20-rc4 v2.6.20-rc1 --
# v2.6.20-rc6 は正しくない
# v2.6.20-rc4 と v2.6.20-rc1 は正しい
Bisect run
もし、現在のソースコードが正しいか悪いかを教えてくれるスクリプトがあれば、
このコマンドを使ってbisectを実行することが出来ます。
$ git bisect run my_script arguments
スクリプト(上記の例ではmy_script)は
現在のソースコードが正しい場合は0を、
もし現在のソースコードが正しくない場合は、exitコードに125をのぞいた
1から127(含む)を終了コードとして返す必要があることに注意してください。
それ以外の終了コードの場合は、bisectプロセスが強制終了するでしょう。
プログラムが "exit(-1)"で終了した場合、"& 0377"でマスクされ、
$? == 255(訳注: $?はunix等でプログラムの終了コードが格納される環境変数のこと)
になることに注意して下さい。(exit(3)のmanページを見て下さい)
特殊な終了コード125は、現在のソースコードがテスト出来ない時に使用して下さい。
このコードを使用してスクリプトを終了すると、現在のリビジョンはスキップされます。
(上記の`git bisect skip`を見て下さい)
時折、分割テストをするリビジョンに一時的な変更を加えたくなるでしょう。
(例えば s/#define 0/#define 1/をヘッダーファイルに適用したり、
"リビジョンにコミットしない、今回のbisectにはあまり関係のない他の問題のためのパッチが必要です。")
このような状況に対処するためには、
'git bisect'の中で次のテストするべきリビジョンが見つかった後、
コンパイル、テストを行う前に、スクリプトがパッチを与えることが出来ます。
そして、最終的にそのリビジョン(場合によっては必要なパッチを決定して)
でテストをパスするか判断し、元の状態にツリーを戻します。
最後に、スクリプトは"git bisect run"コマンドループが今回の分割の結果を
判断させるための、実質的なテスト結果を終了時に渡します。