send patches with git commands

まとめ。といっても 1.6 系列は使ったことないので 1.5.2.5 ( Ubuntu 7.10 gutsy で apt-get から install できる最新 package 。ちなみに pacakage 名は "git-email" ) の場合なんだけど、最新 ( 今のところ 1.6.1.3 ) でも使う option が多少変わるだけで ( format-patch に --cover-letter 指定して添え状を作ったり各 patch の説明を書くのに send-email に --annotate 指定をしたりするらしい ) おおまかな流れは変わらない。あとここで示した方法は一般的というか、こうしたほうが望ましいと思われることをまとめているだけなので project による別途指定がある場合はそっちに従うべき。

まず以下の流れで進むということで。

  1. いくつか commit する。
  2. git format-patch で patch を作る。
  3. git send-email する。

以下 format-patch と send-email について個別に説明。実際投げる際の command については別 entry ( http://d.hatena.ne.jp/janus_wel/20090211/1234442344 ) に。

  • format-patch
    • mail として送ることが出来る形 ( mail header ついただけ ) で diff を出力する。
    • git format-patch --numbered <committish>
    • 上記の command をうつと "<number>-<summary>.patch" という名前で commit の数だけ patch file が出力される。 <number> は 4 桁の整数、 <summary> は commit message の最初の 1 行。
    • <committish> には sha1 hash での指定や "origin/master" みたいな tag での指定、 "HEAD^^" のような相対指定の他に "-3" のように現在の branch HEAD からいくつ前の commit との差を取るのかという指定できる。
    • --numbered は "[PATCH n/N]" っていう文字列を Subject の最初につけるためのもの ( 通常は "[PATCH]" のみ ) 。好みが分かれるとは思うけどおれは 1 つしか patch がない場合でも --numbered をつけるべきと思う。このほうがわかりやすいし。
    • で、 format-patch に関しては上記の command だけ覚えておけばほとんど問題ない。出力される patch 群を MUA ( mail user agent ) がひとつの thread として扱うようにさせる --thread っていう option も指定できるんだけど、ここらへんは後述する send-email で指定したほうが柔軟に出来るのであまり意味ない。
    • あと patch 送るのには関係ないけど --stdout ( ファイルを作らせずにどんな形で出力されるか確認する ) や --start-number ( 振られる番号を自分が管理しやすいように変更する ) 、 --quiet ( shell script なんかで変更があったか check する際に使う ) あたりを知っておけばいいんでないかな。まぁ詳細は man git-format-patch ということで。
  • send-email 基本
    • git send-email <patchfile>
    • 上記の command をうつと mail を送るために必要な最低限の情報指定をするように対話 prompt で促される。途中でやめるには Ctrl+C 。 default を指定する際は何も入力せずに Enter のみを押す。
      1. From ( 送り主の名前と mail address ) の指定。 default は git var -l で確認できる GIT_COMMITER_IDENT という値 ( たぶん git config で指定した user.name と user.email をつなげただけのもの ) 。
      2. To ( 送り先 ) 。省略しても意味ないと思うんだけど省略できる。 default はなし。
      3. In-Reply-To ( どの mail に対しての返信かを指定する ) に設定する Message-ID の指定。これは返信したい mail の header に書いてあるはず。 < と > が入っていてもかまわない ( 本来そういうもん ? ) みたいなので copy & paste が楽。最初に何か patch を送るときはなしにして返信にしない ( default はなし ) 。
    • 上記のように対話 prompt で指定するのが面倒な場合それぞれ --from 、 --to 、 --in-reply-to で代用できる。 To は対話 prompt だと間違えても修正しづらいので command をうつときに --to で指定した方が気が楽。あと In-Reply-To がでるのがめんどくさいけど何らかの返信にしたくない場合には git send-email --in-reply-to "" とするのがいい。ちなみに Message-ID の確認方法は Thunderbird の場合以下のような感じ。
    • 対話形式での入力が終わるとすぐに送信される。その際送られるのは patch のみなので続けて捕捉説明の mail を投げるとか、先に「こういう patch 書いたんだけど投げるよ ? 」的な mail を投げておいてその返信として ( In-Reply-To に先に投げた mail の Message-ID を指定する ) 投げるといい。
  • patch の説明を一緒に書いて投げたい場合
    • git send-email --compose *.patch
    • --compose を指定すると patch についての説明を一緒に書ける。最初に説明用の mail が投げられて patch はそれに対しての返信という形になる。ついでに対話 prompt での入力に説明用 mail の Subject ( タイトル・題名 ) の指定が加わる。対話 prompt がいやな場合は --subject で指定可能 ( To 同様間違えると修正が面倒なので --subject 指定を使った方がいいかも ) 。
    • 対話 prompt での入力が終了したあとに editor が起ち上がるのでそこに patch の説明を書く。このときの editor は環境変数や git config で指定可能なので man git-send-email とかで確認するとよさげ。ちなみにうちの環境だと default は vi だった。で、 editor が起ち上がったら From や Subject のあとに "GIT: " ではじまる行がいくつか続いたものがあると思うのでそのしたにいろいろ書く。以下の例はテケトー英語です。
    • 保存して editor を閉じると送っていいかどうか聞かれるのでよい場合は y 。ここでやめた場合は editor で書いた説明が消滅するので注意。
  • send-email 注意点
    • 複数の patch を投げる際には --no-chain-reply-to を指定したほうがいいかもしれない。というのも default では --chain-reply-to が指定されていて複数の mail を送る際にそれぞれの mail はひとつ前に送った mail に対しての返信ということになるんだけど、このときに複数 patch を送ったり --compose 指定したりすると以下のように nest が深くなってしまうのでちょっとウザい。
    • これを避けるのに --no-chain-reply-to を使う。 git send-email --compose --no-chain-reply-to *.patch とすると以下のように patch が並んでくれる。