はじめに
こんにちは、クライアントエンジニアの菅原です。
みなさんGitのブランチの履歴を吹っ飛ばしたことはありますか。自分はあります。
そういった危機的状況をなるべく防ぐため、本日は Protected Branch 機能のご紹介をしたいと思います。
発端
自分が所属しているグローバルスタジオは、海外リージョン向けにアプリをローカライズしてリリースするのが主な仕事になります。
ゆえに、国内でリリースされている処理をマージしてくるという作業が必然的に多くなります。
たまにあるのが
「マージ先をミスってしまったのでマージコミットを取り消したい」
というもの。
1年以上前の話なので少し記憶が曖昧ですが、
pushされていたマージコミットを、単純にresetしてpushしようとするとエラーになっていたため、force pushをかけようとしました。
ただそこでうっかり git push -f origin master
を叩きました。
ここで問題だったのが、作業したかったブランチがmasterブランチではなかったことです。
何が起こったか
リモートのmasterブランチが、自分のローカルにあった古い状態の(しばらくpullしていなかった)masterブランチの状態になってしまいました。
どうしたか
同僚が最新のmasterブランチをローカルに持っていたので、それをpushしなおしてもらって助かりました(運が良かった)。
事後対応として、消えたら困る/直接pushされたくないブランチにはプロテクトをかけました。
ブランチへのプロテクトのかけ方
弊社だとGitHubを使用していますので、Setting->Branches->Branch protection rules にて、Add ruleできます。
特にチェックしておいた方が良いと思われる設定
Branch name pattern
保護したいブランチ名を指定します。パターンマッチも使えます(命名規則にもよりますが、develop/*
など)。
デフォルトで、force pushとブランチ削除を禁止してくれます。
Require pull request reviews before merging
該当ブランチにpushする際に、PRを通すことを必須にします。
配下の項目で、approve必要な人数や、レビュー通った後に新しいcommitした場合のふるまいなどを細かく設定できます。
Include administrators
admin権限のあるユーザもこのルールの対象にします。
これで、該当のブランチには直接pushができなくなり、pushしたい場合は Pull request を経ることが必要になります。
上記の画像ではチェックついていませんが、「CIなど外部ツールの実行が成功しないとマージ不可」や、「pushするメンバーを制限する」など、設定を更に加えることも可能です。
余談
上述した通り、自分がやらかしたのは1年半くらい前の話なのですが、
つい先日、近いチームで似た事案が発生していました。
事象としては、Pull requestを閉じる際に一緒に、削除してはいけないブランチを削除してしまったとのこと。
GitHubではPRに付随してブランチを削除した場合は、PRのページ上からRestore branchができるので、事なきを得たようです。
これも事後対応でブランチにプロテクトかけていました。
また、これもつい先日、プライベートでプレイしているゲームのギルドメンバーが、後輩に1日分の作業吹っ飛ばされたと嘆いていましたが、話聞く限りforce pushをされたようでした。
世界には悲しみが溢れていますね。
結論
- 大事なブランチにはプロテクトをかけよう
- force push を使う場合は細心の注意を払おう
おわりに
自分はやったことはないですが、復旧方法として、やらかす直前のコミットのハッシュ値を探してきてforce pushをやり直すというのも場合によっては可能なようです。
ただ、やはり事前に防げた方が良いですね。
プロテクトブランチにすると、設定によってはブランチにマージする際に必ずPRを出さないといけなくなったりするため少々手間は増えるかもしれませんが、誰かに吹き飛ばされるリスクがあるよりいいのではないでしょうか。
それではみなさま、良きgitライフを。