The git for-each-ref command returns no matches when the pattern provided doesn't match any existing references in the repository. This commonly occurs due to incorrect ref path patterns or shell quoting issues.
The git for-each-ref command is designed to iterate over all refs that match a given pattern and display them in a specified format. When you see "no refs match pattern" or receive empty output, it means the pattern you provided doesn't correspond to any existing references in your repository. Unlike git branch which operates on short branch names (like "main" or "feature-branch"), git for-each-ref requires full reference paths. This means you need to specify the complete ref path like refs/heads/main instead of just main. The command uses fnmatch(3) pattern matching, which expects glob-style patterns with the full reference namespace. This behavior is by design - git for-each-ref silently returns empty results when patterns don't match, rather than throwing an error. This can be confusing when you're expecting results based on patterns that work with other Git commands.
First, check what refs are actually available in your repository:
# List all refs
git for-each-ref
# List only branches
git for-each-ref refs/heads
# List only tags
git for-each-ref refs/tags
# List remote branches
git for-each-ref refs/remotesThis will show you the full ref paths and confirm refs exist before attempting pattern matching.
When filtering refs, always use the full reference path:
# ❌ Wrong - short name won't work
git for-each-ref "main"
git for-each-ref "feature-*"
# ✅ Correct - use full ref path
git for-each-ref "refs/heads/main"
git for-each-ref "refs/heads/feature-*"
# For all branches containing "hotfix"
git for-each-ref "refs/heads/*hotfix*"
# For nested branches
git for-each-ref "refs/heads/**/*hotfix*"The pattern must match against the complete ref name starting from refs/.
Shell interpretation of wildcards varies by shell type. Always quote patterns to prevent premature expansion:
# Bash/sh - use single or double quotes
git for-each-ref 'refs/heads/*'
git for-each-ref "refs/heads/*"
# For options with wildcards (like --sort)
git for-each-ref '--sort=-*authordate' refs/heads
# Windows cmd.exe - use double quotes only
git for-each-ref "refs/heads/*"On zsh and csh, unquoted wildcards in options (like --sort=-*authordate) will cause "no matches found" errors from the shell itself.
Add a format string to see exactly what refs are being matched:
# Show ref names and author dates
git for-each-ref --format='%(refname) - %(authordate)' 'refs/heads/*'
# Show just the short ref names
git for-each-ref --format='%(refname:short)' refs/heads
# Count how many refs match
git for-each-ref --count=10 refs/headsThis helps debug whether your pattern is matching anything at all.
Start with broad patterns and narrow down:
# Start broad - all branches
git for-each-ref refs/heads
# Add simple wildcard
git for-each-ref 'refs/heads/feature-*'
# Add complex glob patterns only after simple ones work
git for-each-ref 'refs/heads/**/release-*'This helps identify whether the issue is with the pattern syntax or something else.
## Pattern Matching Internals
The git for-each-ref command uses fnmatch(3) for pattern matching, which supports standard glob patterns:
- * matches any sequence of characters
- ? matches a single character
- [...] matches character classes
- **/ matches across directory boundaries
Patterns match either completely or from the beginning up to a slash. This means refs/heads/feature will match both refs/heads/feature exactly and refs/heads/feature/sub-branch.
## Performance Considerations
On large repositories with thousands of refs, using --contains HEAD can be extremely slow (10+ seconds). If you need to find which branches contain a specific commit, consider:
- Using --merged or --no-merged instead
- Limiting with --count
- Filtering by date with --sort=-committerdate and --count=N
## Shell-Specific Issues
Zsh/Csh: These shells perform aggressive glob expansion before passing arguments to commands. Wildcards in option values (like --sort=-*authordate) must be quoted or escaped.
Windows cmd.exe: Single quotes are treated as literal characters, not string delimiters. Always use double quotes on Windows.
## Field References
If you reference a field that doesn't apply to a particular ref type (e.g., %(taggerdate) on a branch), for-each-ref returns an empty string rather than an error. This is intentional for format compatibility.
warning: 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