やらかした
forkして使い始めたから、もう元リポジトリはいらないと思って削除した。
そしたらfork先が消えた。
何をしようとしていたか
Org A(自社)からOrg B(他社)へリポジトリを移動したかった。
GitHubには Transfer repository という正規の機能があるのだが、その機能を知らずforkで代用しようとした。
やったこと:
- Org B(他社)でOrg A(自社)のリポジトリをfork
- Org Bのfork先リポジトリで作業開始
- Org Aの元リポジトリを削除(←ここで事故)
OSSなどは、fork元が閉鎖しても、forkしたリポジトリは生きているから、プライベートリポジトリだと、まさかfork先リポジトリが消えるとは思っていなかった。
何が起きたか
Org Aの元リポジトリを削除した瞬間、Org Bのfork先も自動で削除された。
しかも厄介だったのは、Org Bの設定から「削除済みリポジトリ」を確認しても、リストに出てこないことだ。通常の削除であれば90日以内なら自分で復元できるが、forkが道連れ削除された場合はその方法が使えない。
Settings > Repositories > Deleted repositories
→ そこに表示されない...
なぜこうなるのか
GitHubの仕様として、privateリポジトリを削除するとそのforkも全て削除される。
| リポジトリの種類 | upstream削除時のfork |
|---|---|
| private | 💀 全fork道連れ削除 |
| public | ✅ 最古のforkがupstreamに昇格して生存 |
publicの場合はforkが生き残るが、privateは容赦なく消える。
公式ドキュメントにはちゃんと書いてある。
When you delete a private repository, all of its private forks are also deleted.
— What happens to forks when a repository is deleted or changes visibility?
知らなかった。
復元の手順
1. まず元リポジトリ(upstream)を復元する
自分のOrg Aの元リポジトリは「削除済みリポジトリ」リストに表示されていたので、自力で復元した。
Settings > Repositories > Deleted repositories > Restore
これで、Org Bの削除リポジトリリストに表示されると思ったが、表示されない。
ここで、冷や汗出まくり。
やばい、gitだからソースコードは完全無事だが、issueやPRの記述が全部なくなってしまう。
2. GitHub Supportに連絡する
Org Bのforkは、自力でもOrg Bの管理者でも復元できないため、GitHub Supportに問い合わせた。
GitHub Support Portal からチケットを起票し、以下を伝えた:
- fork先リポジトリが自動削除されたこと
- 復元したいforkのOrg名・リポジトリ名
- upstreamのOrg名・リポジトリ名(復元済みであること)
AIに英文にしてもらって、送信しました。
3. upstreamのadminによる承認が必要
GitHub Supportから「privateのforkを復元するには、upstreamのadminによる承認が必要」と返ってきた。forkを復元してほしいのはOrg Bなのだが、upstreamであるOrg Aのadminが「このforkの復元を許可する」と同じチケットに返信しなければならない。
4. detachもリクエストできる
復元をお願いするついでに、forkをupstreamからdetach(切り離し)するリクエストも一緒に送った。
detachすることで、同じ事故が再発しないスタンドアロンのリポジトリになる。GitHub Supportは復元と同時にdetachも対応してくれた。
神対応で良かった…
正しいやり方
Org間のリポジトリ移動には Transfer repository を使おう。
Settings > General > Danger Zone > Transfer ownership
forkと違い、Issue・PR・GitHub Actionsの設定ごと移動できる。コード以外の資産も失われない。
まとめ
- GitHubのprivateリポジトリを削除すると、全forkが道連れで削除される
- 道連れ削除されたforkは削除済みリストに出てこない(自力復元不可)
- 復元にはGitHub Supportへの連絡が必要で、upstreamのadmin承認も必要
- 復元時にdetachリクエストも一緒に送ると再発防止になる
- Org間のリポジトリ移動には最初から Transfer repository を使う