home ホーム search 検索 -  login ログイン  | reload edit datainfo version cmd icon diff delete  | help ヘルプ

技術/UNIX/patch

技術/UNIX/patch

技術 / UNIX / patch
id: 490 所有者: msakamoto-sf    作成日: 2009-11-19 16:00:31
カテゴリ: Linux UNIX シェルスクリプト 

細かいところとかが結構「あれれ?」となりやすいので、patchの使い方を今一度自分用にメモ。

基本

patchコマンドはカレントディレクトリのソースツリーに対して処理する。

patch < patchfile
# タブやスペースマッチの条件を緩めにする
patch -l < patchfile
# パッチ適用ファイルに対して".orig"拡張子をつけてバックアップする。
patch -b < patchfile

"-b"によるバックアップファイルの拡張子を変更するには・・・

GNUの場合:
patch -b -z .bk < patchfile
FreeBSDの場合:
patch -b .bk < patchfile

"-d ディレクトリ名"を指定すると、そのディレクトリに移動してから処理が始まる。

(個人的に)一番重要なオプション "-pNum" + "--dry-run"/"-C or --check"

patchを実行する前に、「何が行われるのか確認だけしたい」場合は以下のオプションを使う。

GNUの場合:
patch ... --dry-run ... < patchfile
FreeBSDの場合:(-C or --check)
patch ... -C ... < patchfile

patchを実行する時に個人的に極めて重要だと考えているオプションが "-pNum" オプションである。
"-pNum"を使うと、patchfileで見つかったファイル名それぞれについてNum個のスラッシュとその間のディレクトリ名を除去する。

patchfile中のファイル名が

proj-0.0.1/src/foo/bar/main.c

であったとすると、以下のように調整される。

  • "-p" 指定無し : カレントディレクトリ中のファイル、すなわち "`pwd`/main.c" が適用対象となる。
  • "-p0" or "-p" 指定時 : パス名は変更されない。"`pwd`/proj-0.0.1/src/foo/bar/main.c"が適用対象となる。
  • "-p1" 指定時 : 最初の"/"とその間のディレクトリ名が除去されるので、"proj-0.0.1/"が除去される。従って "`pwd`/src/foo/bar/main.c" が適用対象となる。
  • "-p2" 指定時 : 2番目の"/"とその間のディレクトリ名が除去されるので、"proj-0.0.1/src/"が除去される。従って "`pwd`/foo/bar/main.c" が適用対象となる。

個人的な経験として、Linuxに触りだした当時、雑誌記事を見つつソースコードを弄っていた時"-p"オプションの意味を知らずにpatchを無理矢理あててしまい、ソースコードがぐちゃぐちゃになってしまった事がある。
patchファイルを作成した人の環境と、自分の環境は必ず異なるので、"--dry-run/-C/--check"を活用して丁寧に確認してからpatchを適用するよう心がけたい。

"-R"によるロールバック

"-R"は本来の意味としては「patchfileの中の新旧が逆でした~」というpatchを当てたい時に使う。
しかし見方を変えれば、旧→新で作られた正常なpatchfileを「新→旧へのロールバック用patch」として処理する事を意味する。
従って、パッチ適用後にパッチに間違いが発見され、ロールバックしたい場合は、適用時のオプションに "-R" を加えるだけで適用前の状態にロールバックできる。

$ patch -p1 < foobar.patch
↓ロールバックしたい・・・
$ patch -p1 -R < foobar.patch

なお、ed形式のpatchファイルについては必要な情報が不足している為、"-R"オプションは使えない。

より良いpatchファイルを作成するには

Linux jman, FreeBSDのmanページ共に「パッチを送る人への注意」「パッチ作成者への注意」という項目があり、参考になる。

  1. "patchlevel.h"というファイルを必ず更新するようにしておくと、今どのpatchlevelが当たっているのか分かりやすい。(ソースコード管理ツールが普及した今でも通用するのかな?)
  2. "diff -uNr dir_old dir_new"などで、"dir_old"や"dir_new"にスラッシュを含めない。("-p"でのずれや混乱をなるべく抑える)
  3. 上記に関連して、"-pNum"の調整が必要な場合は、ユーザーにきちんとアナウンスする。
  4. さらに関連して、"-pNum"の調整をユーザーにお願いする場合は、diffする時のディレクトリ階層を合わせておく事。"diff foo/bar/baz/main.c baz/main.c"のようにしてしまうと"-pNum"が上手く動かなくなってしまう為。
  5. 日付については世界協定時を用いてdiffするとよい。"LC_ALL=C TZ=UTC0 diff..."とするとよい。
  6. 新規ファイルの作成や、ファイル削除については "diff -N"オプションを使ってpatchファイルを作成すると良い。
  7. リバースパッチを送らないよう注意しよう!
  8. 適当な大きさに分割する事。


プレーンテキスト形式でダウンロード
現在のバージョン : 1
更新者: msakamoto-sf
更新日: 2009-11-20 17:18:02
md5:5d28a472f55287d3cb4db18034b37867
sha1:7fe56699b2529baca74f64c8985d1224c2d86763
コメント
コメントを投稿するにはログインして下さい。