コンテンツへスキップ

デプロイ完了とgitコミット完了は別物 — 「アップロード済み=ローカルも同期済み」と思い込む罠

リリース作業の最終段階で、本番サーバーへのファイル転送がすべて成功し、配信用のバージョン情報ファイルも更新できた。ここまで確認して「リリース完了」と報告したところ、実はローカルのgitリポジトリには、転送したはずの変更がコミットされていなかった。

補足: ここでの「デプロイ」は、変更したファイルをscp等で本番サーバーへ転送し、実際にユーザーに配信される状態にする作業のこと。「git push」は、それとは独立して、変更履歴をリモートリポジトリに記録する作業を指す。

何が起きたか

このリリースでは、ランディングページの更新案内ファイル5点・配信トリガーとなるバージョン情報ファイル・進捗記録ファイルの計7ファイルを本番サーバーへ転送した。転送自体はすべて成功し、本番サイトで実際に新しいバージョン番号が表示されることも確認できた。

ところが、これらのファイルをローカルで編集した後、コミットする手順を踏まないまま転送作業に進んでしまっていた。本番サーバー上のファイルは最新化されているのに、ローカルのgitリポジトリには、その変更が記録されていない状態のままリリース完了の報告をしてしまった。

なぜ気づきにくいか

scp でファイルを転送する作業と、git commit / git push でリポジトリに記録する作業は、コマンドとしても目的としても完全に独立している。本番サーバーでの動作確認(HTTP 200・表示内容の確認)は「配信が成功したか」を検証するものであり、「ローカルの変更履歴が記録されているか」は別の問いだ。前者を確認しただけで「作業完了」と判断してしまうと、後者の確認が抜け落ちる。

両者を一連の作業として扱っていると、片方だけが完了している状態に気づく機会がない。今回も、別の作業者が見て「あれ、まだコミットされていない」と気づいたことで発覚した。

対処 — 「アップロード完了」と「git同期完了」を別々の確認項目にする

デプロイ手順のチェックリストに、ファイル転送の確認とは別に、git の同期状態を確認する項目を独立して設ける。

# デプロイ前にコミット
git add <変更ファイル>
git commit -m "..."
git push origin main

# scp でサーバーへ転送
scp <ファイル群> user@server:path/

# 本番確認
curl -s -o /dev/null -w "%{http_code}" https://example.com/version.json

# git 同期確認(ここを独立した手順として明記する)
git status   # "nothing to commit, working tree clean" を確認
git rev-list --left-right --count origin/main...main   # "0 0" を確認

最後の git rev-list は、ローカルブランチとリモートブランチの差分コミット数を両方向で数えるコマンドで、出力が 0 0 であれば「ローカルとリモートが完全に一致している」ことを意味する。「push したつもり」を主観的な記憶ではなく、コマンドの出力で機械的に確認できる。

設計のポイント

この事故の本質は、「scp完了」と「git完了」という性質の異なる2つの状態を、頭の中で1つの「リリース完了」という状態にまとめてしまっていたことにある。対処の核は、技術的な仕組みを追加することよりも、チェックリストの粒度を分けることにある。「本番に反映された」と「変更履歴が記録された」を別々の確認ステップとして明示し、両方が揃って初めて「完了」と判断する運用に変えた。

まとめ

観点 内容
問題 ファイルの本番転送(scp)とgitへの記録(commit/push)は独立した作業なのに、片方の確認だけで「完了」と判断してしまった
気づきにくさ 本番動作確認は「配信成功」を検証するが「ローカル変更履歴の記録」は検証しない、別の問い
対処 デプロイ手順のチェックリストに「git同期確認」を独立した項目として明記する
確認コマンド git statusgit rev-list --left-right --count origin/main...main(出力 0 0)で主観に頼らず機械的に確認

複数の意味を持つ「完了」という言葉は、チェックリストの粒度を粗くする落とし穴になりやすい。「何が完了したのか」を1つずつ言葉にして確認項目に分解しておくことが、こうした抜け漏れを防ぐ。