Resolving refs
Turn a branch name, tag name, commit SHA, or HEAD into a single commit with refs.resolve.
refs.resolve turns one ref — a branch name, tag name, commit SHA, or HEAD — into a single
RefMatch telling you what it is and which commit it points at. Where refs.search prefix-matches
many refs for autocompletion, resolve answers the exact question “what does v2.1.0 point to?” —
the typical first step of a CI/CD or pinning flow.
Resolving
const match = await client.refs.resolve({
repo: 'capawesome-team/repo-sdk',
ref: 'v2.1.0',
});
// { type: 'tag', name: 'v2.1.0', ref: 'refs/tags/v2.1.0', sha: '4f2a…', raw: {…} }
The returned sha is always the peeled commit SHA — annotated tags are followed to the commit
they tag, on every provider. This differs from refs.search, whose GitHub and Gitea results carry
the tag object SHA for annotated tags.
Parameters
repo?string
The repository to resolve in.
stringref?string
The ref to resolve: a branch or tag name, a fully-qualified ref (refs/heads/…, refs/tags/…), a 4–40 hex commit SHA, or 'HEAD'.
stringtype?RefType
Restrict resolution to 'branch', 'tag', or 'commit'. Omit to try all (see resolution order). A type contradicting a fully-qualified ref throws a validation error.
RefTypeFully-qualified refs
ref also accepts the fully-qualified forms git and webhooks use: refs/heads/<name> resolves as a
branch, refs/tags/<name> as a tag — one lookup, no ambiguity. This makes resolve symmetric with
ParsedWebhookEvent.ref and RefMatch.ref, so any ref the SDK itself emits can be passed straight
back:
const event = parseWebhookEvent({ headers, body });
if (event.ref) {
const match = await client.refs.resolve({ repo: 'o/r', ref: event.ref });
}
Passing a type that contradicts the prefix (e.g. ref: 'refs/heads/main' with type: 'tag')
throws a RepoError with code: 'validation'.
Resolution order
Without a type hint (and no refs/… prefix), the SDK resolves in this order:
- If
refis a full 40-hex SHA, it is looked up as a commit first — git treats a full object id ahead of a same-named ref — so the webhook hot path of resolving aheadCommitShacosts a single request. The steps below only run when that lookup misses. - The name is looked up as a branch and a tag in parallel; a matching tag wins — even when a
branch shares the name (git
rev-parsesemantics). - Otherwise a matching branch is returned.
- Otherwise, if
refis 4–39 hex characters, it is resolved as an abbreviated commit SHA. - Otherwise the call throws a
RepoErrorwithcode: 'not_found'.
Pass type when you already know what you’re resolving — it skips the other lookups (one request
instead of two) and removes the ambiguity:
await client.refs.resolve({ repo: 'o/r', ref: 'release', type: 'branch' });
HEAD
ref: 'HEAD' resolves the repository’s default branch and returns it as a branch match with the
actual branch name — a one-call answer to “what is the default branch and its current tip”:
const head = await client.refs.resolve({ repo: 'o/r', ref: 'HEAD' });
// { type: 'branch', name: 'main', ref: 'refs/heads/main', sha: 'a1b2…', raw: {…} }
An empty repository without a default branch throws not_found.
Single branches and tags
resolve is built on branches.get and tags.get, which are also public — use them when you want
the full normalized model instead of a RefMatch (tags.get returns message, date, and
isAnnotated, always peeled):
const branch = await client.branches.get({ repo: 'o/r', name: 'main' });
const tag = await client.tags.get({ repo: 'o/r', name: 'v2.1.0' });
Both throw not_found on a miss.