patch コマンドは、diff コマンドで作成した差分ファイル(パッチファイル)を適用し、元のファイルを更新するための Linux コマンドです。
ソースコードの修正配布、バグ修正パッチの適用、設定ファイルの差分管理などに広く利用されます。
パッチファイルとは
パッチファイルとは、ファイルの変更前後の差分を記録したテキストファイルです。diff コマンドで生成され、.patch や .diff という拡張子が使われることが多いです。
パッチファイルの中身は次のような形式です(unified diff 形式):
--- old.txt 2024-01-01 00:00:00
+++ new.txt 2024-01-02 00:00:00
@@ -1,3 +1,3 @@
line1
-old line2
+new line2
line3
---が変更前のファイル、+++が変更後のファイルを表す-で始まる行が削除された行、+で始まる行が追加された行@@で囲まれた部分は変更箇所の位置情報(ハンク)
diff と patch の関係
diff と patch はペアで使うコマンドです。
diff:2つのファイルを比較して差分ファイルを作成するpatch:差分ファイルを元のファイルに適用する
典型的な流れは次のとおりです:
# 1. diff でパッチファイルを作成
diff -u old.txt new.txt > change.patch
# 2. patch でパッチを適用
patch < change.patch
構文(Syntax)
patch [オプション] [元ファイル [パッチファイル]]
基本の使い方
標準入力からパッチを適用する
最もシンプルな使い方は、パッチファイルをリダイレクトで渡す方法です。パッチファイル内にファイル名が含まれているため、対象ファイルを指定しなくても自動的に適用されます。
patch < change.patch
対象ファイルを明示して適用する
patch original.txt < change.patch
パッチファイルを -i で指定する
patch -i change.patch
diff でパッチファイルを作成する
patch コマンドで使えるパッチファイルは、diff -u(unified diff 形式)で作成します。
ファイル単位のパッチを作成する
diff -u old.txt new.txt > change.patch
-u:unified diff 形式で出力(patch との相性が良い)
ディレクトリ単位のパッチを作成して適用する
複数のファイルにまたがる変更をまとめてパッチにするには、diff -r でディレクトリごと比較します。
# パッチファイルを作成
diff -ur old_dir new_dir > change.patch
# パッチを適用(-p1 でパスの先頭を除去)
patch -p1 < change.patch
-r:ディレクトリを再帰的に比較- ディレクトリの差分を適用する場合は
-p1を付けるのが一般的(後述)
-p オプションの意味(-p0 と -p1 の違い)
-pN オプションは、パッチファイル内のファイルパスの先頭から N 階層分を無視して適用します。このオプションは最もよく使われるオプションの1つで、ディレクトリ構造の違いを吸収するために使います。
パッチファイル内のパスが a/src/main.c の場合:
| オプション | 使用するパス | 説明 |
|---|---|---|
-p0 | a/src/main.c | パスをそのまま使用 |
-p1 | src/main.c | 先頭の a/ を除去(最も一般的) |
-p2 | main.c | 先頭 2 階層を除去 |
git diff や diff -u old_dir new_dir で作ったパッチは先頭に a/ や b/ が付くため、通常は -p1 を指定します。
主なオプション一覧
| オプション | 説明 | 使用例 |
|---|---|---|
| (なし) | 標準入力からパッチを適用 | patch < fix.diff |
-pN | パスの先頭から N 階層を無視して適用 | patch -p1 < fix.diff |
-i FILE | 指定したパッチファイルを使用 | patch -i fix.diff |
-R | パッチを逆に適用(元に戻す) | patch -R < fix.diff |
-b | 元ファイルのバックアップを作成 | patch -b < fix.diff |
--dry-run | 実際には変更せずに適用可否を確認 | patch --dry-run < fix.diff |
-N | すでに適用済みの変更を無視 | patch -N < fix.diff |
-d DIR | 指定ディレクトリに移動して実行 | patch -d src -p1 < fix.diff |
適用前に確認する(–dry-run)
--dry-run オプションを使うと、実際にファイルを変更せずにパッチが適用できるかどうかを確認できます。本番適用前のテストとして使うと安全です。
patch --dry-run -p1 < change.patch
問題なく適用できる場合は次のように表示されます:
checking file src/main.c
パッチ適用を取り消す(patch -R)
-R(--reverse)オプションを使うと、適用済みのパッチを逆に適用して元の状態に戻すことができます。
patch -R -p1 < change.patch
同じパッチファイルを使うため、保管しておく必要があります。
バックアップを作成して適用する
patch -b < fix.diff
適用後、元ファイルは filename.orig という名前で残ります。重要なファイルには -b を付けておくと安全です。
適用に失敗した場合(.rej ファイル)
パッチの適用が失敗すると、.rej ファイルが生成されます。このファイルには適用できなかった差分(リジェクト)が記録されています。
Hunk #1 FAILED at 42.
1 out of 1 hunk FAILED -- saving rejects to file main.c.rej
main.c.rej を参照して手動でマージする必要があります。対処方法:
.rejファイルを開き、適用できなかった差分を確認する- 対象ファイルと
.rejファイルを見比べて手動で変更を反映する - 作業完了後、
.rejファイルを削除する
Git のパッチ適用との違い
Git 管理下のプロジェクトでは、patch コマンドの代わりに Git のコマンドを使う選択肢もあります。
| コマンド | 特徴 |
|---|---|
patch -p1 < file.patch | Git に依存しない汎用的なパッチ適用 |
git apply file.patch | Git インデックスに適用。Git 管理下での標準的な方法 |
git am file.patch | メールボックス形式(git format-patch で作成)のパッチをコミットとして取り込む |
diff -uで作ったパッチ →patchコマンドやgit applyで適用git format-patchで作ったパッチ →git amで適用(コミット情報も保持される)
よくある失敗例
-p の指定を間違える
パッチファイルのパスと実際のファイル位置のズレが原因です。エラーメッセージで対象ファイルが見つからないと表示されたら -p の数値を変えて試してください。
# パッチ内のパスが a/src/main.c の場合
patch -p1 < change.patch # ○ src/main.c に適用
patch -p0 < change.patch # × a/src/main.c を探してしまう
対象ファイルの内容が変わっていて適用できない
パッチを作成した時点と現在のファイル内容が異なる場合、行番号やコンテキストが合わずに失敗します。.rej ファイルを確認して手動でマージしてください。
カレントディレクトリが違う
パッチを適用するディレクトリが違うと、ファイルが見つからないエラーになります。-d DIR でディレクトリを指定するか、正しいディレクトリに移動してから実行してください。
patch -d /path/to/project -p1 < change.patch
改行コードの違いで失敗する
Windows(CRLF)と Linux(LF)の改行コードの違いでパッチが当たらないことがあります。dos2unix コマンドで改行コードを統一してから適用してください。
dos2unix change.patch
patch -p1 < change.patch
よくある疑問
patch は何をするコマンドか
diff コマンドで生成した差分ファイル(パッチファイル)を、元のファイルに適用して変更を反映するコマンドです。ソースコードの修正配布やバグ修正に使われます。
diff と patch はどう使い分けるか
diff で差分を作り、patch で適用するという役割分担です。変更を作る人が diff でパッチファイルを作成し、受け取った人が patch で適用するという流れが一般的です。
-p1 は何を意味するか
パッチファイル内のファイルパスから先頭 1 階層を取り除いて適用することを意味します。git diff や diff -ur で作ったパッチは先頭に a/ が付くため、-p1 を指定すると正しいパスで適用できます。
適用前にテストするにはどうするか
--dry-run オプションを使います。実際にファイルは変更されず、適用できるかどうかだけを確認できます。
patch --dry-run -p1 < change.patch
適用したパッチを戻すにはどうするか
-R オプション(逆適用)を使います。同じパッチファイルを使って元の状態に戻せます。
patch -R -p1 < change.patch
関連コマンド
diff:ファイルやディレクトリの差分を生成git apply:Git 管理下でパッチを適用git am:メールボックス形式のパッチをコミットとして取り込むgit diff:Git における差分生成cmp:2つのファイルをバイト単位で比較
参考
- manページ: man7.org patch(1)
- GNU patch: https://www.gnu.org/software/diffutils/manual/patch.html

コメント