Skip to content
repo-sdk
Esc
navigateopen⌘Jpreview
On this page

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

PropType
repo?string

The repository to resolve in.

Typestring
ref?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'.

Typestring
type?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.

TypeRefType

Fully-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:

  1. If ref is 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 a headCommitSha costs a single request. The steps below only run when that lookup misses.
  2. 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-parse semantics).
  3. Otherwise a matching branch is returned.
  4. Otherwise, if ref is 4–39 hex characters, it is resolved as an abbreviated commit SHA.
  5. Otherwise the call throws a RepoError with code: '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' });

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.

Provider semantics

Was this page helpful?