git はファイルの集合の履歴を格納するツールとして とても良く考慮されたツールです。 ファイル階層の中身を圧縮したスナップショットと スナップショット間の関係を表す "commit" を格納することで これを実現しています。
git は非常に柔軟で高速に動作するプロジェクトの履歴探索ツールです。
プロジェクトにバグを入れ込んだコミットを見つける為の便利な 特殊ツールの説明からはじめましょう。
プロジェクトのバージョン 2.6.18 では動作するが、"master" ブランチの 最新バージョンではクラッシュするとしましょう。 そのようなリグレッションの原因を探し出す最良の方法は プロジェクトの履歴を総当たりで検索し、問題を引き起こす特定のコミットを見つけることです。 git-bisect(1) コマンドはこの作業の手伝いをしてくれます:
$ git bisect start
$ git bisect good v2.6.18
$ git bisect bad master
Bisecting: 3537 revisions left to test after this
[65934a9a028b88e83e2b0f8b36618fe503349f8e] BLOCK: Make USB storage depend on SCSI rather than selecting it [try #6]
この時点で "git branch" を実行すると、git は一時的に "(no branch)" に移動していることが確認できます。 HEADはいまやあらゆるブランチから分離されており、 "master" からは到達可能だが、v2.6.18 からは到達できない コミット(id が 65934… のコミット)を指しています。 コンパイルとテストをし、クラッシュするかを確認します。 もしクラッシュするのなら、以下のように:
$ git bisect bad
Bisecting: 1769 revisions left to test after this
[7eff82c8b1511017ae605f0c99ac275a7e21b867] i2c-core: Drop useless bitmaskings
として、より古いバージョンを確認します。このように git に各段階でそのバージョンが good か bad かを伝える作業を続け、 テストすべきリビジョンの残数は各回で約半分ずつに削られていきます。
(今回の場合では)約13回テストした後、罪を犯したコミットの id を 見つけることができます。そのコミットに対して git-show(1) を実行し、 誰がそのコミットを書いたかを見つけ出し、コミットの id を添えて、 バグレポートをメールします。最後に、
$ git bisect reset
を実行し、以前いたブランチに戻ます。
ここで注意すべきことはgit bisect
が各状態でチェックアウトする
バージョンが単なる提案にすぎないことです。
違うバージョンをテストしてもかまわないのです。
例えば、関係のない変更をしているコミット上にいるかもしれません;
その時は以下を実行してください。
$ git bisect visualize
こうすると gitk が起動して、選択されたコミットに "bisect" という マーカーをつけます。近くの安全そうなコミットを探し、コミットIDをメモして 次のコマンドでチェックアウトします。
$ git reset --hard fb47ddb2db...
そしてテストし、"bisect good" または "bisect bad" の適切な方を実行し、 作業を続けます。
"git bisect visualize"を実行して"git reset —hard fb47ddb2db…" を実行するかわりに、単に現在のコミットをスキップしたいかもしれません。 その場合は以下を実行してください。
$ git bisect skip
しかしこの場合にgitは結果的いくつかの最初のスキップされたコミットと その後の悪いコミットの間にある最初の悪いコミットが わからなくなる可能性があります。
もし良いコミットと悪いコミットを判断することが可能な テストスクリプトがあるなら、bisect作業の自動化には いくつかの方法があります。 詳細はgit-bisect(1)をご覧ください。