Linuxのpatchコマンドとは?diffで作ったパッチファイルの適用方法を解説

コマンドリファレンス

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 の関係

diffpatch はペアで使うコマンドです。

  • 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 の場合:

オプション使用するパス説明
-p0a/src/main.cパスをそのまま使用
-p1src/main.c先頭の a/ を除去(最も一般的)
-p2main.c先頭 2 階層を除去

git diffdiff -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.patchGit に依存しない汎用的なパッチ適用
git apply file.patchGit インデックスに適用。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 diffdiff -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つのファイルをバイト単位で比較

参考

Bash玄

はじめまして!Bash玄です。

エンジニアとしてシステム運用に携わる中で、手作業の多さに限界を感じ、Bashスクリプトを活用して業務を効率化したのがきっかけで、この道に入りました。「手作業は負け」「スクリプトはシンプルに」をモットーに、誰でも実践できるBashスクリプトの書き方を発信しています。

このサイトでは、Bashの基礎から実践的なスクリプト作成まで、初心者でもわかりやすく解説しています。少しでも「Bashって便利だな」と思ってもらえたら嬉しいです!

# 好きなこと
- シンプルなコードを書くこと
- コマンドラインを快適にカスタマイズすること
- 自動化で時間を生み出すこと

# このサイトを読んでほしい人
- Bashに興味があるけど、何から始めればいいかわからない人
- 定型業務を自動化したい人
- 効率よくターミナルを使いこなしたい人

Bashの世界に一歩踏み出して、一緒に「Bash道」を極めていきましょう!

Bash玄をフォローする

コメント