技術 約3分で読めます

GitHubでリモートブランチを削除してしまったときの復元方法

Claude Codeに「マージされてないブランチ2個あるから落として」と言ったら、「ローカルにチェックアウトして」の意味で言ったのに git push origin --delete でリモートブランチを消された。ローカルにも残ってない。そんなときの復元方法。

ローカル削除の場合(git reflog)

ローカルで git branch -d した場合は git reflog から復元できる。

# 操作履歴を確認
git reflog

# 出力例: 4895a77 HEAD@{5}: checkout: moving from my-branch to main
# ↑このコミットハッシュを使う

# ブランチを復元
git checkout -b my-branch 4895a77

reflogはデフォルトで90日間保持される。

リモート削除の場合(GitHub API)

リモートで削除した場合、reflogには記録が残らない。GitHub CLIの gh api コマンドでリポジトリのアクティビティログを取得できる。ブランチ削除イベントには、削除前の最後のコミットハッシュが記録されている。

gh api repos/{owner}/{repo}/activity \
  --jq '.[] | select(.activity_type == "branch_deletion") | {ref: .ref, sha: .sha}'

出力例:

{
  "ref": "refs/heads/feature/my-branch",
  "sha": "d1525b761a6bdaed7df1058b68fd09da7b2fa81e"
}

sha が削除前のコミットハッシュ。

ブランチを復元する

コミットハッシュがわかれば、そこから新しいブランチを作成できる。

# ローカルにブランチを作成
git checkout -b feature/my-branch d1525b761a6bdaed7df1058b68fd09da7b2fa81e

# リモートにプッシュ
git push -u origin feature/my-branch

特定のブランチを探す場合

削除したブランチ名の一部がわかっている場合、jq のフィルタで絞り込める。

gh api repos/{owner}/{repo}/activity \
  --jq '.[] | select(.ref | contains("my-branch")) | {ref: .ref, activity_type: .activity_type, sha: .sha}'

branch_creationbranch_deletion の両方が出てくるので、sha0000000... でない方(削除イベント)のハッシュを使う。

注意点

  • activityログの保持期間は不明。早めに対応したほうがいい
  • コミット自体はGitHubのガベージコレクションで削除されるまで残っている(通常は数ヶ月)
  • プライベートリポジトリでも gh コマンドで認証済みなら取得可能

再発防止: CLAUDE.mdにガードレールを追加

今回の事故を受けて、CLAUDE.mdに以下のガードレールを追加した。

### Gitブランチ削除禁止
ブランチの削除(`git branch -d``git branch -D``git push origin --delete` など)は絶対に実行しない。
「チェックアウトして」「そのブランチに移動して」などの指示を「削除して」と誤解しやすいため、削除と解釈できる可能性がある場合はAskUserQuestionツールで確認を取ること。
例: 「ブランチ xxx を削除しますか?それともチェックアウト(切り替え)しますか?」

まあこっちが思ってることと相手が思ってることが違うってのはよくあることなんで、ちゃんと言えってことかもしれない……いやいつもはこれで大丈夫だったんだよ!