重要前提
安装AI Skills的关键前提是:必须科学上网,且开启TUN模式,这一点至关重要,直接决定安装能否顺利完成,在此郑重提醒三遍:科学上网,科学上网,科学上网。查看完整安装教程 →
npx skills add https://github.com/dagster-io/erk --skill gtGraphite (gt) 是一个用于管理堆叠式拉取请求的 CLI 工具——将大型功能拆分为多个相互依赖的小型增量更改。本技能提供了有效使用 gt 所需的心智模型、命令参考和工作流模式。
--no-interactive切勿在不使用 --no-interactive 的情况下调用任何 gt 命令。 这是一个被所有 gt 命令继承的全局标志——而非每个命令的选项。
在没有 --no-interactive 的情况下,gt 可能会打开提示、分页器或编辑器,在代理/CI 环境中无限期挂起。--force 标志不会阻止提示——你必须单独使用 --no-interactive。
# 错误 - 可能挂起等待用户输入
gt sync
gt submit --force
gt track --parent main
# 正确 - 始终传递 --no-interactive
gt sync --no-interactive
gt submit --no-interactive
gt track --parent main --no-interactive
gt restack --no-interactive
gt create my-branch -m "message" --no-interactive
广告位招租
在这里展示您的产品或服务
触达数万 AI 开发者,精准高效
--interactive 控制的内容(所有内容均被 --no-interactive 禁用):
注意: gt modify --interactive-rebase 是一个独立的、不相关的标志,用于启动 git 交互式变基。它与全局的 --interactive 不同。
一个堆栈是一系列分支,其中每个分支(主干除外)都恰好有一个父分支:
有效堆栈(线性):
main → feature-a → feature-b → feature-c
无效(不是堆栈):
main → feature-a → feature-b
└─────→ feature-x
gt down 从 feature-b → feature-a → main 移动gt up 从 feature-a → feature-b → feature-c 移动main 或 master)使用 Graphite 堆栈时,始终将主干想象在底部:
顶部 ↑ feat-3 ← 上游(叶节点)
feat-2
feat-1
底部 ↓ main ← 下游(主干)
给定堆栈:main → feat-1 → feat-2 → feat-3
如果当前分支是 feat-1:
feat-2, feat-3(子分支,朝向顶部)main(父分支,朝向底部)如果当前分支是 feat-3(在顶部):
feat-2, feat-1, main(祖先分支,朝向底部)🔴 命令依赖于此可视化:
gt up / gt down 在堆栈中导航land-stack 按特定方向遍历分支🔴 常见错误: 认为“上游”意味着“朝向主干”
🔴 PR 合并顺序: 始终自底向上(main 优先,然后逐层向上)
所有 gt 元数据都存储在共享的 .git 目录中(可在所有工作树中访问):
.git/.graphite_repo_config - 仓库级别配置(主干分支).git/.graphite_cache_persist - 分支关系(父子图).git/.graphite_pr_info - 缓存的 GitHub PR 信息重要提示: 由于元数据位于公共的 .git 目录中,因此所有工作树共享这些元数据。
记住:以下所有 gt 命令都必须包含 --no-interactive(参见上文的重要:始终使用 --no-interactive)。
| 命令 | 别名 | 用途 |
|---|---|---|
gt create [name] | gt c | 基于当前分支创建新分支并提交暂存的更改 |
gt modify | gt m | 修改当前分支(修改提交)并自动重堆叠子分支 |
gt submit | gt s | 推送分支并创建/更新 PR |
gt submit --stack | gt ss | 提交整个堆栈(上游 + 下游) |
gt sync | - | 从远程同步并提示删除已合并的分支 |
| 命令 | 别名 | 用途 |
|---|---|---|
gt up [steps] | gt u | 向上游移动(远离主干) |
gt down [steps] | gt d | 向下游移动(朝向主干) |
gt top | gt t | 移动到堆栈顶部 |
gt bottom | gt b | 移动到堆栈底部 |
gt checkout [branch] | gt co | 交互式分支检出 |
| 命令 | 用途 |
|---|---|
gt restack | 确保每个分支在 git 历史记录中都有其父分支 |
gt move | 将当前分支变基到不同的父分支上 |
gt fold | 将分支的更改折叠到父分支中 |
gt split | 将当前分支拆分为多个单提交分支 |
gt log | 可视化堆栈结构 |
| 命令 | 用途 |
|---|---|
gt branch info | 显示分支信息(父分支、子分支、提交 SHA) |
gt parent | 显示父分支名称 |
gt children | 显示子分支名称 |
gt track [branch] | 开始用 gt 跟踪分支(设置父分支) |
gt untrack [branch] | 停止用 gt 跟踪分支 |
gt delete [name] | 删除分支并更新元数据 |
gt rename [name] | 重命名分支并更新元数据 |
将功能拆分为多个可审查的块:
# 1. 从主干开始
gt checkout main --no-interactive
git pull
# 2. 创建第一个分支
gt create phase-1 -m "添加 API 端点" --no-interactive
# ... 进行更改 ...
git add .
gt modify -m "添加 API 端点" --no-interactive
# 3. 在其上创建第二个分支
gt create phase-2 -m "更新前端" --no-interactive
# ... 进行更改 ...
git add .
gt modify -m "更新前端" --no-interactive
# 4. 提交整个堆栈
gt submit --stack --no-interactive
# 结果:创建了 2 个 PR
# PR #101: phase-1 (基础:main)
# PR #102: phase-2 (基础:phase-1)
更新堆栈中间的分支:
# 向下导航到目标分支
gt down --no-interactive # 根据需要重复
# 进行更改
# ... 编辑文件 ...
git add .
# 修改(自动重堆叠上游分支)
gt modify -m "处理审查反馈" --no-interactive
# 重新提交堆栈
gt submit --stack --no-interactive
在中间插入新分支:
# 检出要插入位置的父分支
gt checkout phase-1 --no-interactive
# 使用 --insert 创建新分支
gt create phase-1.5 --insert -m "添加验证" --no-interactive
# 提交新 PR
gt submit --no-interactive
在 GitHub 上合并 PR 后进行清理:
# 运行同步(--no-interactive 自动确认分支删除)
gt sync --no-interactive
# 结果:
# - 已合并的分支在本地被删除
# - 剩余分支被变基到主干上
# - GitHub 上的 PR 基础分支已更新
将大型提交拆分为可审查的部分:
# 检出包含大型提交的分支
gt checkout large-feature --no-interactive
# 拆分为单提交分支
gt split --no-interactive
# 有意义地重命名分支
gt rename add-api-endpoints --no-interactive
gt up --no-interactive
gt rename add-frontend --no-interactive
gt up --no-interactive
gt rename add-tests --no-interactive
# 提交
gt submit --stack --no-interactive
git rebase:使用 gt modify 或 gt restack - gt 需要在变基期间更新元数据git branch -d 删除分支:使用 gt delete - 需要更新元数据以重新设置子分支的父分支gt submit 只影响当前分支:它也会提交下游(所有祖先分支)。使用 gt submit --stack 来包含上游分支gt sync:陈旧的分支会累积,元数据会过时gt log short 查看分支状态:其输出格式反直觉且会混淆代理。请改用 gt branch info、gt parent 或 gt children 来显式访问元数据何时使用 gt 命令:
gt create(设置父子关系)gt modify(自动重堆叠子分支)gt up/down/top/bottom(在链中移动)gt log(查看可视化)gt branch info(解析 "Parent:" 行)gt parent / gt children(快速访问)gt submit --stack(创建/更新所有 PR)gt sync(清理 + 变基)gt move(更改父分支)gt fold(合并到父分支)gt split(拆分为多个分支)包含详细的命令参考和全面的心智模型文档:
gt-reference.md - 完整的命令参考、元数据格式详情和高级模式当用户需要关于特定 gt 命令、元数据结构或复杂工作流场景的详细信息时,请加载此参考。
每周安装次数
53
仓库
GitHub 星标数
74
首次出现
2026 年 1 月 29 日
安全审计
安装于
github-copilot53
codex53
opencode52
claude-code52
kimi-cli52
gemini-cli52
Graphite (gt) is a CLI tool for managing stacked pull requests - breaking large features into small, incremental changes built on top of each other. This skill provides the mental model, command reference, and workflow patterns needed to work effectively with gt.
--no-interactiveNEVER invoke anygt command without --no-interactive. This is a global flag inherited by every gt command — not a per-command option.
Without --no-interactive, gt may open prompts, pagers, or editors that hang indefinitely in agent/CI contexts. The --force flag does NOT prevent prompts — you must use --no-interactive separately.
# WRONG - may hang waiting for user input
gt sync
gt submit --force
gt track --parent main
# CORRECT - always pass --no-interactive
gt sync --no-interactive
gt submit --no-interactive
gt track --parent main --no-interactive
gt restack --no-interactive
gt create my-branch -m "message" --no-interactive
What--interactive controls (all disabled by --no-interactive):
Note: gt modify --interactive-rebase is a separate, unrelated flag that starts a git interactive rebase. It is NOT the same as the global --interactive.
A stack is a sequence of branches where each branch (except trunk) has exactly one parent:
VALID STACK (linear):
main → feature-a → feature-b → feature-c
INVALID (not a stack):
main → feature-a → feature-b
└─────→ feature-x
gt down moves from feature-b → feature-a → maingt up moves from feature-a → feature-b → feature-cmain or master) that all stacks build uponWhen working with Graphite stacks, always visualize trunk at the BOTTOM:
TOP ↑ feat-3 ← upstack (leaf)
feat-2
feat-1
BOTTOM ↓ main ← downstack (trunk)
Given stack: main → feat-1 → feat-2 → feat-3
If current branch isfeat-1:
feat-2, feat-3 (children, toward top)main (parent, toward bottom)If current branch isfeat-3 (at top):
feat-2, feat-1, main (ancestors, toward bottom)🔴 Commands depend on this visualization:
gt up / gt down navigate the stackland-stack traverses branches in specific direction🔴 Common mistake: Thinking "upstack" means "toward trunk"
🔴 PR landing order: Always bottom→top (main first, then each layer up)
All gt metadata is stored in the shared .git directory (accessible across worktrees):
.git/.graphite_repo_config - Repository-level configuration (trunk branch).git/.graphite_cache_persist - Branch relationships (parent-child graph).git/.graphite_pr_info - Cached GitHub PR informationImportant : Metadata is shared across all worktrees since it's in the common .git directory.
Remember: ALL gt commands below must include--no-interactive (see CRITICAL: Always Use --no-interactive above).
| Command | Alias | Purpose |
|---|---|---|
gt create [name] | gt c | Create new branch stacked on current branch and commit staged changes |
gt modify | gt m | Modify current branch (amend commit) and auto-restack children |
gt submit | gt s | Push branches and create/update PRs |
gt submit --stack |
| Command | Alias | Purpose |
|---|---|---|
gt up [steps] | gt u | Move up stack (away from trunk) |
gt down [steps] | gt d | Move down stack (toward trunk) |
gt top | gt t | Move to tip of stack |
gt bottom |
| Command | Purpose |
|---|---|
gt restack | Ensure each branch has its parent in git history |
gt move | Rebase current branch onto different parent |
gt fold | Fold branch's changes into parent |
gt split | Split current branch into multiple single-commit branches |
gt log | Visualize stack structure |
| Command | Purpose |
|---|---|
gt branch info | Show branch info (parent, children, commit SHA) |
gt parent | Show parent branch name |
gt children | Show children branch names |
gt track [branch] | Start tracking branch with gt (set parent) |
gt untrack [branch] | Stop tracking branch with gt |
gt delete [name] |
Build a feature in multiple reviewable chunks:
# 1. Start from trunk
gt checkout main --no-interactive
git pull
# 2. Create first branch
gt create phase-1 -m "Add API endpoints" --no-interactive
# ... make changes ...
git add .
gt modify -m "Add API endpoints" --no-interactive
# 3. Create second branch on top
gt create phase-2 -m "Update frontend" --no-interactive
# ... make changes ...
git add .
gt modify -m "Update frontend" --no-interactive
# 4. Submit entire stack
gt submit --stack --no-interactive
# Result: 2 PRs created
# PR #101: phase-1 (base: main)
# PR #102: phase-2 (base: phase-1)
Update a branch in the middle of a stack:
# Navigate down to target branch
gt down --no-interactive # Repeat as needed
# Make changes
# ... edit files ...
git add .
# Modify (auto-restacks upstack branches)
gt modify -m "Address review feedback" --no-interactive
# Resubmit stack
gt submit --stack --no-interactive
Insert a new branch in the middle:
# Checkout the parent where you want to insert
gt checkout phase-1 --no-interactive
# Create new branch with --insert
gt create phase-1.5 --insert -m "Add validation" --no-interactive
# Submit new PR
gt submit --no-interactive
Clean up after PRs merge on GitHub:
# Run sync (--no-interactive auto-confirms branch deletion)
gt sync --no-interactive
# Result:
# - Merged branches deleted locally
# - Remaining branches rebased onto trunk
# - PR bases updated on GitHub
Break up a large commit into reviewable pieces:
# Checkout branch with large commit
gt checkout large-feature --no-interactive
# Split into single-commit branches
gt split --no-interactive
# Rename branches meaningfully
gt rename add-api-endpoints --no-interactive
gt up --no-interactive
gt rename add-frontend --no-interactive
gt up --no-interactive
gt rename add-tests --no-interactive
# Submit
gt submit --stack --no-interactive
Don't usegit rebase directly: Use gt modify or gt restack - gt needs to update metadata during rebasing
Don't delete branches withgit branch -d: Use gt delete - metadata needs to be updated to re-parent children
Don't assumegt submit only affects current branch: It submits downstack too (all ancestors). Use gt submit --stack to include upstack
Don't forget togt sync after merges: Stale branches accumulate and metadata gets outdated
When to use gt commands:
gt create (sets parent relationship)gt modify (auto-restacks children)gt up/down/top/bottom (move through chain)gt log (see visualization)gt branch info (parse "Parent:" line)gt parent / gt children (quick access)gt submit --stack (create/update all PRs)Contains detailed command reference and comprehensive mental model documentation:
gt-reference.md - Complete command reference, metadata format details, and advanced patternsLoad this reference when users need detailed information about specific gt commands, metadata structure, or complex workflow scenarios.
Weekly Installs
53
Repository
GitHub Stars
74
First Seen
Jan 29, 2026
Security Audits
Gen Agent Trust HubPassSocketPassSnykWarn
Installed on
github-copilot53
codex53
opencode52
claude-code52
kimi-cli52
gemini-cli52
React 组合模式指南:Vercel 组件架构最佳实践,提升代码可维护性
123,700 周安装
gt ss |
| Submit entire stack (up + down) |
gt sync | - | Sync from remote and prompt to delete merged branches |
gt b |
| Move to bottom of stack |
gt checkout [branch] | gt co | Interactive branch checkout |
| Delete branch and update metadata |
gt rename [name] | Rename branch and update metadata |
⚠️ NEVER usegt log short for branch status: The output format is counterintuitive and confuses agents. Use gt branch info, gt parent, or gt children for explicit metadata access instead
gt sync (clean up + rebase)gt move (change parent)gt fold (merge into parent)gt split (break into branches)