pancake

command module
v0.1.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 22, 2026 License: MIT Imports: 11 Imported by: 0

README ΒΆ

πŸ₯ž pancake

Stateless stacked-PR management, derived from your git graph.

No server. No account. No stored lineage. pancake figures out your whole stack every time from the commit graph itself, so it works identically in any clone β€” including throwaway worktrees / APFS workspaces β€” with zero setup.

You give it two things you already know: the top branch of your stack and the trunk it targets (default origin/master). It derives the rest.

$ pancake list feature/dev-67
feature/dev-43
feature/dev-37
feature/dev-38
…
feature/dev-67

Why

Stacked PRs are great; managing them by hand (rebasing every branch onto master after each merge, moving refs, force-pushing the lot) is tedious. The existing tools each ask for something we don't want:

Tool Trade-off
Graphite Proprietary; requires an account and server-side stack state.
git-town OSS & good, but stores lineage in local git config that doesn't travel to fresh/ephemeral clones, and expects you to adopt its create commands.
pancake Stateless. Nothing stored β€” the stack is read from the graph. Use it on any branch, in any clone, immediately.

How it works

Four git plumbing calls behind a nice UX:

  • discover the stack β†’ git for-each-ref --merged <top> --no-merged <trunk>
  • fork point β†’ git merge-base <trunk> <top>
  • restack β†’ git rebase --update-refs --onto <trunk> <fork>
  • submit β†’ git push --force-with-lease

Because sync rebases from the fork point onto the latest trunk, any commit already contained in trunk (i.e. whatever just merged) replays empty and is dropped β€” so you never have to tell it which branch merged.

Commands

pancake list   [top] [trunk]   print the stack, bottom -> top
pancake log    [top] [trunk]   PR-aware stack (via gh) + decorated graph
pancake sync   [top] [trunk]   fetch+prune, restack onto trunk, move every ref
pancake submit [top] [trunk]   force-push (--force-with-lease) every branch
pancake doctor                 check the GitHub prerequisites for stacked PRs
pancake install                symlink git-stack/git-pancake so `git stack …` works

Flags (before positionals): --trunk <ref>  --remote <name>  --dry-run  --json  --trace[=json]

list --json emits [{branch, sha, commitsAboveTrunk, subject}], ordered bottom β†’ top β€” for scripting and for piping into other tools.

log annotates each branch with its PR number/state/base (via gh) and flags any PR whose base isn't the branch directly below it β€” the misconfiguration you most want to catch in a stack. If gh is missing or unauthenticated it degrades to the plain decorated graph.

git stack β€” the native-feeling alias

pancake is a mouthful to type. pancake install symlinks git-stack and git-pancake next to the binary, so git picks them up as subcommands:

pancake install          # one time (the binary's dir must be on PATH)
git stack sync           # == pancake sync β€” auto-detects the top branch
git stack submit
git stack log

git runs git-stack for git stack …, and pancake ignores argv[0], so the symlink is the whole trick β€” no wrapper, no extra process.

Per-repo defaults: .pancake

pancake defaults its trunk to origin/master, but plenty of repos default to main, dev, or develop β€” and stacking onto the wrong branch is a silent, maddening failure. Rather than pass --trunk every time, commit an optional .pancake file at the repo root:

# .pancake β€” pancake defaults for this repo
trunk  = origin/dev
remote = origin
  • Precedence: --trunk (flag/positional) β†’ .pancake β†’ built-in origin/master.
  • It's committed and versioned, so a fresh or ephemeral clone gets the right default from the first second. It configures the default target only β€” the stack itself is still derived from the graph, so this doesn't touch the stateless contract.
  • pancake doctor shows where the trunk came from and, if you didn't configure one, warns when pancake's built-in default doesn't match the repo's default branch (the real trap). A deliberate override is reported as intentional, not an error.

Prerequisite: auto-delete head branches

Stacked PRs on GitHub depend on one repo setting pancake cannot substitute for β€” Settings β†’ General β†’ "Automatically delete head branches" (delete_branch_on_merge). Without it, when a base PR merges, GitHub does not retarget the PR stacked above it: the merged branch lingers, the dependent PR keeps the wrong base, and the stack silently rots. pancake won't flip org settings for you, but it will tell you when it's off:

pancake doctor          # βœ“/βœ— gh auth, delete_branch_on_merge, trunk == default branch
pancake doctor --fix    # enable delete_branch_on_merge for you (via gh)

submit also warns if the setting is off.

Omit [top] and pancake infers it: the tip of your stack (the unmerged branch nothing else is built on). With one stack that's unambiguous; with several it picks the one containing your current branch, else asks you to name it.

Seeing where the time goes

pancake is a thin wrapper over git, so a slow run means a slow git command β€” and which one is wildly repo-dependent (history depth, remote ref count, whether a commit-graph exists, working-tree size, hooks). --trace times every git call and prints an end-of-run summary; --trace=json emits a machine-readable object. Set GIT_TRACE2=1 alongside it to see git's own internal phases.

pancake sync feature/dev-67 --trace        # per-call timings + slowest phase
pancake sync feature/dev-67 --trace=json    # structured, for collecting/diffing
PANCAKE_TRACE=1 pancake sync feature/dev-67 # same, via env
Typical loop, after the bottom PR merges
pancake sync   feature/dev-67   # fetch+prune, restack the rest onto master, move all refs
pancake submit feature/dev-67   # force-push every branch β†’ every PR updates at once

Install

go install github.com/devergehq/pancake@latest

Optionally expose it as a git subcommand (git stack …) by symlinking a shim onto your PATH:

ln -s "$(go env GOPATH)/bin/pancake" ~/.local/bin/git-stack

Shell prototype

contrib/git-stack is the original POSIX-shell prototype these commands grew from β€” handy if you want the workflow without building the binary. Source contrib/pr-stack.sh from your shell rc for prs-list / prs-sync / prs-submit.

Status

v0 β€” see the Pancake project in Linear.

License

MIT Β© Deverge

Documentation ΒΆ

Overview ΒΆ

Command pancake is a stateless stacked-PR manager.

It manages a stack of stacked pull requests without storing any state: the stack is derived on every run from the Git commit graph (every remote branch reachable from the top branch but not from the trunk). That means it works identically in any clone β€” including throwaway APFS workspaces β€” with no config, no server, and no account.

You provide the top branch and a trunk (default origin/master); everything else is computed.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL