git bisectでメソッドが削除されたコミットを探す

git bisectを使うと、コミット履歴から「何らかのテスト」が初めて失敗するコミットを探し出すことができます。

ちょうど、「Doctrine2 MongoDB ODMのDocumentManagerからcreateQuery()メソッドが無くなっている」という発言を見かけたので、これを例にやってみます。

まず、リポジトリをcloneしてきて準備

$ git clone git://github.com/doctrine/mongodb-odm.git
$ cd mongodb-odm

bisectを開始します。最新のコミットではメソッドが無くなっているので「bad」、どこか適当な古いコミットで目的のメソッドがあるものを「good」に指定します。最初のbadとgoodを指定すると、gitがその中間のコミットを取ってきてくれます。

$ git bisect start
$ git bisect bad
$ git bisect good 246e2ae9	
Bisecting: 49 revisions left to test after this (roughly 6 steps)
[078d158aaa5cd421f7bc726a16d457e8f77de28f] updated MongoDB\ODM\Query(Builder) to match MongoDB\Query(Builder)

このコミットで目的のメソッドが削除されているかどうかをテストし、あれば「good」、なければ「bad」を指定します。すると、gitがさらに自動的に次のコミットを取得してきて、最終的に最初にbadになるコミットがみつかります。
この手順は自動化でき、git bisect run にテストスクリプトを指定できます。今回は特定のファイルの特定のメソッドがあるかどうかなので、次のようにしました。

$ git bisect run grep 'function createQuery(' lib/Doctrine/ODM/MongoDB/DocumentManager.php
running grep function createQuery( lib/Doctrine/ODM/MongoDB/DocumentManager.php
Bisecting: 24 revisions left to test after this (roughly 5 steps)
[9a7c804ea0080bad4998aba79135a951b6912ed9] Adding doc blocks.
running grep function createQuery( lib/Doctrine/ODM/MongoDB/DocumentManager.php
Bisecting: 11 revisions left to test after this (roughly 4 steps)
[0fd37ae16f40373948e4a1f374d1f1e83a358b7b] Fix so initial version comes from default value of property.
running grep function createQuery( lib/Doctrine/ODM/MongoDB/DocumentManager.php
Bisecting: 5 revisions left to test after this (roughly 3 steps)
[4645babd9ab1cb4ee2473f662744dc60a3582243] Implemented id generator strategies and got rid of the old custom id stuff. Also implemented uuid and increment id generator.
running grep function createQuery( lib/Doctrine/ODM/MongoDB/DocumentManager.php
    public function createQuery($queryString, $parameters = array())
Bisecting: 2 revisions left to test after this (roughly 2 steps)
[daedacfbfddca96c3d75d19acdf50b9e1ca1be56] Refactoring API to match ORM and implementing optimistic and pessimistic locking
running grep function createQuery( lib/Doctrine/ODM/MongoDB/DocumentManager.php
    public function createQuery($queryString, $parameters = array())
Bisecting: 0 revisions left to test after this (roughly 1 step)
[182f14e1e5ebe66a5d0885b25d44c36f04f4bda1] Fixing argument to match orm.
running grep function createQuery( lib/Doctrine/ODM/MongoDB/DocumentManager.php
Bisecting: 0 revisions left to test after this (roughly 0 steps)
[134b7ae418d33697fcb6a6dc73a34a8ec4d32904] Ripping out DQL and fixing a few things in QueryBuilder
running grep function createQuery( lib/Doctrine/ODM/MongoDB/DocumentManager.php
134b7ae418d33697fcb6a6dc73a34a8ec4d32904 is the first bad commit
commit 134b7ae418d33697fcb6a6dc73a34a8ec4d32904
Author: Jonathan H. Wage <jonwage@gmail.com>
Date:   Sat Nov 27 22:43:33 2010 -0600

    Ripping out DQL and fixing a few things in QueryBuilder

:040000 040000 16b89b55af621da2ae44a6b99d70a592ef54c42c bcf0f8dd448e4df6c2428f3d2bb2c8636ad3e72f M      lib
:040000 040000 f447e4e4db267d6fe65520d75d848f4a02074fb3 fcb0035153200ade88bb9cc88f31a666089ca108 M      tests
bisect run success

初めてbadになったコミット=メソッドが削除されたコミットが見つかりました!


参考: git-bisect(1)


もっと上手いor簡単なやり方など、教えてください!