Google Codeのgitとnon-fast-forwardエラー

Mandarine-wp7ではリポジトリにgitを選択している。
svnがgitになってもやることは変わらなくて、最初はローカルにあるファイルをGoogle Codeのサーバにアップするが、gitの場合は既にローカル側にリポジトリがあることが殆どなので、まずはこれをリモートにプッシュする。

その時のプッシュは全く問題無く終わったのだが、その後幾つかのファイルを修正して追加でコミットし、その後再度プッシュした時に問題は発生した。

>git push 
To https://〜.git
! [rejected] master -> master (non-fast forward)
error: failed to push some refs to 'https://〜.git'
To prevent you from losing history, non-fast-forward updates were rejected
Merge the remote changes before pushing again.  See the 'non-fast-forward'
section of 'git push --help' for details.

何度プッシュしてもこのメッセージが出てリモートにコミットが反映されない。そもそも"non-fast forward"ってなんだろう。と調べてみたのだが「プッシュ先のコミットの子孫では無い」とされた場合にこのエラーが出てしまうらしい。つまりは自分以外が既に修正している、ということ。しかし、そもそも最初にプッシュした以外は何もしていないしんだけどなぁ。

と調べていたところ、気になる記述をいくつか見つけた。

個人で使っている場合でもcommit --amendを行った後にpushを実行すると歴史が失われるためnon-fast-forwardが発生する。
Git - 個人的なメモのページ PukiWiki plus!

最後の部分、--amend でコミットしたせいでリモートの情報とローカルの情報が 食い違ってしまっていて、そのままだと push させてくれない。
ソフトウェア/rails/言語ネゴシエーション/github を使った公開 - takeuchi@ShigekawaLab

なるほど、下手に"git commit --amend"を使ってしまうとプッシュ済みのリモートとローカルのコミット済みの情報に差異が出てしまうため、以降普通にプッシュできなくなるらしい。なるほど、私も確かに"commit --amend"をしたのだ。

解決方法としては

    • 作業用にブランチを作ってそちらにプッシュし、その後masterとマージする
    • git push --forceで強制的に上書きする (その後コンフリクトが発生するが無視してプッシュする)
    • git pull origin masterでローカル側を一旦合わせて再度修正する

等があるが今回はまだブランチは実質無いし、作成して日が浅いので強制的にプッシュすることで済ませてしまった。今後同じケースを発生させないためにも、"--amend"オプションはできるだけ使わないほうが良さそうだ。