gitでタグをチェックアウトする。

Modernizrが2月20日に1.7をリリースしたようです。まだリリースノートも無いようなので、1.6のも欲しくなりました。Githubからリポジトリをクローンして、1.6のコードを取ろうと思ったら、意外にタグをチェックアウトする方法が分からなかったので調べました。

方法

$ git clone https://github.com/Modernizr/Modernizr.git
$ cd Modernizr
$ git tag -l
v1.1
v1.5
v1.6
v2010.07.06dev

まず、前提条件としてModernizrのリポジトリにはこんなタグがあります。

ブランチを作る場合
$ git checkout -b 1.6 refs/tags/v1.6

ブランチを作りつつ、v1.6タグの内容をワーキングツリーにチェックアウトします。ブランチ名とタグ名が被ると、diffが取りにくくなったり*1するので違うものに。

ブランチを作らない場合
$ git checkout refs/tags/v1.6

単にタグの内容を確認したいだけなのに、使いもしないブランチを作りたくない場合は、このように使います。

解説

ブランチを作る場合
$ head -n 4 modernizr.js 
/*!
 * Modernizr v1.7
 * http://www.modernizr.com
 *
$ git branch
* master
$ git checkout -b 1.6 refs/tags/v1.6
Switched to a new branch '1.6'
$ git branch
* 1.6
  master
$ head -n 4 modernizr.js 
/*!
 * Modernizr v1.6
 * http://www.modernizr.com
 *

1.6ブランチが作られて、ワーキングツリーにあるファイルもv1.6タグのものになってます。

ブランチを作らない場合
$ head -n 4 modernizr.js 
/*!
 * Modernizr v1.7
 * http://www.modernizr.com
 *
$ git branch
* master
$ git checkout refs/tags/v1.6
Note: checking out 'refs/tags/v1.6'.

You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

  git checkout -b new_branch_name

HEAD is now at 067bc80... Version change to 1.6 and small (semantic) comment tweaks for a clean release
$ git branch
* (no branch)
  master
$ head -n 4 modernizr.js 
/*!
 * Modernizr v1.6
 * http://www.modernizr.com
 *

ちょっと長いですが、ブランチを作らずにタグをチェックアウトすると、注意文が表示されました。どうやら'detached HEAD'という状態になるらしく、その扱いについての説明のようです。

You can look around (v1.6タグの内容を)見てまわれる
make experimental changes and commit them 実験的な変更が出来、コミットも出来る
you can discard any commits you make in this state without impacting any branches by performing another checkout 別のブランチをチェックアウトする事で、実験的なコミットを無かった事に出来る

'detached HEAD'ステートだと、*2こういうことが出来るようです。

$ git checkout -b new_branch_name

そして、'detached HEAD'ステートで実験的にやったコミットを、やっぱり残したい場合は、このコマンドでブランチを作る事で残せるようです。下記で実際に試してみました。

$ echo 'foo' > modernizr.js
$ head -n 4 modernizr.js 
foo
$ git commit -am 'put foo'
[detached HEAD 687ffdc] put foo
 1 files changed, 1 insertions(+), 892 deletions(-)
 rewrite modernizr.js (100%)
$ git checkout -b foo
Switched to a new branch 'foo'
$ git branch
* foo
  master
$ head -n 4 modernizr.js 
foo
$ git checkout master
Switched to branch 'master'
$ head -n 4 modernizr.js 
/*!
 * Modernizr v1.7
 * http://www.modernizr.com
 *
$ git checkout foo
Switched to branch 'foo'
$ head -n 4 modernizr.js 
foo

こんな感じで'detached HEAD'でのコミットをfooブランチに残せました。

環境

Mac Mac OS X 10.5.8(Leopard
git 1.7.3.5

*1:他にも問題になったり?

*2:英文を読み間違えてなければ