Safe Rollback
壊れた状態から安全に回復するためのスキル。最優先の目的は「元に戻すこと」ではなく「これ以上悪化させないこと」。今ある状態(壊れたコードも含めて)は、消さない限り必ず後から調査・回復できる。逆に、慌てて git reset --hard や git clean を実行すると、原因調査の材料も、直前まで動いていたかもしれない作業も、両方失われる。
大原則
- 消さない・上書きしない。 回復作業で使ってよいのは「追加する」操作(ブランチ作成、stash退避、revertコミット)だけ。
git reset --hard、git clean、git checkout -- .、force push は使わない(このテンプレートでは settings.json の deny でもブロックされている)。
- 作業前に必ず退避する。 どんな回復手段を取るにも、先に現状をバックアップブランチに退避してから行う。
- 1操作ごとに平易な言葉で説明する。 ユーザーは技術用語で状況を判断できない前提に立つ。「これから何をするか」「それで何が起きるか」「失敗してもやり直せるか」を一言ずつ添える。
- 2回試して直らなかったら手を止める。 回復の試行を重ねるほど状態は複雑になる。2回試みて改善しない場合は、それ以上触らず、現状・試したこと・残っている選択肢を整理してユーザーに報告する。
Step 1: 現状を凍結して把握する
まず何も変更せず、読み取り系コマンドだけで状況を集める。
git status # 未コミットの変更があるか
git log --oneline -15 # 最近何が入ったか
git diff # 未コミットの変更の中身
git stash list # 退避済みの作業が残っていないか
あわせてユーザーに「いつまでは動いていたか」「壊れる直前に何をしたか(自分の操作・Claudeへの依頼・デプロイ等)」を聞く。エラーメッセージやスクリーンショットがあれば見せてもらう。
Step 2: どこが壊れているかを切り分ける
壊れ方によって取るべき手段が全く違うので、次のどれに当たるかを判定する。複数該当することもある。
| 状況 | 見分け方 | 対応するStep |
|---|
| 未コミットの変更で壊れた | git status に変更があり、最後のコミット時点では動いていた | Step 4-A |
| コミット済み(未push)の変更で壊れた | 壊した変更がローカルのコミットに含まれる | Step 4-B |
| push済みの変更で壊れた | 壊した変更がリモート(GitHub等)にも上がっている | Step 4-C |
| デプロイ済みの本番が壊れた | 本番環境でエラー・障害が出ている | Step 4-D |
| DBマイグレーションで壊れた | migration実行後からおかしい、データが見えない・消えた | Step 4-E |
どのコミットから壊れたか不明な場合は、git log を見ながら「この日は動いていましたか」とユーザーの記憶と突き合わせて範囲を絞る。テストコマンドがあるなら(CLAUDE.md参照)、過去のコミットをチェックアウトして確認する手もあるが、その場合も現在の状態を先にStep 3で退避してから行う。
Step 3: 現状を退避する
回復操作の前に、必ず今の状態を丸ごとバックアップブランチに残す。
git stash push -u -m "rollback前の未コミット退避 <日付>" # 未コミット変更がある場合
git branch backup/before-rollback-<日付> # 現在のコミット位置に印を付ける
git stash pop など必要に応じて元に戻す
未コミット変更が無ければブランチ作成だけでよい。ユーザーには「今の状態は backup/... という名前で保存したので、この後の作業で何が起きても今の時点には戻れます」と伝える。
Step 4: 安全な手段で復旧する
4-A: 未コミットの変更を取り消す
git checkout -- . や git restore で捨てるのではなく、git stash push -u -m "壊れた変更の退避 <日付>" で退避する。結果は同じ(作業ツリーが最後のコミットに戻る)だが、退避なら後から原因調査や部分的な取り出しができる。stashは消さずに残しておく。
4-B: コミット済み(未push)の変更を取り消す
git reset ではなく git revert <コミット> を使う。歴史を書き換えず「打ち消すコミットを追加する」ので、後から経緯を追える。複数コミットをまとめて戻すなら git revert --no-commit <古い方>..HEAD してから1コミットにする。
4-C: push済みの変更を取り消す
ローカルで git revert してから通常の git push。force pushは絶対にしない(チームの他の人や自動デプロイが参照している歴史を壊すため。denyでもブロックされている)。PRベースの運用をしているプロジェクトなら、revertもPR経由で出す。
4-D: デプロイ済みの本番を戻す
プロジェクトのデプロイ手順(CLAUDE.md や .claude/commands/ のdeployコマンドに記載があるはず)を確認し、「前のバージョンを再デプロイする」手段があるかを探す。ホスティングサービス(Vercel, Netlify, Cloud Run等)には管理画面から前のデプロイに戻すボタンがあることが多いので、コードをいじるより先にそれを案内する——コード修正→再デプロイより、前バージョンへの切り戻しの方が速くて確実。切り戻し手段がどこにも書かれていない場合は、コード側を4-B/4-Cで戻してから再デプロイする。
4-E: DBマイグレーションを戻す
ここだけは慎重さのレベルを一段上げる。コードと違ってデータは退避が効いていないことがあり、間違った巻き戻しでデータを失うと回復不能なため。
- down migration(巻き戻し用のマイグレーション)が用意されているか、直前のバックアップが存在するかをまず確認する。
- どちらも確認できない場合、または巻き戻しがデータ削除を伴う場合は、実行せずに手を止める。 状況を整理してユーザーに提示し、DBのホスティングサービスのサポートやバックアップ機能(ポイントインタイムリカバリ等)の利用を案内する。
- 実行する場合も、何が起きるかを平易な言葉で説明して明示的な承認を得てから行う。
Step 5: 直ったことを確認する
戻しただけで終わらせない。CLAUDE.md に記載のテスト・起動コマンドがあれば実行し、ユーザーが訴えていた症状が実際に消えたことを確認する(可能ならユーザー自身にも見てもらう)。テスト手段が無いプロジェクトなら、その旨を正直に伝える。
Step 6: 平易な言葉でまとめる
最後に次を報告する。
- 何が原因で壊れていたか(分かった範囲で。分からなければ「分からなかった」と言う)
- 何をどこまで戻したか
- 退避した壊れた状態がどこに残っているか(
backup/... ブランチ、stash)と、原因調査に使えること
- 再発を防ぐために次にやるとよいこと(例: 壊した変更を退避ブランチから調査する、テストを追加する)
壊れた変更の退避ブランチ・stashは勝手に削除しない。ユーザーが「もう要らない」と明言したときだけ片付ける。