トップ «前の日記(2011-08-18) 最新 次の日記(2011-10-05)» 編集

Route 477



2011-09-08

[git] どの段階で混入したのか全く分からないバグが発生したので、git bisectを使ってみた

気づいたら、BiwaSchemeのmakeが通らない状態になっていた。

java -jar bin/yuicompressor-2.4.2.jar lib/biwascheme.js -o lib/biwascheme-min.js

[ERROR] 16082:51:invalid property id

[ERROR] 1:0:Compilation produced 1 syntax errors.

数日前までは通っていたんだけど、それから結構な回数コミットを行ったので、どれが原因なのか分からない。

でも大丈夫、こんな時こそ(存在は知っていたけど使う機会のなかった)git bisectを使うチャンスだ。

git bisectは、「OKなコミット」と「NGなコミット」の2点の間を二分探索することで、バグの原因となったコミットを見つけるコマンドだ。 使い方はPro Gitの説明が非常に分かりやすい。特に、手動で二分探索する手順も書いてあるところがいい。

というわけでやってみよう。まず、git bisect startでbisectを初期化する。(※出力はreposhのもの)

 master> bisect start

次に、OKなコミットとNGなコミットを指定する。現在のmasterはNGな状態なので、まずは「git bisect bad」だ。

 master> bisect bad

OKなコミットはgit logから適当な地点を拾う。2点を指定すると、間に13のコミットがあるというメッセージが表示される。二分探索すれば、だいたい4回で見つけられる計算だ。

 master> bisect good ceeab65e9e73815b508012e4c9dc124abf7bdc05
 Bisecting: 13 revisions left to test after this (roughly 4 steps)[d7d600d0c9390f339b92e6e960187201294725b2] Changed BiwaScheme.inspect to show true/false as "#t", "#f".

ここでもう一度makeをやってみる。失敗したので、git bisect badを実行。さらに間のコミットに移動した。

(no branch)> bisect bad
Bisecting: 6 revisions left to test after this (roughly 3 steps)
[042520b233f904db9657fd1fe94f9f59b240880a] there's no `named let*' in Scheme

これを何回か繰り返すと、最終的に「xxxx is the first bad commit」というメッセージが表示される。これがバグの原因となったコミットだ。

(no branch)> bisect bad
55376219795834122bd3c01c6c482bd7c090f7d8 is the first bad commit
commit 55376219795834122bd3c01c6c482bd7c090f7d8
Author: Yutaka HARA <yutaka.hara.gmail.com>
Date:   Tue Sep 6 20:54:06 2011 +0900

    new: console-log, console-debug, etc.

    Also improved BiwaScheme.inspect to take additional argument 'opts'.

:040000 040000 701ac0d424da53822a8f91e4b095e651e5781cf7 dd1b14c850c8c62ee018e1d60abd6abad26a250e M      src

git show 042520b233f904db9657fd1fe94f9f59b240880aでそのコミットを見て、ソースコードの当該箇所をコメントアウトしてみる。確かにmakeが通った。 どうも、オブジェクトのキーにdefault(予約語)を使っていたのがダメだったようだ。

+          return BiwaScheme.inspect(item, {default: item});

なお、「git bisect run make」とすれば、手でmakeを実行するプロセスも省くことができる*1

*1 今回は、makeで生成されたファイルを消す作業があったりしてとりあえず手動でやったけど