普通のpatchコマンドで取り込めるdiffファイルをgitで作成する

まとめ

$ git diff --no-prefix HEAD~ > thisis.patch
$ patch --dry-run -p0 < thisis.patch
$ patch -p0 < thisis.patch

git diff--no-prefixをつける事で、普通のpatchで当てられるパッチファイルを出力できます。この例ではHEADの1個前*1からHEAD*2までのパッチです。
普通のpatchコマンドのほうの知識があまり無くて-p0がいまいちよく分からないんですが、git diff --no-prefixで作成したパッチファイルを当てるには必要みたいです。--dry-runは、実際には当てないけど当てた場合の結果を出力します。なので、まずは--dry-runで確認して、問題が無ければ実際にパッチを当てます。

エントリー書いた後に教えてもらった補足

patch -p1の様に-p0-p1にすれば、--no-prefixは付けなくても良いみたいです。patchコマンドに不慣れだったので言われるまで気がつかなかったんですが、言われてみればその通りでした。--no-prefixがdiff内にあるファイルパスに、1階層分のプレフィックスを付けるもので、-p1はそのファイルパスから1階層無視するものなので、そのまんまですね。@nojimageさんありがとうございました。

解説

gitにはgit format-patchというコマンドがあります。流石分散バージョン管理といった所か、git format-patchはパッチを直ぐにメール出来るようにmbox形式でパッチを生成してくれる*3らしい。そのパッチは、git send-emailgit imap-sendでメールできるようになっています。
ただ、普通のpatchコマンドでパッチを当てたい時には、mbox形式はむしろ困ったフォーマットです。一応、メールするのではなく*4パッチを当てるgit amというコマンドがあります。ただ、これが使えるのはgitで管理されてるプロジェクトだけ。
Subversionで管理してるプロジェクトに、gitで管理されてるプラグインを使うといったことがあり、プラグインの修正を取り込む必要が出てきました。本体はsvnなのでgit amは使えるはずも無く、なんとかpatchで当てられるdiffが必要でした。

-p0オプションについて

つまり、最初の "-p0" というオプションは「ディレクトリを無視しない」という意味になります。

パッチをあてる(その3:patchコマンドの-pオプションについて): 小粋空間

どうやらdiffの最初に記載されてるディレクトリパスの扱いのようです。なんとなくは分かったけど、まとめられるほど理解してないです。詳しくは上記サイトをどうぞ。

余談だけどGithubからパッチを得る方法

Githubに置いてるなら、URLにちょっと拡張子を追加するだけで、パッチファイルが保存できます。URLに.patch.diffをつける事で、それぞれgit format-patchgit diff相当で出力されます。
ただ、残念ながら.diffをつけても--no-prefixが無いgit diffなので、patchコマンド用にはなりません。
前述した追記の通り、patch -p1を使えば.diffを付けた方なら取り込めそうです。試してはないですけど。

環境

Mac Mac OS X 10.5.8(Leopard
git 1.7.3.5

*1:HEAD~

*2:例では省略

*3:使ったこと無いのでよく分からないけど

*4:もしくはメールされてきた