本文へスキップ
AZ Tools

パッチ / diff 検査ツール

統合 diff を貼り付けるか、git format-patch や GitHub の .patch URL、メーリングリストから受け取った .patch ファイルを開くと、適用する前にそれが何をするのかを示します。メールヘッダーを持つパッチならコミットの件名・作成者・日付を読み、続いてファイルごとの表を作ります。パスと、そのファイルが追加・削除・変更・リネーム・モード変更・バイナリのどれか、そして git が数えるのと同じやり方で数えた追加行数と削除行数です。中心になるのは、実際に知りたい問い——これはきれいに適用できるのか——に答える部分です。統合 diff は自己記述的です。すべてのハンクヘッダーが @@ -1,4 +1,5 @@ のように両側で何行を覆うかを述べ、git は何かに触れる前に本体がその宣言と合っているかを確かめます。二つが食い違うと——メールクライアントが行を折り返した、誰かが手で編集した、文脈行の先頭の空白が転送中に失われた——git は `corrupt patch at line N` とだけ言い、何を期待していたのかは教えません。このツールは同じ計算をして、問題のハンクと、ヘッダーが約束した値と、本体が実際に持つ値を並べて見せます。より静かな失敗も示します。LF のファイルと合わない CRLF の改行、pre-commit フックが拒む末尾の空白、欠けた末尾改行、ハンクが一つもないファイルヘッダーです。すべてブラウザー内で動作し、パッチは送信されません。

2 ファイル変更+4 行追加−1 行削除2 ハンク
パス変更追加削除ハンク
src/app.js変更+2−11
README.md追加+21

使い方

  1. 統合 diff を枠に貼り付けるか、.patch や .diff ファイルをドロップします。
  2. 合計を見て変更の規模を把握します。ファイル数、追加行、削除行、ハンク数です。
  3. 表から目的のファイルを探します。リネームされたファイルは新しいパスの横に元のパスが出ます。
  4. git apply を実行する前にオレンジ色の項目を確認してください。失敗する理由がそこにあります。
  5. メールで届いたパッチなら、ハンクの警告を `git apply --check` の結果と比べてください。同じ破損をより短く報告します。

よくある質問

`corrupt patch at line N` は具体的に何を意味しますか。
ハンクの本体が、ヘッダーの宣言した行数と一致しなかったという意味です。@@ -1,4 +1,5 @@ のようなヘッダーは旧側に 4 行(文脈+削除)、新側に 5 行(文脈+追加)を約束します。git は読みながら数え、計算が破綻した瞬間に止まり、誤っていたヘッダーではなく到達した行番号を報告します。原因はほぼ常に転送です。メールクライアントが長い行を折り返した、あるいは文脈行を示す先頭の空白 1 個を削ったために片側が足りなくなったのです。このツールは該当のハンクと、約束された値、実際に届いた値を示すので、たいていは手で直せます。
空の文脈行がなぜこれほど頻繁にパッチを壊すのですか。
文脈行は先頭の空白 1 個で示されるため、変更のない空行は「空白 1 個だけの行」になるからです。それは目に見えず、非常に多くのツールが取り除きます。保存時に末尾空白を削るエディター、メールクライアント、チャットアプリ、端末を経由したコピー&ペーストなどです。空白が消えるとその行は文脈ではなく空行として読まれ、ハンクは両側とも 1 行足りなくなります。画面上は問題なく見えたパッチが適用できなくなる、最もよくある経路です。
このツールはパッチを適用したり、手元のファイルと照合したりしますか。
しませんし、できません。読むのはパッチ自体——diff の中の計算だけで、対象のファイルには一切アクセスしません。それでも壊れたパッチは捕まえられます。それはパッチ単体の性質だからです。ただし文脈行があなたの作業ツリーと一致するかは分からないので、このツールが正常と言ったパッチでも、ファイルが先に進んでいれば `does not apply` で拒否され得ます。その確認にはファイルが必要で、コマンドは `git apply --check` です。
git のパッチだけでなく素の `diff -u` の出力も読めますか。
読めます。git のパッチには `diff --git` 行、index 行、リネームやモードの情報が付き、format-patch ならメールヘッダーも付きますが、あればすべて読みます。diff -u が出す素の統合 diff にはそれらがなく、いきなり `--- ` / `+++ ` のヘッダー対から始まりますが、同じように扱います。ただしリネームとモード変更は素の形式では検出できません。形式にそれを表す手段がないからです。
ここの行数が GitHub の表示と違うのはなぜですか。
GitHub も同じ行を数えますが、要約が異なることがあります。生成ファイルを隠し、大きな diff を折りたたみ、バイナリファイルを合計から除くからです。このツールは渡されたパッチ内のすべてのハンクを数え、その値は `git apply --numstat` が報告する値と同じです。合計が違うなら、手元のパッチが変更の全体かどうかを確かめてください。コミット 1 個分の .patch URL は、プルリクエストの累積 diff とは一致しません。
パッチはどこかに送信されますか。
いいえ。テキストはこのページの JavaScript が解析し、どこにも送りません。ドロップしたファイルも同じで、ブラウザーのファイル API で読みます。ページを開いてからネットワークを切り、diff を貼り付けてみれば、そのまま動くことで確かめられます。知っておく価値があります。パッチはレビューの過程で最も機微な物であることが多く、未公開のコードをそのまま含んでいるからです。

関連ツール