git bisectの使いかた

gitを話を聞きに第33回git勉強会に行ってきました。

詳しいまとめは

などがあるので割愛します。

git stashの話が出てきたときに、git stashがいつごろから入った機能なのか調べるにはどうしたらよいか?という話が出ていて、git bisectを使うと有効に探せるのではないか?とあまりgit bisectがわかってないながらも言ってみたので、できるのかどうか検証してみた。

まずはgitをgit clone. URLがgitgitですね。

git clone git://git.kernel.org/pub/scm/git/git.git

git stashの機能がいつ入った機能かは知らないものとして、最新版から最初のコミットまですべてを対象とするものとする。

まず、git logの一番最後を見て、一番最初のコミットを調べる。(いまいちうまいやりかたがわからず。)

$ git log 
commit e83c5163316f89bfbde7d9ab23ca2e25604af290
Author: Linus Torvalds <torvalds@ppc970.osdl.org>
Date:   Thu Apr 7 15:13:13 2005 -0700

    Initial revision of "git", the information manager from hell

これだと分かるので、

$ git bisct start HEAD e83c5163316f89bfbde7d9ab23ca2e25604af290

でgit bisectを開始。

git bisect start badになるコミット goodになるコミットというふうに指定するらしい。

git bisect run commandで自動的に探索してくれる。

commandは0を返せばgood、1を返せばbadと扱ってくれるらしい。ここではgit-stash.shが存在するとエラーを返すようなシェルスクリプトを書く。

$ cat ./test.sh             
#!/bin/sh
ls git-stash.sh || exit 0

exit 1

あとは下記のように実行すれば勝手にgit stashが初めて入ったコミットが特定できる。

yoshimi% git bisect run ./test.sh                                                                                                                             [ ~/Sources/c/git ]
running ./test.sh
ls: git-stash.sh: No such file or directory
Bisecting: 4010 revisions left to test after this
[3d66dc9657f195cb241387a87bcdd5709abd8a21] Merge branch 'ph/parseopt'
running ./test.sh
git-stash.sh
Bisecting: 2005 revisions left to test after this
[8b7f5fc1cac8eb49b4846021706fc06ce074881b] cvsimport: add support for new style remote layout
running ./test.sh
ls: git-stash.sh: No such file or directory
Bisecting: 1002 revisions left to test after this
[cf32190aa6966dea519e77cdcc80b87026beb3b4] git.c: execution path
running ./test.sh
git-stash.sh
Bisecting: 501 revisions left to test after this
[ad562a817256adff4faadc17900b4aba67ca471a] ignore git-rebase--interactive
running ./test.sh
ls: git-stash.sh: No such file or directory
Bisecting: 255 revisions left to test after this
[237ce836e770e8ead12a14ee4a8170009fa4a40b] Merge branch 'maint'
running ./test.sh
git-stash.sh
Bisecting: 127 revisions left to test after this
[b941ffac506d3f57246e46a8913da614e62a1d48] Merge branch 'maint'
running ./test.sh
git-stash.sh
Bisecting: 63 revisions left to test after this
[39741ab1c54c6e7411b983f2a64d5813bc5b4059] Merge branch 'lt/run'
running ./test.sh
ls: git-stash.sh: No such file or directory
Bisecting: 32 revisions left to test after this
[71e55854fd6e5c9ce786bcd20efef43bd56f9df0] Merge branch 'rs/diff'
running ./test.sh
ls: git-stash.sh: No such file or directory
Bisecting: 15 revisions left to test after this
[e1bc8dc66dd5a2ef8b23c6b7cac8164d85e73307] Merge branch 'jc/diffcore'
running ./test.sh
ls: git-stash.sh: No such file or directory
Bisecting: 8 revisions left to test after this
[9a5391cf1836fa1b66f3c89ce9b38f8249bb0521] Documentation: quote {non-attributes} for asciidoc
running ./test.sh
git-stash.sh
Bisecting: 3 revisions left to test after this
[9488e875862de4e3c9b022ecd9d0845bc28d1996] git-stash: require "save" to be explicit and update documentation
running ./test.sh
git-stash.sh
Bisecting: 1 revisions left to test after this
[09ccdb630517842e6ad3d9354fbd856174c70d17] Document git-stash
running ./test.sh
git-stash.sh
Bisecting: 0 revisions left to test after this
[f2c66ed196d1d1410d014e4ee3e2b585936101f5] Add git-stash script
running ./test.sh
git-stash.sh
f2c66ed196d1d1410d014e4ee3e2b585936101f5 is first bad commit
commit f2c66ed196d1d1410d014e4ee3e2b585936101f5
Author: しらいしななこ <nanako3@bluebottle.com>
Date:   Sat Jun 30 14:37:09 2007 +0900

    Add git-stash script

    When my boss has something to show me and I have to update, for some
    reason I am always in the middle of doing something else, and git pull
    command refuses to work in such a case.

    I wrote this little script to save the changes I made, perform the
    update, and then come back to where I was, but on top of the updated
    commit.

    This is how you would use the script:

      $ git stash
      $ git pull
      $ git stash apply

    [jc: with a few fixlets from the list]

    Signed-off-by: Nanako Shiraishi <nanako3@bluebottle.com>
    Signed-off-by: Junio C Hamano <gitster@pobox.com>

:100644 100644 e8b060cbe43d13b82ad8686f7676a26ef559a609 02d9b04da0a493fd6d28156fadc1a1f188ac2b0f M      .gitignore
:100644 100644 5d60dc8e1247bdea39016dd409159f1ca1b15982 b3b66b79914170cdce1ccd5f5617b6d0408d6981 M      Makefile
:000000 100755 0000000000000000000000000000000000000000 c8c5c5648efa20d8c565da63279c57ad76767101 A      git-stash.sh
bisect run success

git bisectすばらしす。

ただもちろんこの場合は、git log git-stash.shの結果の一番下を見る方が速いですw