日本語 ▾ Topics ▾ Latest version ▾ git-bisect last updated in 2.55.0

NAME

git-bisect - バイナリサーチでバグを導入したコミットを特定する

概要

git bisect start [--term-(bad|new)=<term-new> --term-(good|old)=<term-old>]
		   [--no-checkout] [--first-parent] [<bad> [<good>…​]] [--] [<pathspec>…​]
git bisect (bad|new|<term-new>) [<rev>]
git bisect (good|old|<term-old>) [<rev>…​]
git bisect terms [--term-(good|old) | --term-(bad|new)]
git bisect skip [(<rev>|<range>)…​]
git bisect next
git bisect reset [<commit>]
git bisect (visualize|view)
git bisect replay <logfile>
git bisect log
git bisect run <cmd> [<arg>…​]
git bisect help

説明

このコマンドはバイナリサーチ(2分探索)アルゴリズムを使って、プロジェクト履歴のどのコミットでバグが導入されたかを特定します。まず、バグが含まれていることが分かっている「bad」なコミットと、バグがまだ存在しないことが分かっている「good」なコミットを指定します。すると git bisect はその2点の間のコミットを選び、そのコミットが「good」か「bad」かを尋ねてきます。この範囲を絞り込む操作を繰り返し、最終的にバグを導入した正確なコミットを特定します。

実際には、git bisect はプロジェクトの 任意の 性質が変化したコミットを特定するためにも使えます。たとえば、バグを修正したコミットや、ベンチマークの性能が向上したコミットなどです。このような一般的な用途に対応するため、「good」「bad」の代わりに「old」「new」などの用語を使ったり、独自の用語を指定することもできます。詳細は後述の「用語のカスタマイズ」セクションを参照してください。

基本的なバイセクトコマンド: start, bad, good

例として、バージョン v2.6.13-rc2 で正常に動作していた機能が、どのコミットで壊れたかを調べたいとします。バイセクトセッションは次のように開始します:

$ git bisect start
$ git bisect bad                 # 現在のバージョンは不具合あり
$ git bisect good v2.6.13-rc2    # v2.6.13-rc2 は正常であることが分かっている

bad と good のコミットをそれぞれ1つ以上指定すると、git bisect はその範囲の中間にあるコミットを選択してチェックアウトし、次のようなメッセージを出力します:

バイセクト中: この後テストすべきリビジョンが675件残っています(おおよそ10ステップ)

この時点でチェックアウトされたバージョンをビルドしてテストします。もしそのバージョンが正常に動作する場合は、次のコマンドを入力します

$ git bisect good

もしそのバージョンに不具合がある場合は、次のコマンドを入力します

$ git bisect bad

すると git bisect は次のようなメッセージを表示します

バイセクト中: この後テストすべきリビジョンが337件残っています(おおよそ9ステップ)

この手順を繰り返します。ツリーをビルドしてテストし、正常なら git bisect good、不具合があれば git bisect bad を実行して、次にテストすべきコミットを指定します。

最終的に調査すべきリビジョンがなくなると、コマンドは最初に不具合が導入されたコミットの説明を表示します。このとき refs/bisect/bad 参照がそのコミットを指すようになります。

Bisect をリセット

bisect セッション終了後、bisection 状態をクリーンアップして元の HEAD に戻すには、次のコマンドを実行します:

$ git bisect reset

デフォルトでは、これにより git bisect start を実行する前にチェックアウトされていたコミットにツリーが戻ります。(新しく git bisect start を実行した場合も同様に、古い bisection 状態をクリーンアップします。)

オプションの引数を指定すると、代わりに別のコミットに戻ることができます:

$ git bisect reset <commit>

例えば、git bisect reset bisect/bad は最初のバッドリビジョンをチェックアウトし、git bisect reset HEAD は現在のバイセクションコミットに留まり、全くコミットを切り替えないことになります。

代替の用語

場合によっては、不具合を引き起こしたコミットではなく、ある「古い」状態と「新しい」状態の間で変更を引き起こしたコミットを探すことがあります。例えば、特定の修正が導入されたコミットを探している場合や、ソースコードのファイル名がすべて会社の命名規則に変換された最初のコミットを探している場合などです。あるいは他のどんな場合でも同様です。

このような場合、「変更前の状態」と「変更後の状態」を指すのに「good」と「bad」という用語を使うと非常に紛らわしくなることがあります。そこで代わりに、「good」と「bad」の代わりにそれぞれ「old」と「new」という用語を使用できます(ただし、一つのセッション内で「good」と「bad」を「old」と「new」と混在させることはできないことに注意してください。)

この、より一般的な使用方法では、ある特性を持つ「new」コミットと、その特性を持たない「old」コミットを git bisect に提供します。git bisect がコミットをチェックアウトするたびに、そのコミットがその特性を持っているかどうかをテストします。持っている場合は、そのコミットを「new」とマークし、そうでない場合は「old」とマークします。bisection が完了すると、git bisect はどのコミットがその特性を導入したかを報告します。

「good」と「bad」の代わりに「old」と「new」を使用するには、引数としてコミットを指定せずに git bisect start を実行し、その後、コミットを追加するために次のコマンドを実行する必要があります:

git bisect old [<rev>]

これは、コミットが探している変更の前にあったことを示します。あるいは、

git bisect new [<rev>...]

これは、コミットが探している変更の後にあったことを示します。

現在使用している用語を確認するには、次のコマンドを使用します

git bisect terms

古い状態を表す用語だけを確認するには git bisect terms --term-old または git bisect terms --term-good を使用します。git bisect terms --term-newgit bisect terms --term-bad は、探している変更よりも新しいコミットをどう呼ぶかを確認するために使用できます。

「bad」/「good」または「new」/「old」の代わりに独自の用語を使用したい場合は、次のように bisection を開始することで、任意の名前を選択できます(ただし、resetstart などの既存の bisect サブコマンドは除きます)

git bisect start --term-old <古い状態の用語> --term-new <新しい状態の用語>

例えば、パフォーマンス低下を引き起こしたコミットを探している場合は、次のように使用できます

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

あるいは、バグを修正したコミットを探している場合は、次のように使用できます

git bisect start --term-new fixed --term-old broken

そして、コミットをマークするには git bisect goodgit bisect bad の代わりに git bisect <古い状態の用語>git bisect <新しい状態の用語> を使用します。

Bisect の可視化/表示

bisection プロセス中に、現在残っている候補を gitk で確認するには、次のコマンドを実行します(サブコマンド viewvisualize の代わりに使用することもできます):

$ git bisect visualize

Git はさまざまな環境変数を通じてグラフィカル環境を検出します:Unix システムの X Window System 環境で設定される DISPLAY、Cygwin の対話的デスクトップセッションで設定される SESSIONNAME、Msys2 および Git for Windows で設定される MSYSTEM、macOS の対話的デスクトップセッションで設定される可能性がある SECURITYSESSIONID などです。

これらの環境変数が一つも設定されていない場合は、代わりに git log が使用されます。また、-p--stat などのコマンドラインオプションを指定することもできます。

$ git bisect visualize --stat

Bisect ログと bisect リプレイ

リビジョンを good または bad としてマークした後、次のコマンドを実行すると、これまでに何が行われたかを確認できます:

$ git bisect log

リビジョンのステータス指定に誤りがあったことに気付いた場合は、このコマンドの出力をファイルに保存し、そのファイルを編集して間違ったエントリを削除した後、次のコマンドを実行して修正された状態に戻ることができます:

$ git bisect reset
$ git bisect replay that-file

コミットのテストを回避する

bisect セッションの途中で、提案されたリビジョンがテストに適していないことがわかった場合(例えば、ビルドに失敗し、その失敗が追跡しているバグとは関係ないとわかっている場合)、手動で近くのコミットを選択して、代わりにそれをテストすることができます。

例えば:

$ git bisect good/bad			# 前のラウンドが good または bad だった
Bisecting: 337 revisions left to test after this (roughly 9 steps)
$ git bisect visualize			# おっと、これは興味深くない
$ git reset --hard HEAD~3		# 提案された内容の3つ前の
					# リビジョンを試す

その後、選択したリビジョンをコンパイルしてテストし、通常の方法でそのリビジョンを good または bad としてマークします。

Bisect スキップ