【Git】「remote HEAD refers to nonexistent ref」警告の原因と対処法|4パターン診断と根本対処完全ガイド

【Git】warning: remote HEAD ~エラーが出てcloneできないときの対処法 Git

git cloneを実行したのに、次のような警告が出てカレントディレクトリにファイルが展開されないことがあります。

典型的な警告
$ git clone https://github.com/user/repo.git
Cloning into 'repo'...
warning: remote HEAD refers to nonexistent ref, unable to checkout.

このwarningはリモートのHEAD(デフォルトブランチの参照)が指している先が存在しないことをGitが伝えています。cloneは内部的には完了していますが、「どのブランチにチェックアウトすべきか」が分からずファイルが配置されていません。結果として、ローカルディレクトリは存在するのに作業ツリーが空の状態になります。

この記事では、このwarningの正体と4つの典型原因、リモート側・クライアント側それぞれの修復手順、GitHubやGitLabで起きる特有のパターン(master→main改名直後など)、そして同じ問題を起こさないための予防策までを解説します。

この記事で学べること

  • 「remote HEAD refers to nonexistent ref」が発生する4つの原因
  • HEAD(refs/remotes/origin/HEAD)とは何か
  • リモート側の修正:GitHub UIでdefault branchを更新する手順
  • クライアント側の修正:git remote set-headで追跡を修復
  • 空リポジトリ/master→main改名直後/削除済みブランチへの対処
  • cloneが完了しているのにファイルが見えないケースの復旧
  • 同じ問題を起こさないチーム運用ルール
スポンサーリンク

エラーの正体:HEADが「存在しない参照」を指している

GitリポジトリにはHEADという特別な参照があり、「デフォルトブランチ(初期ブランチ)」を指しています。cloneするとクライアント側にrefs/remotes/origin/HEADとしてこの情報がコピーされ、「このブランチをcheckoutすればいい」という指示になります。このHEADが指すブランチがリモート側で削除・改名されていると、「存在しない参照」という状態になってwarningが発生します。

HEADの中身を覗く
# リモート側HEADの情報(git protocol)
git ls-remote --symref origin HEAD
# 出力例:
# ref: refs/heads/main	HEAD   ← mainを指す
# abc1234...	HEAD

# クライアント側HEADの設定
cat .git/refs/remotes/origin/HEAD
# または
git symbolic-ref refs/remotes/origin/HEAD

# リモートで存在するブランチ一覧
git ls-remote --heads origin

ポイント:このwarningはcloneが失敗したわけではないことに注意。リポジトリは.gitごとダウンロードされ、すべてのブランチがgit branch -rで見えます。「どのブランチに自動でチェックアウトすべきか分からなかった」だけなので、存在するブランチをcheckoutすれば作業ツリーが復活します。

4つの典型原因

このwarningが出る状況は限定的です。次の4パターンのいずれかに該当します。

原因 典型例
① デフォルトブランチが削除された 管理者がmainを誤削除した直後
② デフォルトブランチが改名された master→main移行でHEADが更新されていない
③ 空リポジトリ(commitが無い) 作成直後のリポをcloneした
④ 古い--bare/mirror由来の参照ズレ 自前ホスティングリポのメンテ不備

どれに当てはまるかを判定

  • git ls-remote --symref origin HEADで現在HEADが指すブランチを確認
  • git ls-remote --heads originで実在ブランチ一覧を確認
  • HEADが指すブランチが実在しない → ①②④のいずれか
  • 実在ブランチが0件 → ③空リポジトリ

STEP 0:診断してから対処を選ぶ

闇雲に試すより、まず状態を正確に把握する方が早いです。GitHubなどホスティング側の管理画面と、Gitの問い合わせコマンドを併用します。

クライアント側の診断コマンド
# リモートのHEADが指す先を確認
git ls-remote --symref origin HEAD
# → ref: refs/heads/XXX   ← このXXXが実在するかが鍵

# ブランチ一覧(HEAD候補)
git ls-remote --heads origin

# cloneしたあとの状態確認
cd repo
git branch -a
# → 存在するリモート追跡ブランチ一覧

# 現在HEADの状況
git status
# → "HEAD detached" 等の表示がヒントになる

注意:GitHub/GitLab/Bitbucket等のホスティング側では「デフォルトブランチ」という独自設定を管理画面で持っています。ここを直さない限り、クライアント側でいくら修復しても新規cloneではまたwarningが出ます。根本解決はリモート側設定の更新、クライアント側は症状緩和と覚えましょう。

解決①:ホスティング側でデフォルトブランチを更新する(根本対処)

警告の根本原因はリモートHEADが「存在しないブランチ」を指していることなので、GitHub/GitLab/Bitbucket等の管理画面からデフォルトブランチを正しく設定するのが本筋です。

GitHubでのデフォルトブランチ更新

  1. リポジトリページ → Settings タブ
  2. 左メニュー General → Default branch セクション
  3. 切替アイコン(⇆)をクリック → 実在するブランチを選択 → Update
  4. 確認ダイアログで I understand, update the default branch を押す
  5. CI/保護ルール/webhook等の再設定が必要なら併せて更新

GitLab/Bitbucketの場合

  • GitLab:Settings → Repository → Default branch
  • Bitbucket:Repository settings → Branches → Main branch
  • Azure DevOps:Project settings → Repositories → 対象リポ → Default branch
  • 自前Gerrit/Gitea/Soft Serve等も管理画面に同様のdefault branch設定あり

自前サーバーでbareリポを直接操作する場合

bareリポジトリのHEADを書き換える
# サーバーにSSHでログイン
ssh git@your-server.example.com
cd /path/to/repo.git

# 現在のHEAD設定を確認
cat HEAD
# 例: ref: refs/heads/master

# 実在ブランチを指すよう書き換え
git symbolic-ref HEAD refs/heads/main

# 確認
cat HEAD
# ref: refs/heads/main

ポイント:GitHubなどSaaSの場合は管理画面のUIで完結、自前ホスティングの場合はサーバー側でgit symbolic-ref HEADを書き換えます。いずれも「HEADがどのブランチを指すか」の1箇所を直すだけで根本解決します。

解決②:クライアント側で追跡情報を修復する

リモート側の管理権限が無い、あるいは「今すぐ作業を進めたい」場合はクライアント側だけで応急対処できます。git remote set-headを使います。

リモートHEADの追跡を自動修復
# リモートに問い合わせて実在のdefault branchを自動検出+設定
git remote set-head origin --auto
# 出力例: origin/HEAD set to main

# 明示的に指定する
git remote set-head origin main

# いったん解除(稀)
git remote set-head origin --delete

# 確認
git symbolic-ref refs/remotes/origin/HEAD
# → refs/remotes/origin/main

作業ツリーにブランチを展開する

実在ブランチにcheckout
# cloneしたがカレントに作業ツリーが無い状態
cd repo
ls
# → 空っぽ

# 実在ブランチを一覧
git branch -r
#   origin/main
#   origin/develop

# ローカルブランチを作って切り替え
git switch main
# Git 2.23+ なら自動でリモート追跡を設定

# 旧コマンドでの対応
git checkout -b main origin/main

ポイント:警告が出たあとでもcloneしたデータは無事です。作業ツリーが空なだけで、.git内にはすべての履歴があります。実在するブランチをcheckoutすれば、そこから通常どおり開発を始められます。

原因別の対処レシピ

ケースA:master→main改名直後の残存影響

GitHubでは2020年にmaster→mainへの移行を促進しました。古いリポだと改名時にdefault branch設定がずれているケースがあります。

master改名後のクライアント修復
# 実在ブランチを確認
git ls-remote --heads origin | grep -E "master|main"

# クライアントのHEAD追跡を更新
git remote set-head origin --auto

# ローカルがmasterを指していた場合の移行
git switch main    # Git 2.23+で自動トラック

# 古い master ローカルブランチを削除(不要)
git branch -d master

master→main移行とブランチ名変更全般はブランチ名を変更する方法も参考にしてください。

ケースB:デフォルトブランチが削除されてしまった

誤削除の復旧
# 管理権限があるなら GitHub UIで
# Settings → General → Default branch → 別ブランチに切替

# その後、削除されたブランチをreflogから復元
git clone https://github.com/user/repo.git
cd repo
git reflog --all | grep "deleted-branch-name"
# 見つかったSHAで復元(権限があれば)

main削除からの復旧は誤ってmaster/mainを削除したときの復旧方法を参照。

ケースC:空リポジトリをcloneした

空リポの挙動

  • 1つもcommitが無いリポはHEADが仮の状態になる
  • warningは出るが、cloneできているのでディレクトリ移動してpush準備できる
  • 最初のcommit+pushでdefault branchが確定する
空リポから初push
cd repo

# Gitのデフォルトブランチ名設定(任意)
git config --global init.defaultBranch main

# 空リポなので git initの代わりに branch を切る
git switch -c main

# 最初のcommit
echo "# My Project" > README.md
git add README.md
git commit -m "feat: initial commit"

git push -u origin main

ケースD:自前GitサーバーのbareリポでHEAD不整合

サーバー側でHEAD整備
ssh git@server
cd /var/git/repo.git

# 現状
cat HEAD
# ref: refs/heads/nonexistent-branch

# 実在ブランチを確認
ls refs/heads/
# main develop

# HEADを実在ブランチに向ける
git symbolic-ref HEAD refs/heads/main

再発防止のチーム運用

同じ問題を起こさないために

  • Branch protection rulesでdefault branchを保護して削除禁止に
  • ブランチ名変更時はdefault branchを先に切替→古い名前を削除、の順序
  • GitHubの「Rename branch」機能を使うとdefault branchが自動追従する
  • 空リポを作る時はInitialize with READMEで最初のcommitを入れておく
  • 自前サーバー運用なら定期的にgit symbolic-ref HEADを確認するスクリプトを入れる
  • cloneスクリプトにはgit remote set-head origin --autoを忘れずに
プロジェクトセットアップスクリプト
#!/bin/bash
# safe-clone.sh
REPO_URL=$1
git clone "$REPO_URL"
cd "$(basename "$REPO_URL" .git)"

# HEADがない場合の自動修復
if ! git symbolic-ref refs/remotes/origin/HEAD 2>/dev/null; then
  git remote set-head origin --auto
fi

# 作業ツリーが空だったら実在ブランチに切替
if [ -z "$(ls -A)" ] || [ "$(ls -A | wc -l)" -eq 1 ]; then
  git switch "$(git remote show origin | grep "HEAD branch" | awk '{print $NF}')"
fi

実践シナリオ

シナリオ① cloneしたらフォルダが空だった

応急対処から本対処
git clone https://github.com/user/repo.git
# warning: remote HEAD refers to nonexistent ref

cd repo
ls
# → 空

# 応急対処:実在ブランチを確認してcheckout
git branch -r
git switch main    # 実在するブランチ名

# 本対処:管理者に伝えてdefault branch設定の更新を依頼

シナリオ② master→main改名を自分で実施

改名時の正しい順序
# STEP 1: ローカルを改名
git branch -m master main

# STEP 2: 新ブランチをpush(upstreamも設定)
git push -u origin main

# STEP 3: GitHub UIでdefault branchをmainに変更(先に!)

# STEP 4: 旧masterを削除
git push origin --delete master

# STEP 5: クライアントのHEAD追跡を更新
git remote set-head origin --auto

改名の詳細はブランチ名を変更する方法を参照。

シナリオ③ 新規リポジトリ作成直後のclone

空リポ→初commitまで
git clone https://github.com/user/empty-repo.git
# warning: you appear to have cloned an empty repository.

cd empty-repo

# デフォルトブランチ名の設定
git config --global init.defaultBranch main
git switch -c main

# 初期ファイル
cat > README.md << "EOF"
# My Project
EOF

git add README.md
git commit -m "feat: initial commit"
git push -u origin main

やってはいけない落とし穴

警告を見てcloneを何度もやり直す

warningが出てもcloneは成功しています。再clone前に、まずcd repoで移動しgit branch -rで実在ブランチを確認してください。再cloneしても同じwarningが出る根本原因(default branch設定ズレ)は解消しません。

リモートを操作せずクライアント側だけで済ませる

git remote set-head origin --auto自分のローカルだけ修復します。リモート側のHEAD設定はそのままなので、他メンバーが新規cloneしたときに同じwarningが出続けます。管理権限があるなら、リモート側のdefault branch設定を正しく直すことが根本解決です。

GitHubの削除済みブランチを復活させずに新ブランチを作る

誤削除したdefault branchを復旧せずに新しい名前を作ると、PR・履歴・webhookなど過去の参照がすべて無効化されます。まずは誤ってmaster/mainを削除したときの復旧方法でreflogから復元を試みてください。

自前サーバーでHEADファイルを直接編集してtypo

bareリポのHEADファイルをechoviで編集してrefs/heads/mianのようにtypoすると、またwarningが再発します。必ずgit symbolic-ref HEAD refs/heads/mainコマンド経由で設定し、git ls-remote --symrefで検証してください。

空リポに.gitignoreや.gitattributesだけpushしてdefault確定したつもりになる

これらのファイルだけでは一部のホスティングサービスで自動的にdefault branchが確定しないことがあります。確実に初期化するならREADME.md等を含めた最初のcommitをしてからpushしてください。

よくある質問

Qcloneしたのにファイルが見えない。失敗した?
A失敗していません。データは.git配下に全部あります。git branch -rで実在するリモートブランチを確認し、git switch <branch>で切り替えればファイルが作業ツリーに展開されます。
Qgit remote set-head origin –auto とは何をする?
Aリモートに問い合わせて現在のdefault branchを自動検出し、クライアント側のrefs/remotes/origin/HEADを更新します。これでgit branch -rの出力や補完などが正常化します。
Q管理者権限が無い。自分だけで解決できる?
Aクライアント側のgit remote set-head origin --autogit switch 実在ブランチで作業自体は進められます。ただしリモート側設定が間違っている根本原因は残るため、管理者へ連絡して修正を依頼するのが理想です。
Q空リポジトリをcloneした時のwarningも同じ対処で良い?
A空リポは「cloneしたが中身が無い」だけなので、cd repoしてブランチを作り最初のcommitをpushすればdefault branchが確定します。以降のcloneでwarningは出なくなります。
QGitHubのdefault branch変更で何が連動する?
A新規cloneのHEAD先・PRのbase自動選択・GitHub Actionsのon: push対象・GitHub Pagesの公開元・webhook等が連動します。Rename機能を使うと多くの連携が自動更新されるので、UIで切り替えるのが無難です。
Q自前Gitサーバーでgit symbolic-refを直すと履歴はどうなる?
A履歴には一切影響しません。HEADファイルの中身(テキスト参照)を書き換えるだけで、commit/ref/objectsは何も変わりません。安全に実行できる修復です。
Qmaster/mainのどちらが今のdefaultか分からない
Agit ls-remote --symref origin HEADが最も確実です。ref: refs/heads/xxxのxxxが現在のdefault branch名です。GitHub UIではリポジトリトップで「X branches」の隣にbranch名表示、Settings → Branches でも確認できます。

関連記事

まとめ

  • 警告の正体は「リモートHEADが存在しないブランチを指している」ことで、cloneは成功している
  • 原因は4種類:default削除/改名/空リポ/bareリポのHEAD不整合
  • 診断はgit ls-remote --symref origin HEADで開始
  • 根本解決はリモート側のdefault branch設定更新(GitHub等のUI)
  • 応急対処はクライアントでgit remote set-head origin --autogit switch
  • 自前サーバーはbareリポでgit symbolic-ref HEAD refs/heads/main
  • 予防:Branch protectionでdefault削除禁止・Rename機能利用・初期commit必須

このwarningに遭遇しても、焦らずにまずcdで中に入り、git branch -rgit ls-remote --symrefで状況を把握すれば、多くは5分以内に作業再開できます。「cloneに失敗した?」と思っても、Gitのデータ自体は無事なので慌てずに診断から始めましょう。根本解決にはリモート側のdefault branch設定更新が必要ですが、クライアント側でも応急対処は十分可能です。予防策と合わせて押さえておけば、チーム内で同じ問題が繰り返し発生することも避けられます。