Skip to content
LatchkeyLatchkey home

git show-ref --verify: Test a Ref Exists in CI

git show-ref --verify --quiet refs/heads/<branch> exits 0 if that exact ref exists and nonzero otherwise, the reliable way to test for a branch or tag in a script.

Scripts often need to know whether a branch or tag exists before acting. git show-ref --verify gives a clean exit code on a fully qualified ref, avoiding the ambiguity of partial name matching.

What it does

git show-ref lists refs and their SHAs from refs/. With a pattern it lists matching refs; with --verify it requires an exact, fully qualified ref path and exits nonzero if it is absent. --quiet suppresses output so only the exit code matters. --heads and --tags filter to those namespaces.

Common usage

Terminal
# does a local branch exist?
git show-ref --verify --quiet refs/heads/release && echo yes
# does a tag exist?
git show-ref --verify --quiet refs/tags/v1.4.0
# list all branch refs with SHAs
git show-ref --heads
# get the SHA of a specific tag
git show-ref --tags refs/tags/v1.4.0

Options

FlagWhat it does
--verifyRequire an exact, fully qualified ref; nonzero if missing
--quietPrint nothing; rely on the exit code
--headsLimit to branch refs (refs/heads/)
--tagsLimit to tag refs (refs/tags/)
--hash[=<n>]Print only the SHA (abbreviated to n)
-d / --dereferenceAlso show the SHA an annotated tag points to

In CI

Use the fully qualified path with --verify (refs/heads/x, refs/tags/x); a bare name fails. To check a remote-tracking branch fetched into the clone, verify refs/remotes/origin/<branch>. On a shallow single-branch clone, other branches and tags are simply absent, so show-ref legitimately reports them missing.

Common errors in CI

"fatal: 'main' - not a valid ref" from --verify means you passed a short name instead of refs/heads/main. A nonzero exit with --quiet is the intended "not found" signal, not a crash. If a tag you expect is missing, the clone likely did not fetch tags; git fetch --tags.

Using this in CI

CI checkouts are shallow and detached by default, which changes the answer this command gives you. Commands that read history, branch names, or tags need the checkout configured for it.

.github/workflows/ci.yml
- uses: actions/checkout@v4
  with:
    fetch-depth: 0   # history, tags, and git describe all need this

- run: |
    git rev-parse --is-shallow-repository   # expect false
    git rev-parse --abbrev-ref HEAD          # prints HEAD when detached

Frequently asked questions

git show-ref --verify: Test a Ref Exists in CI?
Scripts often need to know whether a branch or tag exists before acting. git show-ref --verify gives a clean exit code on a fully qualified ref, avoiding the ambiguity of partial name matching.
What it does?
git show-ref lists refs and their SHAs from refs/. With a pattern it lists matching refs; with --verify it requires an exact, fully qualified ref path and exits nonzero if it is absent. --quiet suppresses output so only the exit code matters. --heads and --tags filter to those namespaces.
In CI?
Use the fully qualified path with --verify (refs/heads/x, refs/tags/x); a bare name fails. To check a remote-tracking branch fetched into the clone, verify refs/remotes/origin/<branch>. On a shallow single-branch clone, other branches and tags are simply absent, so show-ref legitimately reports them missing.
Common errors in CI?
"fatal: 'main' - not a valid ref" from --verify means you passed a short name instead of refs/heads/main. A nonzero exit with --quiet is the intended "not found" signal, not a crash. If a tag you expect is missing, the clone likely did not fetch tags; git fetch --tags.

Related guides

References

Run this faster and cheaper on Latchkey managed runners - self-healing included. Start free → 30-day trial · No credit card