Documentation

Last updated in git: 2026-06-11

Pull requests

Everlock has a built-in pull request system. It is designed around a single principle: a pull request is a ref, not a database record.

How it works

When you open a pull request, the server creates a Git ref:

refs/pull/{slug}/{target}  →  <commit-oid>
  • {slug} is a human-readable name you choose for the PR, such as oauth-support or fix-login
  • {target} is the branch you want to merge into, such as main
  • the ref points to the commit you want reviewed

Everything the system needs to know about the PR is encoded in the ref itself:

ThingHow it is stored
PR identitythe ref name
Commit to mergethe OID the ref points to
Target branchthe last segment of the ref path
PR is openref exists
PR is closed or mergedref deleted

There is no separate database. Diff and mergeability are computed on the fly from the ref and the current state of the target branch.

Opening a pull request

Via the admin CLI

/git pr open my-project oauth-support main feature-branch

This creates refs/pull/oauth-support/main pointing to the current tip of feature-branch.

You can also point a PR at a specific commit OID instead of a branch name:

/git pr open my-project oauth-support main abc123def456...

Via git push

You can also open a PR directly from the command line without going through the admin shell. Push the commit you want reviewed to the PR ref:

git push origin HEAD:refs/pull/oauth-support/main

The server validates the push:

  • the target branch (main) must exist
  • the ref must not already exist (to prevent accidental overwrites)
  • the commit must be present in the repository

Listing pull requests

/git pr list my-project

Output shows each open PR and its merge status:

  oauth-support/main                       mergeable
  fix-parser/main                          conflict: src/parser.rs
  update-deps/main                         mergeable

mergeable means the PR can be merged automatically, either as a fast-forward or as a three-way merge commit.

conflict means the same lines were modified on both sides and cannot be resolved without manual intervention. The conflicting file paths are shown.

Updating a pull request

Push a new commit to the same ref:

git push origin HEAD:refs/pull/oauth-support/main

The server replaces the ref with the new commit. Force-push semantics apply — the client controls the commit history.

Fetching a pull request locally

To review someone else's PR:

git fetch origin refs/pull/oauth-support/main:pr-oauth-support
git checkout pr-oauth-support

Merging a pull request

/git pr merge my-project oauth-support main

The server:

  1. reads refs/pull/oauth-support/main to find the source commit
  2. reads refs/heads/main to find the current target tip
  3. checks mergeability
  4. if the target is a direct ancestor of the source: fast-forwards main to the source commit
  5. if the branches have diverged but there are no conflicts: creates a merge commit and advances main
  6. if there are conflicts: aborts with the list of conflicting paths
  7. on success: deletes refs/pull/oauth-support/main

The target branch update is atomic — it uses a compare-and-swap against the tip the server read in step 2. If main changed between validation and the update, the merge is rejected and must be retried.

When a merge fails

If the merge reports conflicts:

  error: merge conflict in: src/parser.rs, src/lexer.rs

The PR author needs to rebase or resolve the conflicts locally and push an updated commit to the PR ref:

git fetch origin main
git rebase origin/main
# resolve any conflicts
git push origin HEAD:refs/pull/oauth-support/main

Closing a pull request without merging

Via the admin CLI:

/git pr close my-project oauth-support main

Via git push:

git push origin :refs/pull/oauth-support/main

Both delete the ref. There is no separate "closed" state — a deleted ref is a closed PR.

Ref namespace

All PR refs live under refs/pull/. They are treated as GC roots — the server will not garbage-collect commits that are only reachable from a PR ref.

Clients cannot push directly to refs/pull/ to overwrite an existing PR. The server rejects pushes that would create a PR ref that already exists. To update an existing PR, push a new commit to the same ref path (the server treats that as an update, not a creation).

Design notes

The slug is independent of the source branch. You can open a PR named oauth-support from a branch called feature/auth-rewrite, or from a specific commit on no branch at all. The PR tracks the commit, not the branch.

This means:

  • PRs survive branch renames and deletions
  • Multiple PRs can target the same branch from different commits
  • The slug is the stable identity of the review, not the branch name

Read next

git pull-requests code-review