深夜2時のブランチ・ゴースト
深夜2時、本番デプロイまであと15分。リードエンジニアからSlackが届きます。「feature/login-fix に緊急修正をプッシュした。今すぐレビューしてくれ。」急いで git checkout feature/login-fix と入力し、すぐに切り替わるのを期待しますが、Gitからは無情にも次のようなエラーが返ってきます。
error: pathspec 'feature/login-fix' did not match any file(s) known to git
チームメイトが本当にコードをプッシュしたのか、まずは疑いたくなるでしょう。しかし、GitHubのウェブインターフェース上には確かにそのブランチが存在しています。では、なぜ手元のターミナルは認識してくれないのでしょうか?これは、Gitが分散システムであるために起こります。ローカルリポジトリはあくまである時点のスナップショットであり、現時点ではサーバー上の最新の状態と同期が取れていないのです。
デバッグ手順:ローカルインデックスの確認
当てずっぽうにコマンドを打つ前に、ローカル環境が何を把握しているか確認しましょう。次のコマンドを実行して、ローカルGitに登録されている全ブランチを表示します。
git branch -a
出力を確認してください。もし remotes/origin/feature/login-fix が見当たらない場合、ローカルのインデックスが古くなっています。Gitはコマンドを実行するたびにサーバーに問い合わせるわけではなく、ローカルのキャッシュに依存しています。新しいブランチが作成されてからキャッシュが更新されていない場合、Gitはその「pathspec(パススペック)」、つまりブランチ名を、ただのタイポか存在しないファイルパスだと判断してしまいます。
大文字・小文字の区別に注意
綴りは重要です。WindowsやmacOSのファイルシステムは多くの場合大文字・小文字を区別しませんが、Gitの内部参照システムは別です。feature/Login-Fix と feature/login-fix は異なるものとして扱われます。もしリモートで「L」が大文字なのに、小文字で入力してしまった場合、何度やっても pathspec エラーが発生します。PRから直接名前をコピー&ペーストするのが最も確実な方法です。
主な解決策:強制同期
10回中9回は、Gitにサーバーと通信させ、最新の状態にマップを更新させることで解決します。
1. 最新のメタデータをフェッチする
git fetch origin
このコマンドを実行すると、'origin' という名前のリモートから最新のポインタをダウンロードします。現在のコードを壊したりマージしたりすることはありません。単に remotes/origin/* の参照を更新するだけです。フェッチが完了したら、再度切り替えを試してください。
git checkout feature/login-fix
2. リモートブランチを明示的にマッピングする
ローカルの設定が特殊な場合など、自動マッピングが失敗することがあります。その場合は短縮形を使わず、ブランチがどこにあるのかをGitに直接指示できます。
git checkout -b feature/login-fix origin/feature/login-fix
これにより、新しいローカルブランチが作成され、サーバー上の特定のリモート追跡ブランチに直接リンクされます。
例外ケース:シャロークローン(Shallow Clone)の問題
GitHub ActionsやJenkinsなどのCI/CDパイプラインで作業していませんか?これらの環境では、時間と帯域を節約するために「シャロークローン」(--depth 1)がよく使われます。デフォルトブランチの最新コミットのみをダウンロードすることで数百MBの履歴を節約できますが、その代わりGitは他のブランチを一切認識できなくなります。
切り捨てられた履歴を修正するには、リポジトリを「アンシャロー(unshallow)」にする必要があります。
git fetch --unshallow
# あるいは、フル履歴は不要で全リモートブランチが必要な場合:
git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*"
git fetch origin
検証:修正の確認
ターミナルに赤いエラーではなく、成功メッセージが表示されれば完了です。
Branch 'feature/login-fix' set up to track remote branch 'feature/login-fix' from 'origin'.
Switched to a new branch 'feature/login-fix'
最後に念のため git status を実行しましょう。正しいブランチにおり、リモートと完全に同期されていることが確認できるはずです。
学んだこと
- Gitはオフラインが基本: ターミナルはあくまでローカルのスナップショットです。ブランチが見つからないときは、まず
git fetchを試しましょう。 - 大文字・小文字の区別: 「見えない」タイポを避けるため、ブランチ名は常にソース(GitHub等)から直接コピーしましょう。
- シャロークローンの落とし穴: 高速化には代償があります。
--depthを使用している場合、明示的に指示しない限りGitは他のブランチを認識しません。

