This Git warning occurs when a short reference name (like 'feature') matches multiple refs, such as a branch and a tag with the same name. Use the full refname or remove the duplicate ref.
This warning appears when Git finds multiple references matching the same name in your repository. Git stores references in several namespaces: `refs/heads/` for branches, `refs/tags/` for tags, `refs/remotes/` for remote-tracking branches, and others. When you use a short reference name like "feature", Git searches through these namespaces in a specific order. If it finds "feature" in more than one location (for example, both `refs/heads/feature` and `refs/tags/feature`), it issues this ambiguous refname warning. While Git will typically proceed using its priority rules (tags are checked before branches in the lookup order, so a tag can win over a branch of the same name), the warning indicates that you may not be working with the reference you intended. This can lead to unexpected behavior, especially during merges, checkouts, or when setting upstream branches.
First, find all references that match the ambiguous name:
# Show all refs matching the name
git show-ref feature
# Example output showing the conflict:
# a1b2c3d refs/heads/feature
# e4f5a6b refs/tags/featureYou can also search more broadly:
# Find all references containing the name
git show-ref | grep feature
# List all branches and tags
git branch -a
git tag -lThis reveals whether the ambiguity is between a branch and a tag, or involves other reference types.
To avoid ambiguity in your commands, use the full reference path. This is non-destructive and is the safest first move:
# Checkout the branch (not the tag)
git checkout refs/heads/feature
# Checkout the tag (not the branch)
git checkout refs/tags/feature
# Merge using an explicit branch reference
git merge refs/heads/feature
# Compare using explicit references
git diff refs/heads/feature refs/tags/feature
# Set upstream with an explicit remote-tracking reference
git branch --set-upstream-to=refs/remotes/origin/main mainYou can also use shorter but still unambiguous forms:
# Use the heads/ prefix for branches
git checkout heads/feature
# Use the tags/ prefix for tags
git checkout tags/featureIf the tag is no longer needed or was created by mistake, delete it. Before deleting, confirm what it points to with git show refs/tags/feature so you do not lose a release marker you still need.
# Delete the local tag
git tag -d feature
# If the tag also exists on the remote, delete it there using the refspec form
git push origin :refs/tags/feature
# Equivalent explicit form
git push origin --delete refs/tags/featureNote: git push origin --delete tag feature is not valid syntax — use one of the two forms shown above.
After deleting, verify the ambiguity is resolved:
git show-ref feature
# Should now show only one referenceIf the branch is the duplicate that should be removed, first confirm what each ref points to so you delete the right one:
# Compare what each ref points to before deleting
git log -1 refs/heads/feature
git log -1 refs/tags/featureThen delete the branch:
# Delete the local branch (safe: refuses if unmerged)
git branch -d feature
# If you have verified the work is preserved elsewhere, force-delete
# WARNING: -D discards unmerged commits on this branch. Confirm first.
git branch -D feature
# If it is a remote branch
git push origin --delete featureOccasionally a typo or a failed operation leaves a stray ref. Inspect them first:
# Inspect refs (works for both loose and packed refs)
git for-each-ref | grep feature
# Loose ref files live under .git/refs/
ls -la .git/refs/heads/
ls -la .git/refs/tags/If you find an erroneous ref, remove it with Git rather than deleting files by hand. git update-ref -d is safe, atomic, and also handles refs that are stored in packed-refs (which manual rm would miss):
# Delete a reference safely
git update-ref -d refs/heads/origin/featureAvoid rm .git/refs/... directly: it leaves packed refs and reflogs inconsistent and will not work for packed refs.
If you need to keep both references, rename the branch so the names are unique:
# Rename the local branch
git branch -m feature feature-branch
# Update the remote: push the new name and set upstream
git push origin -u feature-branch
# Delete the old remote branch once the new one exists
git push origin --delete featureRecommended naming conventions to avoid collisions:
| Type | Convention | Example |
|------|------------|---------|
| Feature branch | feature/name | feature/user-auth |
| Release branch | release/version | release/1.2.0 |
| Release tag | vX.Y.Z | v1.2.0 |
| Hotfix branch | hotfix/name | hotfix/login-fix |
Using prefixes like feature/ and release/ for branches and v for tags naturally prevents name collisions.
A common mistake is creating a local branch named like origin/feature instead of checking out the remote-tracking branch:
# This creates a local branch literally named 'origin/feature' (wrong)
git branch origin/feature
# This creates a local 'feature' branch tracking the remote (correct)
git checkout feature # or: git switch featureTo fix the mistake, delete the incorrectly named local branch:
# -D is needed because Git treats this as an unmerged branch.
# Confirm with 'git log -1 origin/feature' first; the real remote ref
# is refs/remotes/origin/feature and is unaffected.
git branch -D origin/feature
# Now the short name resolves cleanly
git switch featureVerify the fix:
git show-ref | grep feature
# Should show only the expected refs### Git reference resolution order
When you provide a short refname, Git resolves it against these patterns in order (see gitrevisions):
1. $GIT_DIR/<refname> (e.g. HEAD, FETCH_HEAD, MERGE_HEAD, CHERRY_PICK_HEAD)
2. refs/<refname>
3. refs/tags/<refname>
4. refs/heads/<refname>
5. refs/remotes/<refname>
6. refs/remotes/<refname>/HEAD
The first match wins. Note that tags (rule 3) are checked before branches (rule 4), so when a tag and a branch share a name, the tag is what a bare short name resolves to — and Git warns because that is rarely what you intended.
### Checking for ambiguous refs repository-wide
# List names that exist as both a branch and a tag
git for-each-ref --format='%(refname:short)' refs/heads refs/tags | \
sort | uniq -dAny output indicates names that are ambiguous.
### Preventing ambiguous refs in team workflows
Establish naming conventions:
- Use a v prefix for version tags: v1.0.0, v2.1.3
- Use directory-style branch names: feature/X, bugfix/Y
- Never name a tag the same as a branch
You can also add a server-side pre-receive hook that rejects a push which would create a name existing as both a branch and a tag:
#!/bin/bash
while read oldrev newrev refname; do
shortname=${refname##*/}
if git show-ref --verify --quiet "refs/heads/$shortname" && \
git show-ref --verify --quiet "refs/tags/$shortname"; then
echo "Error: '$shortname' would exist as both a branch and a tag (ambiguous ref)"
exit 1
fi
done### The core.warnAmbiguousRefs setting
core.warnAmbiguousRefs is true by default. Setting it to false only suppresses the warning — it does not change which ref Git picks, and the underlying ambiguity (and its risk of resolving to the wrong object) remains. Prefer resolving the ambiguity over hiding the warning.
### Remote-tracking branch ambiguity
A related case involves a local branch accidentally created with a remote-style name:
refs/heads/origin/feature # local branch (mistake)
refs/remotes/origin/feature # remote-tracking branch (correct)This usually happens when someone runs git branch origin/feature instead of git switch feature. Delete the stray local branch with git branch -D origin/feature (see step 7).
error: The following untracked working tree files would be overwritten by checkout
Untracked working tree files would be overwritten by checkout
error: remote origin already exists
How to fix 'fatal: remote origin already exists' in Git
pathspec did not match any file(s) known to git
How to fix 'pathspec did not match any file(s) known to git' in Git
ssh: Could not resolve hostname github.com: Name or service not known
How to fix 'ssh: Could not resolve hostname github.com: Name or service not known' in Git
error: insufficient permission for adding an object to repository database .git/objects
How to fix "insufficient permission for adding an object to repository database" in Git