# git for-each-ref: Usage, Options & Common CI Errors

> git for-each-ref iterates over refs with a custom format. Reference for --format, --sort, --points-at, and building stable, scriptable ref listings in CI.

Source: https://latchkey.dev/learn/command-reference/git-for-each-ref  
Updated: 2026-06-25

git for-each-ref lists branches, tags, and other refs in exactly the format you specify.

When a pipeline needs the latest tag, all branches sorted by date, or refs pointing at a commit, for-each-ref gives stable, parseable output that beats scraping git branch or git tag.

## What it does

git for-each-ref walks references matching a pattern and prints each using a custom --format with placeholders like %(refname), %(objectname), and %(creatordate), optionally sorted and filtered.

## Common usage

```Terminal
git for-each-ref --format='%(refname:short)' refs/heads/
git for-each-ref --sort=-creatordate --format='%(refname:short)' refs/tags/
git for-each-ref --points-at HEAD
git for-each-ref --count=1 --sort=-v:refname 'refs/tags/v*'
```

## Options

| Flag | What it does |
| --- | --- |
| --format=<fmt> | Custom output with %(field) placeholders |
| --sort=<key> | Sort by a field (prefix - to reverse) |
| --points-at <obj> | Only refs pointing at an object |
| --count=<n> | Limit to the first n refs |
| --merged / --no-merged <ref> | Filter by merge state |

## Common errors in CI

An empty result usually means the ref pattern did not match (refs/tags/ vs refs/tags/*) or that a shallow/single-branch clone never fetched the refs. Quote glob patterns so the shell does not expand them, and fetch tags (fetch-depth: 0) when you expect them.

## 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
```

> `git rev-parse --abbrev-ref HEAD` returns the literal string `HEAD` on a detached checkout rather than a branch name. On GitHub Actions read `github.ref_name` instead; the git command cannot know what it was checked out for.

## FAQ

### git for-each-ref: Usage, Options & Common CI Errors?

When a pipeline needs the latest tag, all branches sorted by date, or refs pointing at a commit, for-each-ref gives stable, parseable output that beats scraping git branch or git tag.

### What it does?

git for-each-ref walks references matching a pattern and prints each using a custom --format with placeholders like %(refname), %(objectname), and %(creatordate), optionally sorted and filtered.

### Common errors in CI?

An empty result usually means the ref pattern did not match (refs/tags/ vs refs/tags/*) or that a shallow/single-branch clone never fetched the refs. Quote glob patterns so the shell does not expand them, and fetch tags (fetch-depth: 0) when you expect them.

---

Latchkey runs CI/CD that repairs its own failures. Agent entry points: https://latchkey.dev/agent.txt, https://latchkey.dev/openapi.json, https://latchkey.dev/llms.txt
