Git bisectとは?バグの原因コミットを二分探索で特定する方法を解説
Git bisectの使い方と実践的な活用方法を初心者向けに解説します。二分探索アルゴリズムを使ってバグを引き起こしたコミットを効率的に特定する方法を学びましょう。手動での実行から自動化まで詳しく説明します。
Git bisectとは
Git bisectは、バグを引き起こしたコミットを二分探索(バイナリサーチ)で効率的に特定するコマンドです。「以前は動いていたのに、いつの間にか動かなくなった」という問題の原因を見つけるときに非常に役立ちます。
たとえば、1000個のコミットがある中からバグの原因を探す場合、1つずつ確認すると最大1000回のチェックが必要です。しかしbisectを使えば、二分探索により約10回(log₂1000 ≒ 10)のチェックで原因を特定できます。
bisectの仕組み
bisectは「正常だったコミット」と「問題が発生しているコミット」の間を半分に分割しながら、問題の原因となったコミットを絞り込んでいきます。
上の図で、コミットAは正常(good)、コミットHで問題が発生(bad)している場合、bisectはまず中間のコミットDをチェックします。Dが正常ならD〜Hの間を、問題があればA〜Dの間を次に調べます。この繰り返しで原因を絞り込みます。
bisectの基本的な使い方
bisectセッションを開始する
まず、bisectセッションを開始します。
git bisect start
問題のあるコミットを指定する(bad)
現在のコミット(HEAD)で問題が発生している場合は、以下のように指定します。
# 現在のコミットを問題あり(bad)としてマーク
git bisect bad
特定のコミットを指定することもできます。
git bisect bad <コミットハッシュ>
正常だったコミットを指定する(good)
問題が発生していなかった(正常に動作していた)コミットを指定します。
git bisect good <コミットハッシュ>
goodとbadの両方を指定すると、Gitは自動的に中間のコミットをチェックアウトします。
Bisecting: 5 revisions left to test after this (roughly 3 steps)
[abc1234...] コミットメッセージ
各コミットを確認してマークする
チェックアウトされたコミットで問題があるかどうかを確認し、結果をマークします。
# 問題がある場合
git bisect bad
# 問題がない場合
git bisect good
このプロセスを繰り返すと、最終的に問題を引き起こした最初のコミットが特定されます。
abc1234... is the first bad commit
commit abc1234...
Author: 開発者名 <email@example.com>
Date: Mon Jan 6 10:00:00 2026 +0900
問題のある変更を追加
bisectセッションを終了する
原因が特定できたら、bisectセッションを終了して元のブランチに戻ります。
git bisect reset
実践的な使用例
具体的なワークフロー
実際のバグ調査の流れを見てみましょう。
# 1. bisectを開始
git bisect start
# 2. 現在のHEAD(main)で問題が発生している
git bisect bad
# 3. 1週間前のコミットでは正常だったことがわかっている
git bisect good abc1234
# 4. Gitが自動的に中間のコミットをチェックアウト
# Bisecting: 15 revisions left to test after this (roughly 4 steps)
# 5. アプリをビルドしてテスト
npm run build
npm test
# 6. テスト結果に応じてマーク
git bisect good # または git bisect bad
# 7. 手順5-6を繰り返す
# 8. 原因が特定されたら終了
git bisect reset
skipを使う
特定のコミットがビルドできない、またはテストできない場合はskipでスキップできます。
git bisect skip
スキップされたコミットの前後から調査が続行されます。ただし、スキップが多いと原因の特定が困難になる場合があります。
bisectの自動化
手動で毎回テストするのは大変です。テストスクリプトを用意すれば、bisectを完全に自動化できます。
自動化の基本
git bisect runコマンドに、テスト用のスクリプトを渡します。スクリプトが終了コード0を返せばgood、0以外ならbadとして扱われます。
git bisect start HEAD abc1234
git bisect run <テストスクリプト>
テストスクリプトの例
Node.jsプロジェクトで特定のテストが通るかどうかを確認する場合:
#!/bin/bash
# test-bug.sh
# 依存関係をインストール
npm ci
# 特定のテストを実行
npm test -- --grep "問題のあるテスト"
# テスト結果の終了コードがそのまま返される
このスクリプトを実行可能にして、bisect runに渡します。
chmod +x test-bug.sh
git bisect start HEAD abc1234
git bisect run ./test-bug.sh
終了コードの意味
| 終了コード | 意味 |
|---|---|
| 0 | good(正常) |
| 1〜124, 126, 127 | bad(問題あり) |
| 125 | skip(スキップ) |
| 128〜 | bisect中止 |
ビルドに失敗した場合にskipとしたい場合は、スクリプト内で終了コード125を返すようにします。
#!/bin/bash
# test-bug.sh
npm ci || exit 125 # ビルド失敗ならskip
npm test -- --grep "問題のあるテスト"
初心者が混乱しやすいポイント
bisect中に作業内容が変わることへの戸惑い
bisect中はGitが自動的にコミットをチェックアウトするため、作業ディレクトリの内容が次々と変わります。これは正常な動作であり、git bisect resetを実行すれば元の状態に戻れます。
bisectを始める前に、未コミットの変更がないことを確認しましょう。
# 変更がある場合はstashで退避
git stash
git bisect start
# ... bisect作業 ...
git bisect reset
git stash pop
goodとbadの指定を間違えた場合
goodとbadを逆に指定してしまった場合、bisectは正しく動作しません。途中で間違いに気づいたら、いったんリセットしてやり直すのが確実です。
git bisect reset
git bisect start
# 正しい順序で指定し直す
bisectとblameの使い分け
どちらも問題の原因を探すツールですが、用途が異なります。
| ツール | 用途 | 適したケース |
|---|---|---|
| bisect | いつから問題が発生したかを特定 | 動作の変化、回帰バグ |
| blame | 特定の行を誰がいつ変更したかを確認 | コードの意図を調べたい、特定行の変更履歴 |
「この機能が動かなくなった」→ bisect 「この行はなぜこう書かれているのか」→ blame
よくある問題と対処法
マージコミットがある場合
マージコミットが含まれる履歴でbisectを使う場合、--first-parentオプションでメインブランチのコミットのみを対象にできます。
git bisect start --first-parent
問題の再現が難しい場合
断続的にしか再現しない問題の場合、テストを複数回実行するスクリプトを作成します。
#!/bin/bash
# flaky-test.sh
for i in {1..5}; do
npm test || exit 1
done
exit 0
途中経過を確認したい
bisectの進捗状況を確認するにはgit bisect logを使います。
git bisect log
出力例:
git bisect start
# bad: [hash1] 最新のコミット
git bisect bad hash1
# good: [hash2] 正常だったコミット
git bisect good hash2
# bad: [hash3] 中間コミット
git bisect bad hash3
このログを保存しておけば、後から同じ調査を再現できます。
git bisect log > bisect.log
git bisect reset
# 後から再現
git bisect replay bisect.log
bisectを活用するためのヒント
効果的にbisectを使うためのポイントをまとめます。
| ポイント | 説明 |
|---|---|
| こまめなコミット | コミットが細かいほど原因の特定が容易 |
| 動作するコミット | 各コミットがビルド・テスト可能な状態を維持 |
| 自動テストの整備 | bisect runによる自動化が可能になる |
| タグの活用 | リリースポイントにタグを付けておくとgoodの指定が楽 |
特に「各コミットが動作する状態を維持する」ことは、bisectに限らずGitを使う上で重要な習慣です。中途半端な状態でコミットすると、bisect時にビルドエラーでスキップが多発し、調査が困難になります。
まとめ
Git bisectは、バグの原因コミットを二分探索で効率的に特定するツールです。
git bisect startでセッション開始git bisect badで問題のあるコミットを指定git bisect goodで正常なコミットを指定- 各コミットをテストしてgood/badをマーク
git bisect resetで終了
手動での確認が面倒な場合は、git bisect runでテストスクリプトを指定して自動化できます。
数百、数千のコミットがある大規模なプロジェクトでも、bisectを使えば数回のテストでバグの原因を特定できます。「以前は動いていたのに」という問題に遭遇したら、ぜひbisectを活用してみてください。
編集部