Gitの 'cannot lock ref' エラーの修正:macOSにおける大文字・小文字の区別の処理

intermediate🍎 macOS2026-05-02| macOS (APFS/HFS+ ファイルシステム), Git (すべてのバージョン)

Error Message

error: cannot lock ref 'refs/heads/feature/abc': 'refs/heads/feature/ABC' exists; cannot create 'refs/heads/feature/abc'
#git#ファイルシステム#大文字小文字の区別#macos

問題の背景

コーディングに集中している最中、すべてが順調に進んでいて、最新の変更を取り込もうと git fetch を実行したとします。しかし、クリーンなアップデートの代わりに、Gitが突然停止します。「参照のロック(locking references)」に関するイライラするようなエラーが表示されます。ブランチ名を確認しても問題なさそうに見えますが、Gitは一向に動作を受け付けてくれません。

これはGitとmacOSの間の根本的な不一致が原因で発生します。Linuxは 'File.txt' と 'file.txt' を2つの異なるエンティティとして扱いますが、macOSは 大文字・小文字を区別しないが、維持はする(case-insensitive but case-preserving) という性質を持っています。'Feature' という名前のフォルダが既に存在する場合、同じディレクトリ内に 'feature' という名前の別のフォルダを作成することはできません。Macにとっては、それらは同じパスなのです。

実際のエラー内容

error: cannot lock ref 'refs/heads/feature/abc': 'refs/heads/feature/ABC' exists; cannot create 'refs/heads/feature/abc'

なぜこれが発生するのか

Gitは単なるツールではなく、ファイルシステムを使用してデータを保存するデータベースです。デフォルトでは、ローカルブランチを .git/refs/heads/ ディレクトリ内の個別のファイルとして保存します。たとえば feature/ABC という名前のブランチの場合、Gitは feature というフォルダを作成し、その中に ABC というファイルを作成します。

コンフリクトは、チームメイトが feature/abc (小文字)をサーバーにプッシュしたときに始まります。あなたがそれをプルしようとすると、Gitは abc という名前の新しいファイルを書き込もうとします。しかし、macOSは ABCabc を同じファイルと見なすため、Gitはループに陥ります。参照は既に存在しているのに、データが一致しないことに気づき、「cannot lock ref」の失敗につながります。

ロック競合の修正方法

1. 古くなったリモート参照の削除(Prune)

多くの場合、ブランチの「古い」バージョンは既にサーバー上で削除または名前変更されていますが、ローカルマシンがその参照の残骸を保持し続けています。Gitにメモリを同期するよう指示する必要があります。

git remote prune origin

このコマンドは手軽な整理ツールです。リモートに存在しなくなった origin/ 追跡ブランチを削除します。feature/ABC がリモート追跡ブランチのみであった場合、通常はこれで即座に解決します。

2. ローカルの競合を削除する

pruneで解決しない場合、原因はローカルディスク上に存在するブランチである可能性が高いです。衝突の原因となっている具体的な名前を見つける必要があります。

git branch -a | grep -i "feature/abc"

feature/abcfeature/ABC の両方が表示される場合、どちらかを削除する必要があります。Macではこれらを区別できないため、チームの命名規則に合わない方を削除してください。

# 競合しているローカルブランチを強制削除する
git branch -D feature/ABC

3. .gitフォルダの直接クリーンアップ

ファイルシステムの状態が悪化し、標準のGitコマンドでは残骸を消去できないことがあります。このような稀なケースでは、問題のあるファイルを手動で削除できます。これはGitの「内部臓器」を触る作業なので、慎重に行ってください。

  • プロジェクトのルートでターミナルを開きます。
  • 非表示の参照フォルダに移動します:cd .git/refs/heads/
  • プレフィックス(例:feature)に一致するディレクトリを探します。
  • 競合するブランチ名に一致するファイルを削除します。

コマンド例:

rm .git/refs/heads/feature/ABC

ファイルが削除されたら、再度フェッチを試してください:git fetch --prune

4. 「最終手段」:git pack-refs

数多くのブランチがあり、エラーが頻発する場合は pack-refs を使用します。このコマンドは、何百もの小さなブランチファイルを packed-refs という単一のフラットなテキストファイルに圧縮します。

git pack-refs --all

ブランチがディスク上の個別のファイルではなく、テキストファイル内の行として扱われるようになるため、macOSのファイルシステムの制限が適用されなくなります。これにより、大文字・小文字の区別の問題を事実上完全に回避できます。

確認作業

修正が正しく適用されたか確認するために、最新の変更をプルします:

git pull origin main
git fetch --all

エラーなくコマンドが終了すれば完了です。最後に git branch -a を実行し、正しい大文字・小文字のブランチのみが残っていることを確認してください。

今後のための対策

  • 小文字に統一する: トラブルを未然に防ぎましょう。ブランチ名には小文字のみを使用するようチーム内で合意してください(例:Feature/Fix-Header ではなく feature/fix-header)。
  • デフォルトでPruneする: git config --global fetch.prune true を実行して、自動的に古い参照を削除するように設定します。これにより、手間をかけずにローカル環境をクリーンに保てます。
  • 環境の違いを意識する: Macは大文字・小文字を区別しませんが、Linuxのプロダクションサーバーなどは区別します。大文字・小文字の違いは常に意味のあるバグとして扱いましょう。

Related Error Notes