新しいマシンに Homebrew をクリーンインストールした後、最初の brew update が失敗して困ったけど、git reset で解決できた、という話。

最初の brew update が失敗するまで

2011年 5月10日 火曜日 01時24分05秒 JST 現在、以下で再現した。

Homebrew をインストールする。

$ mkdir foo
$ cd foo
$ curl -LsSf https://github.com/mxcl/homebrew/tarball/master | /usr/bin/tar xvz --strip 1
x .gitignore
x Library/
...
x share/man/man1/brew.1

git を入れる(path が通っている場所に git があるなら、ここは飛ばして mkdir Cellar するだけで良い)。

$ ./bin/brew install git
==> Downloading http://kernel.org/pub/software/scm/git/git-1.7.5.1.tar.bz2
...

brew update すると失敗する。

$ ./bin/brew update

Initialized empty Git repository in /Users/nulll/foo/.git/
remote: Counting objects: 36669, done.
remote: Compressing objects: 100% (15870/15870), done.
remote: Total 36669 (delta 21633), reused 33578 (delta 20229)
Receiving objects: 100% (36669/36669), 4.98 MiB | 1.02 MiB/s, done.
Resolving deltas: 100% (21633/21633), done.
From http://github.com/mxcl/homebrew
 * branch            master     -> FETCH_HEAD
error: Untracked working tree file '.gitignore' would be overwritten by merge.

Error: Failed while executing git pull http://github.com/mxcl/homebrew.git master

解決法

適当に検索したら https://github.com/mxcl/homebrew/issues/5128 にたどりついた。色々と書いてあるが、具体的な解決法としては https://github.com/mxcl/homebrew/issues/5128#issuecomment-1111364

$ cd `brew --prefix`
$ git remote add origin https://github.com/mxcl/homebrew.git
$ git fetch origin
$ git reset --hard origin/master

とするか、あるいは

$ cd `brew --prefix`
$ git fetch https://github.com/mxcl/homebrew.git
$ git reset --hard FETCH_HEAD

とする、と書いてある。

が、最初の brew update で失敗した場合は Homebrew を入れたディレクトリ(上記例だと foo)に移動した後

$ git reset

として brew update すると

$ ./bin/brew update
From http://github.com/mxcl/homebrew
 * branch            master     -> FETCH_HEAD
Already up-to-date.

というように、上手くいったっぽい感じになった。

なんで git reset するだけで良かったのか

Homebrew を入れたディレクトリを $HOMEBREW として、$HOMEBRREW/Library/Homebrew/cmd/update.rb を見ると、最初の brew update のときは

$ cd `brew --prefix`
$ git init
$ git pull http://github.com/mxcl/homebrew.git master

が実行されることになる。pull は fetch + merge であるということを思い出しつつ、もう一度 brew update が失敗したときの出力を見ると

$ ./bin/brew update

Initialized empty Git repository in /Users/nulll/foo/.git/
remote: Counting objects: 36669, done.
remote: Compressing objects: 100% (15870/15870), done.
remote: Total 36669 (delta 21633), reused 33578 (delta 20229)
Receiving objects: 100% (36669/36669), 4.98 MiB | 1.02 MiB/s, done.
Resolving deltas: 100% (21633/21633), done.
From http://github.com/mxcl/homebrew
 * branch            master     -> FETCH_HEAD
error: Untracked working tree file '.gitignore' would be overwritten by merge.

Error: Failed while executing git pull http://github.com/mxcl/homebrew.git master

init して、リモートリポジトリの master ブランチ(HEAD として FETCH_HEAD を指している)を fetch したけど merge が失敗した、書いてある(ように見える)。ここで git reset すると、commit が指定されていないのでデフォルトの HEAD が選択されたことになり、さらにデフォルト操作の --mixed により、index だけが HEAD の内容に書き換えられる(戻される?)ことになる。git init した直後で working tree は何も変更されていないので、結果として FETCH_HEAD と同じ状態になり、上手くいったっぽい感じになった、……という解釈でいいんだろうか?

まとめ

ぎっと、ちょうむずかしい。