1. The stack is just parent pointers
When you run gt create, stkd records one fact in your repository's
.git/config: the parent of the new branch. Stack after stack, those
pointers form a directed acyclic graph — a DAG — rooted at your
trunk. There's no hidden database and nothing stored on a server;
the source of truth lives in the repo. It's the same
branch.<name>.parent metadata Graphite uses, which is why
migration is a single command.
2. Restack walks the graph
When you amend a lower branch, everything above it is now out of date.
gt restack topologically walks the stack from the changed branch upward and rebases
each dependent branch onto its parent's new tip, reusing cached merge-bases to stay fast. If a
rebase conflicts, stkd stops exactly there in a normal git conflict state. You resolve it, run
gt continue, and the walk resumes. gt restack --abort unwinds the whole
operation cleanly.
3. Submit maps branches to PRs
gt submit --stack opens or updates one pull request per branch on GitHub — or one
merge request per branch on GitLab, including self-hosted —
setting each PR's base to the branch below it. It posts the cross-linked “Stacked PRs”
navigation comment reviewers expect. Your reviewers never need stkd installed; they see ordinary,
small, isolated PRs.
4. Sync drains the stack from the bottom
When the bottom PR lands, gt sync notices the merged branch on the remote, deletes it
locally, restacks the survivors onto the updated trunk, and retargets their PRs. The stack flows
downstream on its own — no manual git rebase --onto across four branches, no stale
“out of date with base” warnings.
5. Two front-ends, one engine
The interactive TUI and the
MCP server are thin shells over the same engine. That's why an AI agent driving
gt_restack through Model Context Protocol gets
exactly the same behavior as you typing gt restack — and inherits the same
permissions and branch-protection rules.