Skip to content
LatchkeyLatchkey home

spr: Stacked Pull Requests From One Branch

spr update pushes each commit on your branch as its own stacked GitHub PR and keeps them in sync.

spr implements a Phabricator-style workflow on GitHub: one commit equals one PR. spr update is the workhorse that creates and refreshes the whole stack.

What it does

spr reads the commits on your local branch, assigns each a stable commit-id (via a git commit-msg hook), pushes one remote branch per commit, and opens or updates a GitHub PR for each, chaining their bases. spr status lists the stack and spr merge merges the bottom PR.

Common usage

Terminal
# create/update the stack of PRs
spr update
# show the state of each PR in the stack
spr status
# merge the bottom-most PR once it is approved and green
spr merge

Options

Command / FlagWhat it does
spr updatePush commits and create/update their PRs
spr statusPrint the state of each PR in the stack
spr mergeMerge the bottom PR of the stack
--count <n>Limit spr update to the top n commits
github.token (config)GitHub token spr uses to talk to the API

In CI

spr reads its GitHub token from the repo config or a token file; export it (spr respects a configured GitHub token) rather than logging in interactively. It requires a linear commit history with commit-ids, so run it on a clean branch and let its commit-msg hook add the ids.

Common errors in CI

"unable to find GitHub OAuth token" or "GitHub token is required" means no token is configured. "commit ... does not have a commit-id" means the commit-msg hook did not run; amend to add the id. "422 ... A pull request already exists" indicates a stale remote branch. "not a git repository" means it ran outside a checkout.

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

spr: Stacked Pull Requests From One Branch?
spr implements a Phabricator-style workflow on GitHub: one commit equals one PR. spr update is the workhorse that creates and refreshes the whole stack.
What it does?
spr reads the commits on your local branch, assigns each a stable commit-id (via a git commit-msg hook), pushes one remote branch per commit, and opens or updates a GitHub PR for each, chaining their bases. spr status lists the stack and spr merge merges the bottom PR.
In CI?
spr reads its GitHub token from the repo config or a token file; export it (spr respects a configured GitHub token) rather than logging in interactively. It requires a linear commit history with commit-ids, so run it on a clean branch and let its commit-msg hook add the ids.
Common errors in CI?
"unable to find GitHub OAuth token" or "GitHub token is required" means no token is configured. "commit ... does not have a commit-id" means the commit-msg hook did not run; amend to add the id. "422 ... A pull request already exists" indicates a stale remote branch. "not a git repository" means it ran outside a checkout.

Related guides

References

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