リリース1時間前だった。
ローカルでエラーが出た。検証環境では出ていないエラーが、なぜかローカルだけで出ている。おかしい。よく見ると——mainブランチに、いつのものかわからないコミットが大量に入り込んでいた。
「こんなの治せるわけない」
そう思った。
何が起きていたか
ベンダーからの引き継ぎが終わって間もない時期だった。まだgitの全体像を完全に把握しきれていない中で、定期リリースの準備をしていた。
ローカルで最終確認をしていたとき、検証環境では再現しないエラーが出た。環境の差異かと思って調べると、そうじゃなかった。mainブランチにあるはずのないコミットが100本単位で混入していた。 おそらくマージの順番を誰かが間違えたことで、過去のコミットが一気に流れ込んできたのだと思う。
コードは完全にカオスだった。どこからどこまでが正しい状態なのかわからない。revertを試みたが、コミットが絡み合いすぎていて、直すほど別の問題が出てくる。
時計を見た。リリースまで1時間を切っていた。
判断:mainブランチを捨てた
直すのに1時間かかるかどうかもわからない。でもリリースは止められない。
判断は早かった。mainブランチは放棄する。 カオスになったコードを直すより、クリーンな状態から作り直した方が速い。
検証ブランチ(stg)は正常だった。そこからリリース用のブランチを切り直し、今回のリリースに含めるべき変更だけを手作業でcherry-pickした。mainは一旦捨てて、後で別途整理する。
# 検証ブランチを起点に、リリース分だけ切り出す
git checkout -b release/hotfix origin/staging
git cherry-pick <リリース対象のコミットのみ>
1時間でなんとか形にした。リリースは通った。ユーザーへの影響はゼロだった。
誰にも理解されなかった
作業中、周りに説明しようとは思わなかった。
運用担当の人間も、他のメンバーも、この状況の重大さを理解できる人間はいなかった。リテラシーの問題ではなく、gitの内部で何が起きているかを把握するには、相応の経験が必要だ。説明するだけ時間の無駄だし、説明したところで「大変だったんだね」以上の言葉は返ってこない。
孤独の極みだった。 黙って、一人でやった。
終わった後、ベンダーの担当者にこっそり話した。引き継ぎの時期に世話になった人だ。その人だけがこの話の重さを理解してくれた。
リリース後、mainを作り直した
リリースが終わった後、壊れたままのmainブランチを放置するわけにはいかない。
やったことはシンプルだった。stgブランチから新しいブランチを切って、それを新しいmainとして稼働させた。 混乱したmainを修復しようとするのではなく、クリーンな起点から作り直す。リリース直前の判断と同じ発想だ。
「治す」より「捨てて作り直す」——この判断の一貫性が、1時間という制約の中でも迷いをなくしてくれた。
「自分かっこいい」と思わないとやってられない
リリースが全部終わったあと、一人でそう思った。
ユーザーへの影響をゼロで食い止めた。誰もこの修羅場を知らない。評価されることもない。でも、やり切った。
自分くらい自分を褒めてあげないと、誰も褒めてくれないのだから。
この経験が変えた習慣
同じことが起きないように、マージのやり方を変えた。
以前は「マージできればOK」という感覚があった。今は違う。
- そのタスクに関係するコミットが過不足なく入っているかを慎重に確認する
- コミット数が適切かを見る。想定より多ければ、意図しない変更が混じっている可能性がある
- マージ前に一度立ち止まって、「このブランチに何が入っているか」を自分の目で確認する
面倒に見えるかもしれないが、1時間で修羅場を経験した身としては、この確認に使う数分は安いものだ。
カオスに対して持っておくべき選択肢
この経験で学んだことが一つある。カオスに陥ったとき、「直す」以外の選択肢を持っておくことだ。
mainブランチを放棄するのは怖い判断に見えるが、「クリーンな状態はどこか」を把握できていれば、そこから切り直す方が速いことがある。どこがクリーンかを常に意識しておくこと——それがこの経験以来、自分の中に残っている考え方だ。
この修羅場の経験が、後のリリースフロー整備にどうつながったかは引き継いだリリースフローが、監査で初めて意味を持ったに書いている。