日に何度もある更新作業にpatchを使う

テストフェーズでの不具合修正のリリースがとにかく面倒くさくなってきたので、patchコマンドを活用してみためもめも。

日々の作業

日々の作業はこんな感じ。

  1. 不具合を修正する。
  2. 修正したファイルをアーカイブしてサーバに持っていく。
  3. 更新ファイルのバックアップを取る。
  4. 念のため差分を確認してから上書き反映。
  5. (ここで待ったがかかる or 戻してって言われる。)
  6. (前のファイルに戻す。)


イケてる職場だとデプロイツールとかで一発だったりするんだろうけど、サーバ上で操作できることが制限されてるのでそうはいかない。
ファイルを固めては多段sshを乗り越えて持っていって差分を確認しつつ反映、という実際に何度もやるとなるとクソ面倒くさい作業をしている。
ファイル数が多いとバックアップを取ったり差分を確認するだけでも大変だしミスも増えてくる。

patchコマンドを使った改善

みんなこういう作業をやってるんだけど、自分は3回ぐらいでもう気が狂いそうなほど耐えられなくなったので、なんとか上手いことやれないか、と考えたのが以下の方法。

  1. 修正内容のパッチファイルを作る(git diffとかで)。
  2. パッチファイルをサーバに持っていく。
  3. patch --dry-runで適用確認。
  4. patchを適用。
  5. 戻せって言われたらpatch -Rで戻す。


別に画期的な方法でもなんでもなくてむしろ昔ながらの方法なんだけど、これだと必要なファイルも1つで済むし、コマンド一発で適用/逆適用ができるので作業が格段に楽になる。ミスも減る。
サーバだけ設定ファイルの一部が書き換えてある、みたいな状況でもうっかりファイル全体を上書きしたりせず該当箇所だけパッチできるのでトラブルも減る。


具体的にはこんな感じ。

git checkout -b issue_123

    ... edit ... commit ...

git diff --no-prefix master >issue_123.patch

こうしてパッチを作り*1、サーバに持っていって、

cd 反映先のルート
patch -p0 --dry-run <issue_123.patch    # --dry-runで確認
patch -p0 <issue_123.patch              # 問題なさそうなら反映

こんな感じで反映する。
戻せーって言われたら、

cd 反映先のルート
patch -p0 -R --dry-run <issue_123.patch    # --dry-runで確認
patch -p0 -R <issue_123.patch              # 問題なさそうなら反映

こんな感じで戻す。
-Rは(間違って作って)新旧が逆になってるパッチを当てるためにあるっぽいんだけど、まぁ元に戻したいのでこれでいいかなと。


不具合の調査とかで一時的にログを増やしたりコードを変更したい場合なんかも、こうやってpatch一発で切り替えられるようにするとよい。
あ、gitのところはお使いのVCSツールに読み替えてください。diff -Naurとかでもいいけど。


一点注意が必要なのはpatchをどこで適用するか、patchファイル内のパス、-pとは何か、というのをちゃんと知ってないと上手くパッチを当てられなくてハマるところかな。
このへん初めてだと難しいよね。

まとめ

とにかくこの方法にすると、

  • 対象ファイルが複数でも1ファイルで管理できる。
  • コマンド一発で全部反映できる。
  • バックアップしてなくてもパッチの逆適用で一発で戻せる。
  • 少しぐらいファイルの内容が違ってても空気を読んでくれる。

と作業が格段に楽になる。
もうcp -rとかdiffとかガチャガチャやって作業ミスすることもなくなる。

ところで自分の場合は

実は上の通りのコマンドは使ってなくて普段はこんな感じ。

git diff master >issue_123.patch

patch -d 反映先ルート -p1 -i issue_123.patch --dry-run
patch -d 反映先ルート -p1 -i issue_123.patch

patch -d 反映先ルート -p1 -i issue_123.patch -R --dry-run
patch -d 反映先ルート -p1 -i issue_123.patch -R

理由は--no-prefixとかつけるの面倒くさいし、-p1のほうが慣れてるから。
-dは場所を間違わないために明示的に指定しておく。
--dry-runとか-Rを付けたり削ったりはコマンドラインの最後のほうが編集しやすいから、リダイレクトではなく-iを使う感じ。

あわせて学びたい

  • diffコマンド
  • patchutils

*1:パッチの作り方はキミ次第!