gitを使ってどのコミットでバグが入り込んだか特定する。git bisectの使い方
git bisectは二分検索で問題があるコミットを探し出してくれるコマンド。
今回用意したリポジトリではあまり二分検索の良さが享受できないが、使い方のデモくらいはできると思う。
リポジトリ: https://github.com/newnakashima/git-learn
単純な使い方
まず、masterのHEADにいる状態で、git bisect startを実行する。
$ git bisect start
次に、HEADでテストを実行してみる。
$ node test.js hogehoge assert.js:49 throw new AssertionError(obj); ^ AssertionError [ERR_ASSERTION]: 'hogehoge\n' === 'fugafuga\n' at Socket.<anonymous> (/Users/nakashima/develop/git-learn/test.js:10:16) at Socket.emit (events.js:180:13) at addChunk (_stream_readable.js:274:12) at readableAddChunk (_stream_readable.js:261:11) at Socket.Readable.push (_stream_readable.js:218:10) at Pipe.onread (net.js:581:20)
テストが通らなかったので、git bisect badコマンドで、HEADのコミットに問題が含まれていることをgitに教える。
$ git bisect bad
次に、テストが通っていたことが確認できているコミットIDを指定してgit bisect goodコマンドを実行して、問題なかったコミットをgitに教える。この場合はinitial commitのIDを渡している。
$ git bisect good Bisecting: 1 revision left to test after this (roughly 1 step) [d27eedce7b2668a995dc0e73560db6f66edb8ed7] hogehogeに戻した
すると、未検証のコミットに自動でチェックアウトしてくれる。ここで再度テストを実行し、gitに結果を教える。
$ node test.js assert.js:49 throw new AssertionError(obj); ^ AssertionError [ERR_ASSERTION]: 'hogehoge\n' === 'fugafuga\n' at Socket.<anonymous> (/Users/nakashima/develop/git-learn/test.js:9:16) at Socket.emit (events.js:180:13) at addChunk (_stream_readable.js:274:12) at readableAddChunk (_stream_readable.js:261:11) at Socket.Readable.push (_stream_readable.js:218:10) at Pipe.onread (net.js:581:20) $ git bisect bad Bisecting: 0 revisions left to test after this (roughly 0 steps) [10c88efbec451262196cd451ee52618b660c397b] fugafugaに変更
再度gitが未検証のコミットにチェックアウトしてくれるので、テストを実行して結果を教える。テストが通った場合はgit bisect goodを実行する。
これを続けていくと、最終的にどこでバグが混入したのかgitが教えてくれる。
$ node test.js test OK $ git bisect good d27eedce7b2668a995dc0e73560db6f66edb8ed7 is the first bad commit commit d27eedce7b2668a995dc0e73560db6f66edb8ed7 Author: newnakashima <newnakashima2014@gmail.com> Date: Tue Jul 24 00:56:04 2018 +0900 hogehogeに戻した :100644 100644 a31254a12816398ce382e6096d7923f330a9ac17 8aa758ae91689ffa39dc30412735a7ddb071032b M app.js
問題のコミットがわかったら、git bisect resetをして、git bisectの状態を元に戻しておく。
$ git bisect reset Previous HEAD position was 10c88ef... fugafugaに変更 Switched to branch 'master' Your branch is up to date with 'origin/master'.
git bisect に自動でテストをやってもらう方法
コミットが多いと毎回手動でテストを実行するのがだるい。git bisectは自動でテストを実行して問題のコミットを見つけてくれたりもする。
git bisect startコマンドには検索開始コミットと終了コミットを指定できる。
$ git bisect start HEAD 8cc2236519e3919bf9edbcd937fd3c0f464dfb04 Bisecting: 1 revision left to test after this (roughly 1 step) [d27eedce7b2668a995dc0e73560db6f66edb8ed7] hogehogeに戻した
自動でテストを回してもらうには、git bisect runコマンドを使う。
$ git bisect run node test.js running node test.js assert.js:49 throw new AssertionError(obj); ^ AssertionError [ERR_ASSERTION]: 'hogehoge\n' === 'fugafuga\n' at Socket.<anonymous> (/Users/nakashima/develop/git-learn/test.js:9:16) at Socket.emit (events.js:180:13) at addChunk (_stream_readable.js:274:12) at readableAddChunk (_stream_readable.js:261:11) at Socket.Readable.push (_stream_readable.js:218:10) at Pipe.onread (net.js:581:20) Bisecting: 0 revisions left to test after this (roughly 0 steps) [10c88efbec451262196cd451ee52618b660c397b] fugafugaに変更 running node test.js test OK d27eedce7b2668a995dc0e73560db6f66edb8ed7 is the first bad commit commit d27eedce7b2668a995dc0e73560db6f66edb8ed7 Author: newnakashima <newnakashima2014@gmail.com> Date: Tue Jul 24 00:56:04 2018 +0900 hogehogeに戻した :100644 100644 a31254a12816398ce382e6096d7923f330a9ac17 8aa758ae91689ffa39dc30412735a7ddb071032b M app.js bisect run success
手動でやるのと同じ手順をgitが勝手にやってくれた。便利。
git bisect runで指定したコマンドが成功したのか失敗したのかの判定は、コマンドの終了ステータスで判定している。0のときは成功、1 - 127(125除く)のときは失敗、と判定されるらしい。125のときはテスト不能と判定され、スキップされるらしい。