Guides
Migrating from Graphite
Map Graphite (`gt`) commands to DubStack equivalents and migrate an in-flight stack in under 30 minutes.
If you have gt muscle memory, this guide is the fast path to DubStack. The mental model is the same: branches stacked on branches, one PR per branch, automatic restack on rebase.
Command Mapping
| Graphite | DubStack | Notes |
|---|---|---|
gt create | dub create | Same flags: -a, -m, --ai |
gt modify / gt m | dub modify / dub m | Amend current branch and restack descendants |
gt submit / gt ss | dub submit / dub ss | --stack, --upstack, --downstack, --branch |
gt sync | dub sync | --all syncs every tracked stack |
gt checkout / gt co | dub checkout / dub co | Interactive picker with no argument |
gt log / gt ls | dub log / dub ls | --stack, --all, --json |
gt up / gt down | dub up / dub down | Identical |
gt top / gt bottom | dub top / dub bottom | Identical |
gt info | dub info | --json machine-readable |
gt pr | dub pr | Opens the PR for the current branch |
gt restack | dub restack | Automatic when a parent changes |
gt continue | dub continue | Add --ai to resolve conflicts via LLM |
gt abort | dub abort | Rolls back restack/rebase |
gt track --parent | dub track --parent | Adopt an untracked branch |
gt untrack | dub untrack | Keep the branch, drop DubStack metadata |
gt delete | dub delete | --upstack, --downstack, --force |
gt parent / gt children | dub parent / dub children | --json outputs the relation |
gt trunk | dub trunk / dub trunk add / dub trunk set-default | Multi-trunk supported |
gt undo | dub undo | 20-entry ring buffer, supports dub redo |
gt absorb | dub absorb | --ai for ambiguous fixups |
gt fold | dub fold | Defaults to keeping commits; --squash to collapse |
gt move --before/--after | dub move --before/--after | Identical semantics |
gt split | dub split | Interactive or AI-assisted commit split |
Conceptual Differences
- Local-first. All state lives in
.git/dubstack/and never leaves your machine. There is no DubStack account, no remote server, and no synchronization daemon. The downside is that team coordination happens through GitHub PRs alone. - Stack metadata in git refs. DubStack mirrors stack state into
refs/dubstack/*so a wiped checkout can rebuild fromdub init --restore-from-refs. Graphite stores the equivalent in.graphite_cache_persist. - First-class AI.
dub create --ai,dub submit --ai,dub flow, anddub absorb --aiall use a provider you configure withdub config ai-provider. Set keys withdub config ai-model --provider anthropic <model>. - Safer merges.
dub merge-next(aliasdub land) refuses to merge a PR whose ancestors are not yet merged, and retargets every dependent PR atomically before deleting the local branch. - Multi-trunk. A single repository can have several trunks (e.g.
mainplusrelease/24.x). Configure withdub trunk addanddub trunk set-default. - MCP server.
dub mcpexposes the local stack to AI coding agents via the Model Context Protocol, gated bydub config mcp-mode.
Common Pitfalls
gt submit --stackdefaulted to the whole tree;dub submitdefaults to downstack. Pass--stackexplicitly when migrating CI scripts that assumed Graphite's old default.gt sync --no-restackdoes not exist in DubStack. Usedub syncand thendub restack --continueif you wanted to defer restack..graphite_user_configis not read. Re-configure withdub config ai-provider,dub config reviewers, and friends.gt downstack edithas no direct equivalent. Usedub reorderfor interactive reordering, ordub move --before/--afterfor single-branch moves.
30-Minute Migration Script
The following walkthrough migrates an active Graphite stack in place without re-creating any branches or losing in-flight PRs.
# 1. Install DubStack (assumes pnpm/npm available)
npm install -g dubstack
# 2. From the repo root, initialize DubStack alongside Graphite
cd path/to/repo
dub init
# 3. Adopt every Graphite-tracked branch into DubStack. DubStack walks the
# git ancestry to infer parent links — this is non-destructive.
git switch main
for branch in $(git for-each-ref --format='%(refname:short)' refs/heads/); do
if [ "$branch" != "main" ]; then
git switch "$branch"
dub track --no-interactive || true
fi
done
# 4. Verify the stack matches what Graphite showed
dub log --all
# 5. Optional: enable AI features. Pick one provider.
dub config ai-assistant on
dub config ai-provider anthropic
dub config ai-model --provider anthropic claude-sonnet-4-7
# 6. Optional: pre-fetch your default reviewers so `dub submit` requests them
dub config reviewers alice,@org/backend
# 7. Confirm restack works on the active stack
dub restack
# 8. Resync PR descriptions with the new metadata layout
dub submit --downstack --no-ai
# 9. (When you are confident) remove Graphite
npm uninstall -g @withgraphite/graphite-cli
rm -rf .graphite_cache_persist .graphite_repo_config .graphite_user_config
# 10. Add an alias so muscle memory survives:
# alias gt=dub # zsh/bashIf anything looks off after step 4, run dub doctor for a diagnostic report. The state is recoverable via dub init --restore-from-refs.