This Git error occurs when you try to checkout, delete, or reference a tag that doesn't exist in your repository. The tag may have never been pushed to the remote, was deleted, or hasn't been fetched yet. Fix it by fetching tags from the remote or verifying the tag name.
The "tag not found" error occurs when Git cannot locate a tag with the name you specified. This typically happens when running commands like `git checkout v1.0.0`, `git tag -d v1.0.0`, or `git show v1.0.0` where the tag name doesn't exist in your local repository. Git tags are references that point to specific commits, commonly used to mark release points (e.g., v1.0.0, v2.1.3). Unlike branches, tags are static - they always point to the same commit. Tags are stored in `.git/refs/tags/` and can be either lightweight (just a pointer) or annotated (full Git objects with metadata). This error is particularly common in CI/CD environments where repositories are cloned with limited depth or without fetching tags. It also occurs when team members create tags locally but forget to push them to the remote, or when checking out a tag that was deleted.
First, check what tags actually exist in your repository:
# List all local tags
git tag
# List tags matching a pattern
git tag -l "v1.*"
# List tags with commit messages (annotated tags)
git tag -n
# Search for tags containing specific text (case-insensitive)
git tag -l | grep -i "release"Tag names are case-sensitive. A tag named V1.0.0 is different from v1.0.0. Make sure you're using the exact name shown in the output.
By default, git fetch and git pull only download tags that are reachable from fetched commits. To get all tags:
# Fetch all tags from origin
git fetch --tags
# Fetch all tags from all remotes
git fetch --all --tags
# Fetch a specific tag
git fetch origin tag v1.0.0After fetching, verify the tag is available:
git tag -l "v1.0.0"Note: Starting with Git 1.9/2.0, git fetch --tags fetches tags in addition to the normal fetch, not instead of it.
The tag might not exist on the remote at all. Verify by listing remote tags:
# List all tags on the remote
git ls-remote --tags origin
# Look for a specific tag
git ls-remote --tags origin | grep "v1.0.0"
# Alternative: list tags from remote URL
git ls-remote --tags https://github.com/user/repo.gitIf the tag doesn't appear in the output, it was never pushed or was deleted. Contact the repository maintainer or check the repository's release page.
Shallow clones (created with --depth) may not have access to all tags. This is common in CI/CD environments:
# Check if your repository is shallow
git rev-parse --is-shallow-repository
# Unshallow the repository to get full history and tags
git fetch --unshallow
# Or just fetch tags with full depth
git fetch --tags --depth=1000For CI/CD pipelines, configure a full clone:
GitHub Actions:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # Full clone with all history and tags
fetch-tags: trueGitLab CI:
variables:
GIT_DEPTH: 0
GIT_STRATEGY: cloneThere are several ways to checkout a tag in Git:
# Checkout tag (creates detached HEAD state)
git checkout v1.0.0
# Or explicitly reference tags namespace
git checkout tags/v1.0.0
# Create a new branch from the tag (recommended)
git checkout -b release-v1.0.0 v1.0.0
# Using git switch (Git 2.23+)
git switch --detach v1.0.0Important: Checking out a tag puts you in "detached HEAD" state. If you need to make changes, create a branch from the tag first.
Note: Don't use origin/v1.0.0 syntax for tags - that's for branches. Tags don't have the origin/ prefix.
If you created a tag locally but it doesn't exist on the remote, you need to push it:
# Push a single tag
git push origin v1.0.0
# Push all local tags
git push origin --tags
# Push only annotated tags (recommended for releases)
git push origin --follow-tagsBy default, git push doesn't transfer tags. You must explicitly push them. Many teams configure hooks or CI/CD to automatically push tags when pushing commits.
If you have multiple remotes, the tag might exist on a different remote:
# List all configured remotes
git remote -v
# Fetch tags from all remotes
git fetch --all --tags
# Check which remote has the tag
git ls-remote --tags origin | grep v1.0.0
git ls-remote --tags upstream | grep v1.0.0
# Fetch tag from a specific remote
git fetch upstream tag v1.0.0Remember that tags are global in your local repository - once fetched, a tag exists regardless of which remote it came from.
If tags were deleted from the remote but still exist locally, you can sync your local tags:
# Prune tags that were deleted on remote
git fetch --prune --prune-tags origin
# Or manually delete a local tag
git tag -d v1.0.0
# Delete a remote tag (if you have permission)
git push --delete origin v1.0.0
# Or
git push origin :refs/tags/v1.0.0The --prune-tags option removes local tags that no longer exist on the remote.
### How Git Stores Tags
Git stores tags as files in .git/refs/tags/. Each file contains the SHA-1 hash of the commit (for lightweight tags) or tag object (for annotated tags):
# View what a tag points to
cat .git/refs/tags/v1.0.0
# Or use git commands
git rev-parse v1.0.0
# Show full tag information (annotated tags)
git show v1.0.0
# Show tag object type
git cat-file -t v1.0.0
# "commit" for lightweight, "tag" for annotated### Lightweight vs Annotated Tags
Lightweight tags are simple pointers to commits:
git tag v1.0.0Annotated tags are full Git objects with metadata:
git tag -a v1.0.0 -m "Release version 1.0.0"Annotated tags are recommended for releases because they store:
- Tagger name and email
- Date
- Message
- Optional GPG signature
### Inspecting Remote Tags Without Fetching
Use git ls-remote to query remote refs without downloading:
# List all tags on remote
git ls-remote --tags origin
# Check if specific tag exists (returns SHA or nothing)
git ls-remote origin refs/tags/v1.0.0### Using skopeo for Tag Inspection
For advanced tag management with container registries:
# Install skopeo
# Ubuntu: apt install skopeo
# macOS: brew install skopeo
# List tags (for container images)
skopeo list-tags docker://nginx### Git Describe and Tags
git describe uses tags to create human-readable names for commits:
# Get description based on tags
git describe
# Output: v1.0.0-5-g1234abc (5 commits after v1.0.0)
# Only use annotated tags
git describe --tags
# If no tags exist, this will fail with "fatal: No names found"### Configuring Automatic Tag Fetching
To always fetch tags with pull:
# Configure for this repository
git config remote.origin.tagOpt --tags
# Configure globally
git config --global fetch.prune true
git config --global fetch.pruneTags true### Semantic Versioning Tags
When working with semantic versioning (SemVer), use consistent tag naming:
# Good: consistent prefixes
v1.0.0, v1.0.1, v2.0.0
# Avoid: inconsistent naming
1.0.0, v1.0.1, version-2.0.0, release/3.0.0List tags sorted by version:
git tag --sort=-v:refnamewarning: BOM detected in file, this may cause issues
UTF-8 Byte Order Mark (BOM) detected in file
fatal: Server does not support --shallow-exclude
Server does not support --shallow-exclude
warning: filtering out blobs larger than limit
Git partial clone filtering large blobs warning
fatal: Server does not support --shallow-since
Server does not support --shallow-since in Git
kex_exchange_identification: Connection closed by remote host
Connection closed by remote host when connecting to Git server