DEV Community

Ryan Carter
Ryan Carter

Posted on • Originally published at stormcloudy.com

Git Branch Exists on Remote But Won't Show Locally

If a git branch shows up on the remote but git branch -r doesn't list it locally, your fetch refspec is almost always scoped to a single branch instead of all branches. Fix it with one config change: git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*" followed by git fetch origin --prune. This commonly happens after shallow clones, certain CI checkouts, and clones run with --single-branch.

The full diagnosis takes about two minutes — start by confirming the branch exists on the remote, then walk through the three fixes below in order.

Confirm the branch actually exists on the remote

First, bypass your local cache entirely and ask the remote directly:

git ls-remote origin
Enter fullscreen mode Exit fullscreen mode

If your branch shows up here but not in git branch -r, your local remote-tracking refs are stale or incorrectly scoped. That's the problem — and it's fixable.

If it doesn't show up here either, the issue is permissions or a wrong remote URL. Check with git remote -v and make sure origin points where you think it does.

Fix 1: Fetch with prune

The simplest thing to try first:

git fetch origin --prune
Enter fullscreen mode Exit fullscreen mode

The --prune flag removes stale remote-tracking refs and re-syncs. Sometimes that's all it takes.

Fix 2: Fetch the specific branch by name

If a general fetch isn't picking it up, fetching by name often forces it:

git fetch origin your-branch-name
Enter fullscreen mode Exit fullscreen mode

Fix 3: Check your fetch refspec

This is the most common root cause when the above don't work. Check your git config:

cat .git/config
Enter fullscreen mode Exit fullscreen mode

Look at the [remote "origin"] section. It should look like this:

[remote "origin"]
    url = git@github.com:you/your-repo.git
    fetch = +refs/heads/*:refs/remotes/origin/*
Enter fullscreen mode Exit fullscreen mode

The fetch line is the refspec — it tells git which branches to track. The * wildcard means "all branches."

If yours looks like this instead:

fetch = +refs/heads/main:refs/remotes/origin/main
Enter fullscreen mode Exit fullscreen mode

That's your problem. The refspec is scoped to a single branch, so git is only tracking main and ignoring everything else. This happens with shallow clones, some CI checkout configurations, and certain git clone flags.

Fix it by updating the refspec:

git config remote.origin.fetch "+refs/heads/*:refs/remotes/origin/*"
git fetch origin
Enter fullscreen mode Exit fullscreen mode

After that, git branch -r should show all remote branches.

Quick reference

Symptom Likely cause Fix
Branch in ls-remote but not branch -r Stale or scoped refspec Update refspec, re-fetch
Branch missing after git fetch Stale tracking refs git fetch origin --prune
Branch missing entirely from ls-remote Wrong remote URL or permissions Check git remote -v

The ls-remote check is always the right first step — it tells you immediately whether the problem is on the remote side or local side, which cuts the diagnosis in half.

FAQ

Why does git fetch not pick up the new branch?

Either your remote-tracking refs are stale (fix with --prune), or your fetch refspec is scoped to a single branch (the most common cause when --prune doesn't help). The refspec lives in .git/config under [remote "origin"].

What is a fetch refspec and why does it matter?

A refspec tells git which remote refs to download and where to store them locally. The default +refs/heads/*:refs/remotes/origin/* means "fetch every branch on the remote into origin/* locally." If yours is scoped to a specific branch (e.g. refs/heads/main:refs/remotes/origin/main), git will only ever track that one branch.

How did my refspec get scoped to a single branch?

Common causes: cloning with --single-branch, cloning with --branch <name> plus --single-branch, GitHub Actions checkouts that use fetch-depth: 1 and a specific ref, and some Dependabot/CI tools that explicitly scope the refspec to save bandwidth.

Is git fetch --all --prune the same as fixing the refspec?

No. --all fetches from every configured remote (relevant if you have multiple), and --prune removes stale remote-tracking refs — but neither expands a refspec that's scoped to a single branch. You still have to fix the refspec itself.

Will fixing the refspec break anything?

No. It just tells git to track all branches instead of one. You won't lose history, refs, or local branches. The next git fetch origin will pull down all the previously-ignored remote branches.

Top comments (0)