リリース直後の夜のオフィスで、モニターに映る見覚えのあるエラー画面を前に、直したはずなのにと首をかしげている保守運用の担当者

hotfixの取り込み漏れを防ぐ|緊急修正を本流に戻す手順と確認

「先月直してもらった決済の不具合、また出てるんですけど……」

金曜の夜、本番で見つかった不具合を急いで直して、なんとか週末を越えた。それから3週間後、予定どおりの機能追加をリリースしたら、あのときの不具合がそっくり戻ってきた——。画面を見て「え、直したよね?」と自分の記憶を疑う瞬間、覚えがある方も多いと思います。

これは、あなたの注意が足りなかったからではありません。緊急修正(hotfix)を当てた場所と、次のリリースを作っている場所が別々だったから起きることです。急いでいるときほど、修正は「いま動いている本番」に直接入ります。一方で、次のリリースは「開発中のコード」から作られます。開発中のコードがその修正を知らないまま本番を上書きすれば、修正は消えてしまいます。

この記事では、hotfixを本流へ戻すところまでを「緊急対応のひと続き」として扱えるように、手順を小さく分けて一緒に整理していきます。

結論:やることは3つです。①緊急修正をしたら、その場で「取り込み待ち」を1行残す、②落ち着いたら、修正を開発中のブランチにも入れる(merge か cherry-pick)、③次のリリース前に「本番にあって、これから出すものにない変更」がないかをコマンドで確かめる。記憶に頼らず、残した1行と確認コマンドで漏れを拾える形にしておけば、「直したはずの不具合が戻る」はぐっと起きにくくなります。

なお、ブランチの名前や運用ルールは現場ごとに違います。ここでは「本番に出ているコード」を main、「次のリリースに向けて開発中のコード」を develop と呼んで説明します。コマンドは考え方をつかむための例なので、手元の構成に合わせて読み替え、検証用のリポジトリで試してから使ってください。

何が起きているか:直した場所と、次に出す場所が別々になっている

上下に平行に伸びる2本の線路のような道があり、上の道に修正の印、そこから下の道へ向かって降りていく矢印が描かれた図
本番で直した修正を、開発中の道にも「取り込み」で戻しておく。これが抜けると、次のリリースで修正が消えてしまう

普段のリリースは、開発中のコードから本番へ、一方通行で流れています。ところが緊急修正だけは、本番の側から先に直すことになります。ここで流れが逆向きになるので、もう一度「開発中」へ戻す一手が必要になります。この一手が「取り込み」です。

取り込みが抜けたまま、次のリリースで開発中のコードを本番に出すと、こうなります。

ブランチを使っていない現場でも、構図は同じです。本番サーバーのファイルを直接直し、手元やリポジトリのコードには入れていない。その状態で手元から次の改修を反映すれば、やはり修正は上書きされます。

ポイントは、取り込み漏れは「緊急対応が終わったあと」に起きるということです。障害が収まった安心感と、溜まっていた通常業務に押されて、戻す作業だけがそっと後回しになる。誰にでも起きる、ごく自然な抜け方です。

取り込み漏れが起きやすい3つの場面

自分の現場がどれに近いかを見ておくと、どこに仕組みを置けばいいかが分かります。

  1. 本番サーバーを直接直した:SSHで入ってファイルを編集した、管理画面から設定を変えた。いちばん速い分、リポジトリにも記録にも何も残りません。
  2. 本番のコードからhotfixブランチを切って直した:main には入ったが、develop へのマージを忘れた。手順としては正しいのに、最後の1ステップだけが抜けるパターンです。
  3. 開発中の側にだけ入れて、本番へは別ルートで当てた:先に develop で直し、本番には同じ内容を手で当てた。中身は同じでも、ファイルの細部や設定値がずれて「似ているけれど違う」修正が2つできてしまいます。

どれも、緊急時の判断としては間違っていません。急いで直すことと、あとで戻すことは、別々の作業として扱っておけばいいだけです。

手順1:緊急修正の直後に「取り込み待ち」を1行残す

まず一番効くのは、直したその場で、戻すべきものを1行書いておくことです。障害対応メモや変更管理台帳、チケット、どこでもかまいません。大事なのは「あとで思い出す」ではなく「あとで見る場所に置いておく」ことです。

[取り込み待ち] 2026-10-03 23:40 決済金額の端数処理を修正
  本番に入れた場所:main(コミット 3f9a1c2) / または サーバー直接:/var/www/app/lib/Payment.php
  戻す先:develop
  戻したら:ここに「取り込み済 YYYY-MM-DD」と追記

この1行は、暫定対応の「戻し忘れ」を防ぐときと同じ考え方です。緊急対応のテンプレートに「取り込み待ち」の欄を最初から入れておくと、書き忘れも減ります(暫定対応と恒久対応を分けて管理する・変更管理台帳の付け方)。

手順2:落ち着いたら、本流に戻す(場面別)

障害が収まり、ひと息ついたら取り込みです。理想は緊急対応の当日か翌営業日。時間が空くほど、開発中のコードが先へ進んで、戻すときにぶつかりやすくなります。

場面A:hotfixブランチで直した場合 → develop にマージする

本番のコードから切ったブランチで直したなら、main に入れたあと、同じブランチを develop にもマージします。

# 本番に出ているコードを起点に、hotfixブランチを切って直す
git switch main
git switch -c hotfix/payment-rounding
# (修正してコミット)

# 本番側に入れる
git switch main
git merge --no-ff hotfix/payment-rounding

# 開発中の側にも入れる ← ここが抜けやすい
git switch develop
git merge --no-ff hotfix/payment-rounding

develop 側で衝突(コンフリクト)が出たら、それは開発中のコードが同じ場所を変えているサインです。慌てずに、修正の意図(何を直したか)が、開発中のコードでも成り立っているかを確かめながら解消します。単純にどちらかを採るのではなく、両方の変更が生きる形にするのが基本です。

場面B:特定のコミットだけ持っていきたい場合 → cherry-pick する

main にほかの変更も混ざっていて、修正のコミットだけを develop に持っていきたいときは cherry-pick を使います。

git switch develop
# -x を付けると、コミットメッセージに「どのコミットから持ってきたか」が残る
git cherry-pick -x 3f9a1c2

-x を付けておくと、メッセージの末尾に (cherry picked from commit 3f9a1c2...) と元のコミットが記録されます。あとから「この修正、本番のどれと同じ?」をたどるときの手がかりになるので、付けておくのがおすすめです。

場面C:本番サーバーを直接直した場合 → まず差分を取り出す

サーバーで直接直した場合は、まず本番と手元(リポジトリ)で何が違うかを確かめます。rsync の確認モードを使うと、ファイルを一切動かさずに違うファイルの一覧だけを見られます。

# 本番 → 手元へ「もし同期したら何が変わるか」だけを表示する(-n で何も変更しない)
# -c は中身で比較、アップロードやログなど本番にしかないものは除外する
rsync -avnc \
  --exclude='uploads/' --exclude='logs/' --exclude='cache/' --exclude='.env' \
  user@prod-server:/var/www/app/ ./app/

違うファイルが分かったら、本番のファイルを1つずつ見て、緊急修正の部分だけを手元の develop に入れてコミットします。コミットメッセージには「本番で直接修正した内容の取り込み(いつ・何のため)」を書いておくと、あとで経緯を追いやすくなります。

なお、ここで緊急修正以外の差分も見つかることがあります。誰かが以前に直接直したまま残っていたものです。見つかったら、その場で全部片づけようとせず、まずは一覧にして残しておけば十分です。ソースがまだバージョン管理に載っていない現場は、バージョン管理なしのソースをGitに載せる手順から始めると、この差分確認がぐっと楽になります。

手順3:次のリリース前に「本番にあって、出すものにない変更」を確かめる

手順1と2で、ほとんどの取り込み漏れは防げます。それでも人の手でやる以上、抜けることはあります。そこで最後に、リリース前の確認に「取り込み漏れチェック」を1行足しておきます。

ブランチで管理している場合

git fetch origin

# main にあって develop にないコミットの一覧
git log --oneline --no-merges origin/develop..origin/main

# cherry-pick で同じ内容が入っているものを見分けるには git cherry
# 先頭が「+」=まだ develop に同じ変更がない、「-」=同じ内容が develop に入っている
git cherry -v origin/develop origin/main

git log の一覧が空なら、main の変更はすべて develop に含まれています。cherry-pick で取り込んだ修正は、コミットが別物になるので git log には出続けます。そこで git cherry を使うと、中身が同じ変更は「-」として見分けてくれます。「+」が付いた行が残っていたら、それが取り込み待ちの候補です。

ただし git cherry は「変更内容がまったく同じか」で見分けるので、衝突を手で直して少し形が変わったものは「+」のまま出ることがあります。「+」が出たら即NGではなく、手順1で残した「取り込み待ち」の行と突き合わせて、ひとつずつ確認するくらいの使い方がちょうどいいと思います。

サーバーで直接直すことがある場合

リリース直前に、手順2の場面Cと同じ rsync -avnc を流して、本番にだけある変更がないかを見ます。ここで何か出てきたら、リリースをいったん止めて、その差分を取り込んでから出すのが安全です。

リリース手順書の「作業前の確認」にこの1行を入れておくと、毎回の作業に自然に組み込めます(リリース手順書の作り方)。出したあとの確認はリリース後の確認項目で整理しています。

具体例:「直したはずの不具合」が戻らなくなった現場

ある会員サイトを一人で保守している担当者の、よくある流れです。

変わったのは、担当者の記憶力ではありません。戻すべきものが目に見える場所に置かれ、出す前に必ず一度のぞくようになったことです。

影響:取り込みを「緊急対応の一部」にすると、何が変わるか

明日やること

  1. いま「取り込み待ち」になっているものがないかを見る。ブランチがあれば git log --oneline --no-merges origin/develop..origin/main、サーバーを直接直すことがあれば rsync -avnc を一度流してみます。
  2. 緊急対応のメモ・テンプレートに「取り込み待ち」の欄を1つ足す。戻す先と、戻したら書く場所を決めておきます。
  3. 取り込みのタイミングを決める。「緊急対応の翌営業日の朝」など、具体的にしておくと後回しになりにくくなります。
  4. リリース前の確認に1行足す。「本番にあって、出すものにない変更がないか」をコマンドで確かめる行です(リリース手順書の作り方)。

今日やるのは、1の「いま取り込み待ちがないかを見る」だけでも十分です。何も出てこなければ、それだけで次のリリースを少し安心して迎えられます。

hotfix取り込み漏れ防止チェックリスト

全部を一度にそろえなくても大丈夫です。まずは「取り込み待ちを1行残す」と「リリース前に1回のぞく」の2つだけで、取り込み漏れの多くは手前で拾えるようになります。

よければ、こちらも

朝の明るいオフィスで、ノートの付箋に完了の印をつけながら、落ち着いた笑顔でモニターを見ている保守運用の担当者

夜中に急いで当てた修正は、その時間にサービスを守り抜いた証拠です。その頑張りを、次のリリースで消してしまうのはもったいない。取り込みまでを「緊急対応のひと続き」にしておけば、あの夜の修正はちゃんと残り続けます。

まずは今日、main と develop の差分を一度のぞいてみてください。何も出なければ、それで安心がひとつ増えます。

ほかの実務ヒントは記事一覧からどうぞ。保守運用の小さな備えを、メールでも少しずつお届けしています。

関連用語