What this error means
Git prints fatal: Not a valid object name: master/main when it cannot resolve the revision string master/main into a commit, tag, or tree. This typically happens when:
- You meant origin/main (a remote branch) but typed master/main.
- You meant a branch range (master..main or master...main) but used a slash.
- The branch you referenced (master or main) does not exist locally or remotely.
- The clone is shallow or missing refs, so the branch tip is unavailable.
This guide shows quick fixes, root-cause diagnosis, and robust patterns suitable for DevOps scripts and CI pipelines.
Quickstart (most common fixes)
- If you meant the remote main branch:
# Make sure refs are up to date
git fetch origin --prune
# Use origin/main (not master/main)
git rev-parse --verify origin/main
- If you meant to diff master and main:
# Use two or three dots, not a slash
git diff master..main # or: git diff master...main
- If your repo’s default branch is main but scripts assume master:
git fetch origin --prune
# Create a local tracking branch if missing
git checkout -B main origin/main
- If you want the default branch programmatically:
# Discover remote default branch and use it
git remote set-head origin -a
BASE=$(git symbolic-ref --quiet --short refs/remotes/origin/HEAD | sed 's|^origin/||')
Minimal working example (reproduce and fix)
#!/usr/bin/env bash
set -euo pipefail
# Reproduce
rm -rf /tmp/g-mwe && mkdir -p /tmp/g-mwe && cd /tmp/g-mwe
git init -b main >/dev/null
echo hi > f.txt
git add f.txt && git commit -m "init" >/dev/null
# This is WRONG and triggers the error (no such rev "master/main")
if git rev-parse master/main >/dev/null 2>&1; then
echo "unexpected"
fi
# Correct ways
# 1) Use the existing branch name
git rev-parse main
# 2) If you want the remote branch, qualify with remote (origin/main)
git remote add origin .
# Simulate a remote by pointing origin to the same repo
git fetch origin --prune
git rev-parse origin/main
# 3) If you wanted a diff between branches, use .. or ...
git diff main...HEAD -- f.txt >/dev/null
echo "Fixed: use main, origin/main, or ranges (not master/main)."
Common causes and their corrections
| Intent | Wrong | Right |
|---|---|---|
| Remote branch | master/main | origin/main or origin/master |
| Compare branches | master/main | master..main or master...main |
| Tree path inside a commit | master/main | master:main (colon syntax) |
| Default branch in CI | hard-coded master | query origin/HEAD to discover default |
| Missing local branch | checkout master | checkout -B main origin/main |
Notes:
- Ranges: .. lists commits reachable from the right but not the left; ... selects the symmetric difference. A slash never denotes ranges.
- Tree paths: commit:path uses a colon, not a slash.
Step-by-step diagnosis
- List branches and confirm names
git branch --list
git branch --remotes --list
- Is the referenced branch present?
# Adjust branch to the one you expect
git show-ref --verify --quiet refs/heads/main || echo "local main missing"
git show-ref --verify --quiet refs/remotes/origin/main || echo "remote main missing"
- Fetch missing refs
git fetch origin --prune
- Create a local tracking branch when needed
# If main exists on origin but not locally
git checkout -B main origin/main
- Determine the default branch programmatically (avoid hard-coding)
# Align origin/HEAD with the host's default branch
git remote set-head origin -a
DEFAULT=$(git symbolic-ref --quiet --short refs/remotes/origin/HEAD | sed 's|^origin/||')
echo "Default is $DEFAULT"
- Fix the command syntax
- Remote branch: use origin/main, not master/main.
- Branch ranges: use .. or ... (e.g., git log master..main).
- Tree paths: commit:path (e.g., main:README.md).
- Handle shallow or partial clones
# Ensure the needed branch exists in a shallow clone
git fetch --depth=100 origin main:refs/heads/main
Robust snippets for DevOps scripts
- Resolve a base branch (prefer main, else master, else remote default):
set -euo pipefail
resolve_base_branch() {
if git show-ref --verify --quiet refs/heads/main; then echo main; return; fi
if git show-ref --verify --quiet refs/heads/master; then echo master; return; fi
git remote set-head origin -a >/dev/null 2>&1 || true
git symbolic-ref --quiet --short refs/remotes/origin/HEAD | sed 's|^origin/||'
}
BASE=$(resolve_base_branch)
- Safe diff with a fallback base:
BASE=$(resolve_base_branch)
# Use three-dot to focus on merge base changes
git diff "${BASE}...HEAD"
- Verify a remote branch exists before use:
branch_exists_remote() {
git show-ref --verify --quiet "refs/remotes/origin/$1"
}
if ! branch_exists_remote main; then
git fetch origin --prune
fi
Pitfalls
- Using master/main instead of origin/main or a proper range.
- Assuming master exists; many repos now use main.
- Forgetting to fetch in CI (shallow clones may lack the branch).
- Confusing tree-path syntax (commit:path) with branch names.
- Overwriting local branches unintentionally; prefer checkout -B only when you intend to re-point.
Performance notes
- Prefer fetching only what you need:
- git fetch origin main for a single branch.
- Use --depth=N in CI to limit history size.
- Cache repositories between CI runs to avoid full fetches.
- Avoid git fetch --all unless you genuinely use multiple remotes.
- Compute the base branch once per job and export it as an environment variable to reduce repeated lookups.
FAQ
Q: Why does master/main fail while origin/main works? A: origin/main is a remote-tracking branch ref. master/main is not a valid ref name; slash does not select a branch.
Q: How do I know whether to use main or master? A: Query the remote default branch via origin/HEAD, or check which branches exist and prefer main if present.
Q: I still get the error in a shallow clone. What now? A: Fetch the specific branch (git fetch --depth=100 origin main) or unshallow (git fetch --unshallow) so the ref resolves.
Q: I wanted a diff between master and main. What is correct? A: Use git diff master..main (two-dot) or git diff master...main (three-dot), not master/main.
Q: How do I reference a file from a branch? A: Use commit:path, e.g., git show main:README.md. Using a slash is invalid for this purpose.