ですが、たいていは以下のようにします。
デフォルト動作では、オリジナルは ``.orig'' の拡張子 (長いファイル名を扱えないシステムでは ``~'') を付けてバックアップとして残した上で、 オリジナルファイルはパッチ済みのバージョンに置き換えられます。 オリジナルをバックアップする拡張子はオプション -b (--suffix), -B (--prefix) あるいは -V (--version-control) によって、あるいは環境変数 SIMPLE_BACKUP_SUFFIX によっても変更できます。 環境変数による指定はオプション指定によって上書きされます。
バックアップファイルが既に存在していた場合、 patch は新しいバックアップファイル名として、 ファイル名本体の中で最初に出てくる英小文字の部分を大文字に替えたもの を使います。 英小文字の部分がなかった場合は、ファイル名の最初の 1 文字削除したものとし、 既存のバックアップファイル名と合致しなくなるまでこれを繰り返します。
ファイルの出力先は -o (--output) で指定することができますが、 もしそこに既に同じファイル名のファイルが存在していたら、 まずバックアップが作られます。
patchfile が指定されない場合やハイフンである場合、 パッチは標準入力から読み込まれます。 -i 引数が指定された場合、標準入力の代りに、これに続くファイル名が使用されます。 -i ディレクティブは 1 度のみ使用可能です。
patch が最初に行う作業は、差分情報がどんな形式か判別することです。 これは、オプション -c (--context), -e (--ed), -n (--normal), -u (--unified) によって形式を指定することもできます。 context diff (old-style, new-style, unified) および normal diff は patch 自身によりパッチが当てられます。 ed diff だった場合は、パイプを通して単にパッチファイルをエディタ ed に入力するだけです。
patch は、差分情報の前に含まれるゴミをスキップし、差分を適用し、 そして後に含まれるゴミをスキップしようとします。 ですから差分情報が入った記事やメッセージなどをそのまま patch に与えても、うまく動作するはずです。 差分全体が一定量だけインデントされていても、 そのことを考慮のうえ処理されます。
context diff の場合、そして normal diff の場合もいくらかあてはまりますが、 patch はパッチに書かれた行番号が正しくない場合にそれを検知し、 各 hunk (パッチの各々の単位)を適用する正しい場所を見つけようと試みます。 まず hunk に書かれた行番号に対し、 前回 hunk を適用した際に用いたオフセットを加算あるいは減算します。 それが正しい場所でなければ、 patch は一定の行数だけその前後を走査し、hunk のコンテキスト(context)にマッチする行を 探します。 一番最初は、 patch はコンテキスト中の全ての行が一致する場所を探します。 一致する場所が見つからない場合、 パッチが context diff 形式であり、 しかも最大曖昧度(maximum fuzz factor)が 1 以上に設定されていれば、 コンテキストの最初と最後の行を無視して再度走査を行います。 それでも見つからない場合、 最大曖昧度が 2 以上なら、コンテキストの最初と最後の 2 行を無視して 再度走査します。 (デフォルトの最大曖昧度は 2 です) もし patch がパッチを当てる場所を見つけられなかった場合、その部分の差分情報を リジェクトファイルに出力します。リジェクトファイルは、通常、 出力ファイルに ``.rej'' の拡張子 (長いファイル名を扱えないシステムでは ``#'') を付けたものになります。 (注意: 入力パッチが context diff であっても normal diff であっても、 リジェクト部分は context diff 形式で出力されます。 入力が normal diff の場合、コンテキストの多くは単なる null になります。) このリジェクトファイルに出力される時の差分情報に付けられている行番号は、 元のパッチファイルにあるものと違ったものになっている可能性もありますが、 元のものよりは場所的により近い位置になっていると思われる行番号になります。
パッチの各 hunk が処理される毎に、そのパッチ処理が 成功した(succeeded)のか失敗した(failed)のかの別と、 patch が推定したパッチ適用行位置(新しいファイルにおける行番号) が報告されます。 この位置が差分中に示された行番号と異なる場合、 そのズレ(オフセット)も報告されます。 hunk のひとつだけが大きなオフセットで適用された場合、 それは誤った位置に適用されたことを意味する「かも」しれません。 またパッチ適用に際して曖昧度(fuzz factor)が用いられた場合も その旨報告されます。この場合は少し疑ってみるべきでしょう。
もし、オリジナルファイルがコマンドラインで指定されなかった場合、 patch は、エディットすべきファイル名を、差分情報の前に付加されているゴミの中 から見つけようとします。 context diff のヘッダの場合、ファイル名は ``***'' もしくは ``---'' で始まる行から探し、 既存ファイルに一致する最も短い名前が用いられます。 context diffには上のような行が含まれますが、 もしヘッダに ``Index:'' という行があったら patch はここから得たファイル名を使うことを試みます。 context diff ヘッダは Index 行に優先して用いられます。 もしファイル名を見つけることができなかった場合、 パッチすべきファイル名を入力するよう求めます。
もしオリジナルファイルが見つからないかリードオンリーであるけれども、 SCCS か RCS ファイルが存在する場合、 patch はそのファイルのゲットもしくはチェックアウトを試みます。
加えて、もし差分の前のゴミの中に ``Prereq: '' という行が含まれていれば、 patch はその行に必要条件 (通常はバージョン番号) が書いてあるものとみなして 最初の word を取りだし、オリジナルファイルの中に同じ word があるかどうかを 調べます。もしその word が発見できなければ、 patch は処理を実行してよいか、確認を求めるようになります。
結局のところ、ニュースリーダを使っているときに、 パッチを含んだ記事に対して
| patch -d /usr/src/local/blurfl
のように指示してやれば、blurfl ディレクトリにあるファイルに 記事から直接パッチをあてることができる、 ということです。
パッチファイルに、1 つ以上のパッチが含まれていた場合、 patch は、各々が別々のパッチファイルであるものと思って処理を実行します。 この場合、パッチを当てるべきオリジナルファイルは、今まで説明したように、 各々の差分情報の中から抽出でき、 また、各差分記述の前にあるゴミの部分を調べることで ファイル名やリビジョンレベル等の重要事項が得られる、 と仮定しています。 この他に、`+' で繋げてファイル名を並べることで、 2 番目以降のファイル名を指定することもできます (ただし、この場合でも、パッチ当てた後の新しいファイル名を 指定することはできません)。
patch には次のようなオプションがあります:
/u/howard/src/blurfl/blurfl.c
であった場合、 -p あるいは -p0 オプションを指定すると、パス名は全く修正されません。 -p1 を指定すると、最初のスラッシュがない
u/howard/src/blurfl/blurfl.c
となり、 -p4 を指定すると
blurfl/blurfl.c
、そして -p を全く指定しないと "blurfl.c" となります。 ただし、その前のパス(u/howard/src/blurfl)が相対パスとして存在する場合は別で、 その場合、パス名全体は無修正のままです。 最後に、こうして得られたファイルを、カレントディレクトリあるいは -d オプションで指定したディレクトリ内で探します。
もしパッチ中の最初の hunk が失敗すれば、 patch はそれをリバースパッチにしてうまく適用できるかどうか試します。 もしうまくいけば、 -R オプションをセットしてパッチを当てますか、と尋ねられます。 そうしないと答えれば、パッチは通常通り適用されていきます。 (注: パッチが normal diff 形式で、しかも最初のコマンドが追加 (つまり本来は削除)であると、この方法ではリバースパッチを検出できません。 空のコンテキストはどこにでもマッチするので、追加操作は常に成功してしまう からです。 幸い、発見的には、 パッチは行を削除するよりも追加あるいは修正するものがほとんどであるため、 normal diff 形式のリバースパッチは削除から始まって失敗におわることが ほとんどです。)
patch -S + -S + <patchfile
と指定すると、3 つのパッチのうち、1 番目と 2 番目のパッチを無視します。
メッセージ ``Hmm...'' は、 パッチファイル中に処理できないテキストが存在していること、 そして patch はそのテキスト中にパッチがあるかどうか、もし存在すれば どういう形式のパッチであるかを推測しようとしていることを 示しています。
ひとつでもリジェクトファイルが作成されれば、 patch は 0 でない終了ステータスで終了します。 いくつものパッチを繰り返し適用する場合は、 この終了ステータスをチェックし、 パッチが部分的にしか適用されていないファイルに対して さらなるパッチをあてないようにすべきです。
たとえ多くの類推を行わなくてはならない場合でも、 patch は通常、正しい結果を生成します。 しかし、結果が正しいと保証できるのは、 パッチを作成したのと正確に同じバージョンのファイルに対して パッチを適用した場合だけです。
コードが複製されている場合(例えば #ifdef OLDCODE ... #else ... #endif に よって)、 patch は両者にパッチをあてることができません。 そしてそこでパッチコマンドがうまくいった場合、 そのパッチはおそらく誤って適用されており、 おまけに「成功しました」と報告してきます。
既に適用済のパッチをあてると、 patch はそれをリバースパッチと考え、適用したパッチを外すかどうか尋ねてきます。 これも特徴の一つと解釈可能でしょう。