はじめに
「昨日まで動いていたのに、今日突然バグが発生した」「どのコミットでバグが混入したのかわからない」。このような状況は、チーム開発において頻繁に発生します。コミット履歴が数百件ある場合、1件ずつ確認するのは現実的ではありません。
git bisectは、二分探索(バイナリサーチ)アルゴリズムを使って、バグを引き起こしたコミットを効率的に特定するコマンドです。たとえば1000件のコミットがあっても、約10回のテストでバグの原因コミットを見つけられます。
本記事では、git bisectの仕組みから基本操作、自動テストとの連携まで実践的に解説します。この記事を読み終えると、以下のことができるようになります。
- git bisectの二分探索アルゴリズムを理解できる
git bisect start、git bisect good、git bisect bad、git bisect resetを使いこなせるgit bisect runで自動テストと連携してバグを自動特定できる- テスト不可能なコミットを
git bisect skipでスキップできる
実行環境と前提条件
本記事の内容は、以下の環境で動作確認を行っています。
| 項目 | 要件 |
|---|---|
| Git | 2.40以上 |
| OS | Windows 10/11、macOS 12以上、Ubuntu 22.04以上 |
| ターミナル | コマンドプロンプト、PowerShell、Terminal.app、bash等 |
| エディタ | VS Code推奨 |
前提条件として、以下の知識があることを想定しています。
- コマンドライン操作の基礎知識(
cd、ls/dir、mkdir等) - テキストエディタの基本操作
- Gitの基本コマンド(
git log、git checkout、git switch)の理解
git bisectの仕組み:二分探索アルゴリズム
git bisectは、二分探索(バイナリサーチ)アルゴリズムを使ってバグの原因コミットを特定します。この手法により、コミット数に対して対数的な回数(O(log n))でバグを発見できます。
二分探索の基本原理
二分探索は、ソートされたデータの中から目的の値を効率的に見つけるアルゴリズムです。git bisectでは、コミット履歴を「正常(good)」と「異常(bad)」の2つの状態に分け、その境界を見つけます。
|
|
bisectの探索ステップ数
git bisectが必要とするステップ数は、コミット数nに対して約log₂(n)回です。
| コミット数 | 最大ステップ数 |
|---|---|
| 10件 | 約4回 |
| 100件 | 約7回 |
| 1,000件 | 約10回 |
| 10,000件 | 約14回 |
たとえば1000件のコミットがあっても、最大10回程度のテストでバグの原因コミットを特定できます。
git bisectの基本操作:start/good/bad/reset
git bisectを使ったバグ特定の基本的な流れを解説します。
bisect startでセッションを開始する
まず、git bisect startでbisectセッションを開始します。
|
|
開始時に「bad」(バグがあるコミット)と「good」(バグがないコミット)を同時に指定することもできます。
|
|
bisect badで異常なコミットをマークする
現在のコミット(通常はHEAD)にバグがあることをgit bisect badで伝えます。
|
|
bisect goodで正常なコミットをマークする
バグが存在しない(正常に動作する)コミットをgit bisect goodで伝えます。
|
|
goodとbadの両方をマークすると、Gitは自動的に中間のコミットをチェックアウトします。
|
|
テスト結果に応じてgood/badをマークする
チェックアウトされたコミットでテストを実行し、結果に応じてマークします。
|
|
この操作を繰り返すと、最終的にバグを導入したコミットが特定されます。
|
|
bisect resetでセッションを終了する
バグの原因コミットを特定したら、git bisect resetでセッションを終了し、元のブランチに戻ります。
|
|
実践例:手動でバグの原因コミットを特定する
実際のバグ特定の流れを、具体的な例で解説します。
シナリオ:計算結果が正しくなくなった
ある計算機能が、最近のコミットで正しく動作しなくなったとします。1週間前のv1.2.0タグでは正常に動作していたことがわかっています。
ステップ1:bisectセッションを開始する
|
|
ステップ2:bad/goodコミットをマークする
|
|
Gitは自動的に中間のコミット(def456abc789...)をチェックアウトします。
ステップ3:テストを実行して結果をマークする
チェックアウトされたコミットでテストを実行します。
|
|
|
|
ステップ4:原因コミットの特定
good/badのマークを繰り返すと、最終的にバグを導入したコミットが表示されます。
|
|
ステップ5:原因を調査して修正する
特定されたコミットの変更内容を確認します。
|
|
ステップ6:セッションを終了する
|
|
git bisect runで自動テストと連携する
手動でのテストは時間がかかります。git bisect runを使えば、テストスクリプトを自動実行してバグを特定できます。
bisect runの基本構文
|
|
テストスクリプトは以下の終了コードを返す必要があります。
| 終了コード | 意味 |
|---|---|
| 0 | テスト成功(good) |
| 1-124, 126, 127 | テスト失敗(bad) |
| 125 | テスト不可(skip) |
例1:makeでビルドテストを自動化する
ビルドが壊れたコミットを自動で特定します。
|
|
例2:テストスイートを自動実行する
特定のテストケースが失敗するコミットを特定します。
|
|
例3:カスタムテストスクリプトを使用する
複雑な条件でテストする場合は、シェルスクリプトを作成します。
|
|
スクリプトに実行権限を付与して使用します。
|
|
例4:ワンライナーでテストを実行する
簡単なテストならワンライナーで記述できます。
|
|
git bisect skipでテスト不可能なコミットを処理する
ビルドが壊れているコミットや、テストに必要なファイルが欠けているコミットがある場合、git bisect skipでスキップできます。
skipの基本的な使い方
|
|
skipを使う場面
| 状況 | 対処法 |
|---|---|
| ビルドが失敗する | git bisect skip |
| テスト環境が整わない | git bisect skip |
| 不完全なコミット | git bisect skip |
注意点:skipの制限
スキップしたコミットが原因コミットの隣接している場合、Gitは正確なコミットを特定できません。
|
|
この場合は、スキップしたコミットを手動で確認する必要があります。
git bisect logとreplayで作業を記録・再現する
bisectセッションの内容を記録し、後で再現できます。
bisect logで履歴を確認する
|
|
bisect replayで再現する
ログをファイルに保存して再現できます。
|
|
高度なテクニック:パス指定とカスタム用語
特定のパスに限定してbisectを実行する
バグが特定のディレクトリやファイルに関連することがわかっている場合、パスを指定して探索を効率化できます。
|
|
カスタム用語を使用する
バグ修正のコミットを探す場合など、「good/bad」が意味的にわかりにくい場合はカスタム用語を使用できます。
|
|
old/newを使用する
「good/bad」の代わりに「old/new」を使うこともできます。
|
|
git bisectを使う際の注意点とベストプラクティス
注意点
| 項目 | 説明 |
|---|---|
| クリーンな作業ツリー | bisect中は作業ツリーの変更を避ける |
| テストの再現性 | 同じコミットで同じ結果が得られるテストを使用する |
| 外部依存 | データベースや外部サービスの状態に依存しないテストが望ましい |
| マージコミット | --first-parentオプションで履歴を単純化できる |
ベストプラクティス
-
再現可能なテストを用意する:bisectを始める前に、バグを確実に再現できるテストケースを作成します
-
範囲を絞り込む:可能な限り、goodとbadの範囲を狭く設定します
-
自動化を活用する:可能であれば
git bisect runで自動化し、人的ミスを減らします -
ログを保存する:
git bisect logで作業を記録しておけば、中断しても再開できます -
チェックアウト不要オプション:ビルド不要のテストなら
--no-checkoutで高速化できます
|
|
まとめ
git bisectは、二分探索アルゴリズムを使ってバグの原因コミットを効率的に特定する強力なツールです。
| コマンド | 用途 |
|---|---|
git bisect start |
bisectセッションを開始 |
git bisect bad |
バグがあるコミットをマーク |
git bisect good |
正常なコミットをマーク |
git bisect skip |
テスト不可能なコミットをスキップ |
git bisect run |
テストスクリプトを自動実行 |
git bisect reset |
セッションを終了 |
git bisect log |
履歴を確認 |
git bisect replay |
ログから再現 |
1000件のコミットがあっても約10回のテストで原因を特定できるgit bisectは、効率的なデバッグに欠かせないツールです。特にgit bisect runと自動テストを組み合わせることで、完全自動でバグの原因コミットを見つけられます。