【Git】誤ってmaster/mainを削除したときの復旧方法

【Git】誤ってmaster/mainを削除したときの復旧方法 Git

誤って master / main を削除してしまった——血の気が引く事故ですが、Gitには強力な復旧手段があります。
多くのケースでは、ローカルの reflog、リモートの参照、他クローンの履歴、CIのミラーなどから元の先端コミットを特定し、ブランチを再作成すれば復活できます。
本記事では「ローカルだけ消した」「リモートも消した」「両方消えた」の順に、確実に戻すための実践手順を解説します。

状況確認:本当に“失われた”のは何かを切り分ける

まずは最新の参照を取得し、ローカル/リモートのどちらで消えたのかを見極めます。削除がローカルだけなら復旧は簡単です。

# 参照更新と不要参照の掃除
git fetch --prune --all

# 追跡先の存在を確認
git ls-remote --heads origin

# ローカルのブランチ一覧(削除されたかの確認)
git branch

# 退路確保(必ず実行)
git switch -c safety/backup-$(date +%Y%m%d-%H%M)

ケースA:ローカルだけで削除してしまった(リモートは生きている)

リモートに origin/main(または origin/master)が残っていれば、追跡ブランチを作り直すだけで復旧できます。

# mainを復旧(masterの場合は名前を読み替え)
git switch -c main origin/main
# 追跡設定を明示しておくと安全
git branch --set-upstream-to=origin/main main

もし誤ってローカルだけで削除(git branch -D main等)しただけなら、これで完了です。

ケースB:リモートのデフォルトブランチを削除してしまった(ローカルには残っている)

ローカルに正しい先端があるなら、そのコミットを指す同名ブランチをリモートへ再公開します。保護設定やデフォルトブランチの指定が無効になっている可能性があるため、管理画面側の復旧も忘れずに。

# ローカルのmainが正しいと仮定して再公開
git push -u origin main

# masterを復旧する場合(例)
# git push -u origin master

リポジトリ設定で「デフォルトブランチ」を再度 main(または master)へ設定し直し、ブランチ保護ルールやCIの対象ブランチも元に戻します。

ケースC:ローカルでもリモートでも消えたが、過去の先端はわかっている

先端コミットのハッシュが分かっているなら、そこからブランチを再作成して公開します。ハッシュはPR、チケット、リリースノート、CIログなどからも追跡できます。

# 既知のハッシュ <HEAD-OF-MAIN> から再作成
git branch main <HEAD-OF-MAIN>
git push -u origin main

ケースD:先端コミットのハッシュが分からない(reflog で捜索)

reflogはHEADや各参照の移動履歴を保持しています。ブランチを削除しても、多くの場合は直前の指し先を辿れます。

# HEADの移動履歴から候補を探す
git reflog

# 例: main の過去先端を直接調べる(残っていれば)
git reflog show main

# 見つけたハッシュ <RECOVER> からブランチを再作成
git branch main <RECOVER>
git push -u origin main

reflogに残っていない場合は、作業端末の他クローン、同僚のクローン、CIのチェックアウト履歴からハッシュを収集すると高確率で見つかります。

ケースE:両方消え、reflogにもない(最終手段:dangling探索と他クローン救出)

参照から外れたコミット(dangling)がオブジェクトDBに残っている可能性があります。総当たりで探し、候補から復旧します。

# ぶら下がりオブジェクトを列挙し、コミットだけ抽出
git fsck --no-reflogs --lost-found | grep commit

# 候補ハッシュを順に確認(日時やメッセージで特定)
git show --stat <HASH>
git show -p <HASH> | less

# 妥当な先端が見つかったら再作成
git branch main <HASH>
git push -u origin main

並行して、同僚のローカルクローンやデプロイ用のミラー(読み取り専用)から git bundle で履歴を回収する方法も有効です。

# 履歴を束ねて共有(他クローン側で)
git bundle create repo.bundle --all

# 手元で取り込み
git clone repo.bundle recovered-repo
# または既存リポジトリへfetch
git fetch repo.bundle "refs/heads/*:refs/remotes/bundle/*"

ケースF:誤って別ブランチへ“復旧push”してしまった(やり直し)

間違ったブランチ名で復旧pushしてしまった場合は、公開履歴を壊さずに取り消すなら revert、完全に巻き戻すなら合意のうえ --force-with-lease を使います。状況により最小影響の方法を選びます。

# 誤pushを「機能的に」取り消す(内容を戻して履歴は維持)
git revert <wrong-commit-range>
git push

# どうしても履歴を戻すなら(要合意・保護ブランチ注意)
git reset --hard <correct-base>
git push --force-with-lease

タグ・リリース・PRの整合を確認する

ブランチ復旧後は、タグが正しいコミットを指しているか、PRのベースブランチが復旧先へ向いているか、リリース自動化やCIのブランチ指定が壊れていないかを確認します。必要に応じてタグの付け直しやPRのベース変更を行います。

事故の前後で必ずやる保険と周知

復旧前に退避ブランチを切ってスナップショットを残すこと、復旧後に影響範囲(再クローン/強制同期の必要性)をチームへ周知することは必須です。

# 既存クローンの再同期例(周知用)
git fetch --prune
git checkout main
git reset --hard origin/main

再発防止:設定と運用の見直し

デフォルトブランチにはブランチ保護(削除禁止・強制push禁止・レビュー必須・CI必須)を設定します。削除操作は管理者のみ、PR経由で行う運用に限定すると安全です。
また、リポジトリのバックアップ(ミラー)や receive.denyDeleteCurrent の有効化、誤操作検知のフック導入も有効です。

# サーバー側で受け取り時の削除を制限(ホスティングにより設定方法は異なる)
# 例: リポジトリ設定で "Deny deleting the current branch" を有効化

まとめ

master/main を誤削除しても、多くのケースで復旧可能です。リモートが生きていれば追跡ブランチの再作成、ローカルだけなら origin/main から復旧、
両方消えた場合でも reflog・他クローン・dangling 探索から先端コミットを特定して再作成できます。
復旧後はデフォルトブランチの保護と周辺設定を必ず見直し、同種事故の再発を防ぎましょう。