What this error means
Git could not find the branch, tag, or ref path you asked it to fetch, pull, or checkout from the remote. Typical causes:
- The branch/tag does not exist on the remote.
- Wrong name (typo or case mismatch) or wrong namespace (heads vs tags).
- Remote URL points to a different repository.
- Shallow/partial fetch omitted the ref.
- Misconfigured refspec in .git/config or CI.
Common contexts: git fetch origin feature-x, git pull origin develop, git checkout tags/v1.2.0, or CI fetching PR refs.
Quickstart (most cases)
- Verify the ref exists on the remote:
# Branches
git ls-remote --heads origin feature-x
# Tags
git ls-remote --tags origin v1.2.0
- If no output, the ref is not on the remote.
- Refresh your local view of the remote:
git fetch origin --prune --tags
- Use the correct name and namespace:
# Branch
git fetch origin feature-x:feature-x && git switch feature-x
# Tag
git fetch origin refs/tags/v1.2.0 && git checkout tags/v1.2.0
- If the branch doesn’t exist remotely but you want it there:
git switch -c feature-x
# commit something
git push -u origin feature-x
Minimal working example (reproduce and fix)
# 1) Create a bare remote with only 'main'
rm -rf /tmp/remote.git /tmp/work
git init --bare /tmp/remote.git
git clone /tmp/remote.git /tmp/work
cd /tmp/work
git commit --allow-empty -m "init"
# publish 'main'
git push -u origin HEAD:refs/heads/main
# 2) Try to fetch non-existent 'develop' (triggers error)
git fetch origin develop
# fatal: couldn't find remote ref develop
# 3) Two fixes:
# A) Use an existing remote branch
git fetch origin main:main && git switch main
# B) Create 'develop' on remote and then fetch it
git switch -c develop
git commit --allow-empty -m "start develop"
git push -u origin develop
# Now fetching works
git fetch origin develop:develop && git switch develop
Diagnose by scenario
| Symptom | Likely cause | What to do |
|---|---|---|
fatal: couldn't find remote ref feature-x | Branch doesn’t exist on remote | git ls-remote --heads origin, push the branch or use an existing one |
fatal: couldn't find remote ref v1.2.0 | Tag missing or not fetched | git ls-remote --tags origin, git fetch --tags, or create the tag |
| Works locally, CI fails | Shallow or selective fetch in CI | Add explicit fetch refspec for needed branches/tags, adjust depth |
| Only fails on Linux remote | Case mismatch (Feature vs feature) | Use exact case; Git refs are case-sensitive on most servers |
| After default branch rename | Stale origin/HEAD or wrong branch name | git remote set-head origin -a, verify main vs master |
| New remote URL, same local checkout | Wrong origin URL | git remote -v, git remote set-url origin <correct-url> |
Step-by-step troubleshooting
- Confirm the remote and URL:
git remote -v
- See what the remote actually has:
# All refs (heads, tags, etc.)
git ls-remote origin | head -n 20
# Specific branch or tag
git ls-remote --heads origin <branch>
git ls-remote --tags origin <tag>
- Refresh local refs and prune stale ones:
git fetch origin --prune --tags
- Specify full refnames when in doubt:
# Branch
git fetch origin refs/heads/feature-x:refs/remotes/origin/feature-x
# Tag
git fetch origin refs/tags/v1.2.0:refs/tags/v1.2.0
- Check for typos and case sensitivity:
Feature-X≠feature-xon most servers.- Ensure you are not mixing
refs/heads/(branches) withrefs/tags/(tags).
- Review refspecs in .git/config (advanced):
[remote "origin"]
url = git@host:org/repo.git
fetch = +refs/heads/*:refs/remotes/origin/*
# Optional: fetch PR refs or additional namespaces if your platform supports them
# fetch = +refs/pull/*/head:refs/remotes/origin/pr/*
[fetch]
prune = true
- Adjust shallow/partial clones (CI):
# Fetch only what you need, but include the target ref
# Example: fetch a single branch with depth
git fetch --depth 50 origin refs/heads/feature-x:refs/remotes/origin/feature-x
Common fixes by task
- Pulling a branch that is new locally:
git push -u origin <branch>thengit switch <branch>.
- Checking out a tag that isn’t fetched:
git fetch --tagsorgit fetch origin refs/tags/<tag>thengit checkout tags/<tag>.
- Sync after default branch rename:
git fetch origin --pruneandgit remote set-head origin -a; update branch names in scripts.
- CI fetching a PR:
- Use provider-specific ref (e.g.,
refs/pull/123/head) or fetch the merge ref if available.
- Use provider-specific ref (e.g.,
Pitfalls
- Assuming tags are always fetched: by default only tags reachable from fetched commits arrive; use
git fetch --tagsor explicit tag ref. - Overwriting refspecs: replacing instead of adding lines in .git/config can hide refs.
- Case mismatch across OS: Windows/macOS may not reveal a case error that fails on Linux CI.
- Detached HEAD confusion:
HEADis not a branch; use explicit branch names.
Performance notes
- Prefer selective fetch over fetching all refs in CI:
git fetch origin refs/heads/<branch>:refs/remotes/origin/<branch>
- Use shallow depth judiciously; if you need tags or multiple branches, either increase depth or fetch specific refs explicitly.
- Enable pruning to keep remote-tracking branches clean:
git config fetch.prune true
- Avoid unnecessary
--tagson every fetch if you don’t use tags; fetch them only when needed.
FAQ
Why does pushing work but pulling fails with this error?
git push origin <branch>creates the remote branch;git pull origin <branch>fails only if that branch didn’t exist previously or you mistyped it.
How do I fetch a single tag without all tags?
git fetch origin refs/tags/v1.2.3:refs/tags/v1.2.3thengit checkout tags/v1.2.3.
How do I verify the exact ref name the server exposes?
git ls-remote originand look forrefs/heads/<branch>orrefs/tags/<tag>.
Can a bad remote URL cause this?
- Yes. If
originpoints to the wrong repo, the ref likely won’t exist. Usegit remote set-url origin <correct-url>.
- Yes. If