「数日前は確かに動いていた機能が、いつの間にか動かなくなっている(デグレード)」。大規模な開発プロジェクトにおいて、このような不具合に直面したとき、数百から数千のコミット履歴の中から「バグが混入した原因コミット」を手動で一つずつ検証して見つけるのは現実的ではありません。
このような探索タスクを劇的に高速化するのが、Gitに標準で備わっているデバッグ支援コマンド git bisect です。
本記事では、二分探索アルゴリズムを用いてバグ混入コミットを爆速で突き止める git bisect の具体的な使い方を解説します。
1. git bisect の仕組み(二分探索)
git bisect は、**二分探索(Binary Search)**のアルゴリズムを利用してコミットを走査します。
例えば、100個のコミットがあり、どれか1つでバグが混入したとします。
- まず、ちょうど真ん中(50番目)のコミットにチェックアウトします。
- その時点で動作テストを行います。
- もしバグがあれば、原因は前半の「1〜49番目」の中にあります。
- もし正常に動けば、原因は後半の「51〜100番目」の中にあります。
- 次はさらにその範囲の半分(例: 25番目、または75番目)に飛びます。
この処理を繰り返すことで、わずか $log_2(N)$ 回(100個のコミットなら最大7回前後)のテスト実行だけで、確実にバグの発生源となったコミットを特定できます。
2. 基本的な手順(手動テスト)
手動でコードを確認しながら探索を行う手順を追ってみましょう。
ステップ1: 探索モードを開始する
まずは探索を開始するコマンドを実行します。
git bisect start
ステップ2: 正常と異常の境界(コミット)を指定する
現在(バグが発生している状態)のコミットを「異常(bad)」として登録します。
git bisect bad
次に、この機能が確実に正しく動作していた過去のコミットハッシュ(例: a1b2c3d、または古いタグ名 v1.2.0 など)を「正常(good)」として登録します。
git bisect good a1b2c3d
このコマンドを実行した瞬間、Gitは自動的に「good」と「bad」の中間地点のコミットにチェックアウトします。
ステップ3: テストと判定を繰り返す
チェックアウトされた状態でアプリを動かすなどして動作確認を行います。
- バグが再現する場合:
git bisect bad - バグが再現せず、正常に動く場合:
git config git bisect good
判定を入力するたびに、Gitは残りのコミット群のさらに半分の位置へとチェックアウトを繰り返します。
ステップ4: 原因コミットの判明と終了
探索範囲が残り1つに絞り込まれると、ターミナルに以下のような決定的な情報が表示されます。
e5f6g7h8i9j0a1b2c3d4 is the first bad commit
commit e5f6g7h8i9j0a1b2c3d4
Author: Jane Doe <[email protected]>
Date: Mon Oct 15 12:00:00 2025 +0900
fix: change payment calculations
:040000 040000 8c1b2d3... 9e3f4a1... M src
これで、Jane Doe氏が10月15日に行った「payment calculations」の修正コミットこそがバグの混入原因であることが突き止められました。
原因がわかったら、以下のコマンドで探索モードを終了し、元の開発ブランチ(HEAD)に戻ります。
git bisect reset
3. テストスクリプトを使った自動探索(git bisect run)
もしバグの有無を自動化テストスクリプト(テストコマンド)で判定できる場合、探索自体を完全に自動化することができます。
git bisect start
git bisect bad
git bisect good v1.2.0
# テストスクリプトを実行し、終了コードが0(成功)ならgood、1以上(失敗)ならbadと自動判定させる
git bisect run npm test
このコマンドを実行すると、Gitが全自動でチェックアウトとテスト実行を繰り返し、ものの数秒で原因コミットを特定してくれます。
まとめ
原因不明の不具合に遭遇したときは、闇雲にコードを読む前に git bisect を活用しましょう。
- 正常だった時期と異常になった時期をGitに教えるだけで、二分探索で絞り込める
- コミット数が多くなるほど効果を発揮する(1,000コミットでも約10回で特定)
git bisect runと自動テストを組み合わせれば数秒で特定可能
トラブルシューティングの時間を大幅に削減できるので、ぜひ習得しておいてください。
