Limitations

Things we haven't built, things that don't work yet, and reasons you might pick a different tool. The goal here is to save you time — if a deal-breaker is on this page, walk away now rather than two weeks in.

Who shouldn't use this

You don't use GitHub.

giff stack is GitHub-specific. GitHub Enterprise works (set the base_url in config), but GitLab, Bitbucket, Gitea, and friends don't. The forge layer is abstracted (ForgeBackend trait) but only one impl exists. Adding GitLab is doable — see the contributing page.

You don't already work in stacked PRs.

This is a workflow change, not a tool change. giff stack makes stacked diffs easier, but if your team's review process assumes one big PR per feature, dropping in a stack tool won't change that. The first cultural conversation is "we're going to start doing smaller PRs" — the tool is downstream of that decision.

You want a polished, shrink-wrapped product.

giff stack is alpha software. Bugs exist. Edge cases will surprise you. No prebuilt binaries (yet). No published Docker image (yet). If you want the polished version, use Graphite — they have ~50 people doing it full-time. We don't.

You want jujutsu / Sapling / virtual-branch semantics.

Different abstraction. giff stack uses real git branches, real merge commits, real PRs. If your mental model is "I work on multiple things in one tree and pick what to publish," GitButler or jj will fit you better.

What's not built

The full inventory lives in the repo's GAPS.md. Here's the short version, by component.

The runner

  • No auth on the HTTP API. The /repos / /stacks / /events / /retry-queue endpoints are unauthenticated. Behind a private tunnel (Cloudflare Access, Tailscale ACL, basic-auth reverse proxy) this is fine; on a public URL it's not. Don't expose the runner publicly without auth in front of it.
  • Approving-review enforcement is delegated to GitHub branch protection. If you turn on auto-merge but haven't required reviews on the trunk, the runner will land unreviewed code. Configure branch protection first.
  • PAT-based auth, not GitHub Apps. A long-lived repo-scope token in the runner's env has a high blast radius if compromised. GitHub Apps would be safer; not built.
  • Pagination caps at 100 open PRs per repo. If you have a busier repo, the runner sees only the first page. Fine for most teams; not fine for monorepos.
  • No multi-tenant isolation. One GITHUB_TOKEN, one set of repos. Two teams sharing a runner can read each other's /events.

The CLI

  • giff stack reorder is linear-only. Tree-shaped stacks have to be flattened (via squash or drop) before reordering.
  • Pre-commit hook auto-installs only after you run any giff command in a repo. A teammate cloning a stack-managed repo won't have the hook until they run giff status (or any other giff command) once.
  • No comprehensive E2E tests against real GitHub. Lower-level wiremock tests cover the components; integration tests are manual.

The web dashboard

  • Plain-text comment rendering. No GFM, no syntax highlighting in code blocks within comments, no link auto-detection. Click through to GitHub for properly-rendered comments.
  • Read-only. By design — no commenting, approving, or merging from the dashboard. If you want to act, click through to github.com.
  • Dark mode is half-built. CSS variables are in place but there's no toggle.
  • Mobile responsive is desktop-first. Sub-640px screens lay out poorly.
  • No tests. Type checks via svelte-check; no Vitest, no Playwright.

Cross-cutting

  • Crate not yet on crates.io. The CLI package is named giffstack in Cargo.toml and ready to be published, but cargo install giffstack won't resolve until the first cargo publish happens. CI is wired up to auto-publish on push to main once the CARGO_REGISTRY_TOKEN repo secret is set; until then, install from a local checkout (cargo install --path crates/giff-cli).
  • No prebuilt standalone binaries or Docker image. CLI is installable via cargo install giffstack after first publish; the runner still installs via docker compose build. Plan to publish prebuilt binaries and a Docker image once the project stabilises.
  • No structured tracing or error reporting. Logs + the runner's events table is all the observability there is.

Things that might bite you

Force-push side effects

giff push uses --force-with-lease. Safe for solo work; if a teammate pushes commits to one of your stack branches between your giff push calls, the lease will fail and you'll have to fetch + sort it out manually. Don't share branch ownership inside a stack with other devs.

The runner's auto-merge race

When the runner auto-merges the bottom of a stack, GitHub typically deletes the merged branch immediately after. If a child PR's webhook hasn't yet caused a base retarget, that child PR's base briefly points at a deleted ref. The retry queue cleans it up on the next attempt — but for ~30 seconds the child PR may show as broken on github.com.

SSH passphrase prompts

We set GIT_SSH_COMMAND with ControlMaster=auto at the top of every CLI command, so within one giff push or giff sync you should be prompted at most once. Across commands the multiplexer expires after 2 minutes of inactivity, so doing giff publish + giff push + giff sync in slow succession could re-prompt. Run ssh-add once at the start of your session for the cleanest experience.

State drift on shared repos

.git/stacked.toml is per-developer and per-machine. Two devs working on the same stack via two clones will each have their own view. They re-converge on giff sync (which reads PR descriptions on GitHub to rebuild the truth), but in the meantime they'll disagree. Don't try to make it the source of truth for shared state; that's GitHub's job.

giff stack · open source · MIT Source