GitHub Stacks in Jujutsu

GitHub Stacks in Jujutsu

This article is part of a series on Stacks in Jujutsu. Other articles in the series: GitHub Stacks in Jujutsu <== you are here. 本文是关于 Jujutsu (jj) 中 Stacks 系列文章的一部分。系列其他文章:GitHub Stacks in Jujutsu <== 你在这里。

GitHub released its stacked pull request (PR) feature into public preview on 2026-07-30. It mainly targets git users but has documented support for other, git-compatible version control systems like Jujutsu (jj). This is a primer for using GitHub stacks with jj. GitHub 于 2026 年 7 月 30 日发布了其堆叠式拉取请求(Stacked PR)功能的公开预览版。该功能主要面向 git 用户,但也提供了对其他兼容 git 的版本控制系统(如 Jujutsu (jj))的文档化支持。本文是使用 GitHub stacks 配合 jj 的入门指南。

Prerequisites / 前置条件

Install CLIs / 安装命令行工具 You need the git (instructions) and jj (instructions) CLIs installed. You need the gh GitHub CLI installed (instructions). Install the stacking extension with gh extension install github/gh-stack. 你需要安装 git(说明)、jj(说明)以及 GitHub CLI gh(说明)。通过运行 gh extension install github/gh-stack 安装 stacking 扩展。

This article was written/tested against: jj v0.43.0, git v2.52.0, gh v2.96.0, github/gh-stack v0.1.0. 本文编写及测试环境为:jj v0.43.0, git v2.52.0, gh v2.96.0, github/gh-stack v0.1.0。

Configure jj / 配置 jj I will be re-using some jj aliases and revset aliases we defined in the previous article, Stacks in Jujutsu. 我将沿用我们在上一篇文章《Stacks in Jujutsu》中定义的 jj 别名和 revset 别名。

Bonus: Learn jj’s bookmark aliases / 进阶:学习 jj 的书签别名 GitHub’s Stacked PRs require every PR to have a jj bookmark (git branch), so you’ll be creating a lot of these. UI tools in the future will surely automate creating branch names under the covers, but for now, learn the jj aliases for easily managing bookmarks: GitHub 的堆叠式 PR 要求每个 PR 都有一个 jj 书签(即 git 分支),因此你需要频繁创建它们。未来的 UI 工具肯定会自动处理分支命名,但目前请学习以下用于轻松管理书签的 jj 别名:

Command / 命令Description / 描述
jj b llist bookmarks / 列出书签
jj b s <name> -r <commit>Create (or move) a bookmark to the given commit / 在指定提交处创建(或移动)书签
jj b aAdvance the nearest bookmark to the current commit (like jj tug) / 将最近的书签推进到当前提交(类似于 jj tug
jj b --helpDocs with the aliases for all the commands / 查看所有命令的别名文档

💡 Aside: Did you know that you can improve the default jj bookmark advance (jj b a) behavior by customizing the revset it uses? 💡 题外话:你知道可以通过自定义 revset 来优化默认的 jj 书签推进 (jj b a) 行为吗?

If you’re on a new, empty commit ABOVE a commit with code, you probably want to advance the bookmark to the code commit below you. You can accomplish this with: 如果你位于一个包含代码的提交之上的新空提交中,你通常希望将书签推进到下方的代码提交。你可以通过以下配置实现:

# ~/.config/jj/config.toml
[revset-aliases."closest_pushable(to)"]
definition = 'heads(::to & mutable() & ~empty() & description(regex:".+"))'
doc = "Closest mutable, non-empty, described commits at or behind to"

[revsets]
bookmark-advance-to = "closest_pushable(@)"

jj makes it super easy to customize behavior by overriding the built-in bookmark-advance-to revset to whatever you want. jj 通过覆盖内置的 bookmark-advance-to revset,让你能够极其轻松地自定义行为。

Manual Workflows / 手动工作流

The gh stack CLI has a bunch of subcommands, most of which manage or consume local tracking of the stack (e.g. init, view). In a jj repo you will only use the few subcommands that manage the remote stack on GitHub (e.g. link, push), as follows: gh stack 命令行工具包含许多子命令,其中大多数用于管理或使用本地的堆栈追踪(如 init, view)。在 jj 仓库中,你只需要使用少数几个管理 GitHub 远程堆栈的子命令(如 link, push),具体如下:

Create a stack / 创建堆栈 Create a bookmark for each commit in your stack: 为堆栈中的每个提交创建一个书签:

# go to the bottom of your stack using our revset alias
jj edit -r "stack_bottom()"
# give commit a name
jj b c <name>
# go to the next commit
jj next --edit
# give commit a name
jj b c <name>
# ... repeat for each commit in stack

Upload your bookmarks to GitHub, create draft PRs for each, and link them all into a stack: 将书签上传到 GitHub,为每个书签创建草稿 PR,并将它们链接成一个堆栈:

# Using our stack alias:
gh stack link $(jj sb -r "stack()")

Or, using a jj revision range: 或者使用 jj 修订范围:

gh stack link $(jj sb -r commit1::commitN)

Or, since jj sb defaults to your substack, you can go to the top (where your stack and substack are the same thing) and then link the entire stack: 或者,由于 jj sb 默认指向你的子堆栈,你可以直接跳转到顶部(此时堆栈和子堆栈相同),然后链接整个堆栈:

jj top --edit
gh stack link $(jj sb)

This last one is probably the easiest to remember. 最后这种方法可能是最容易记住的。

Add a new commit to the TOP of the stack / 在堆栈顶部添加新提交 Assuming the new commit is change id abc: 假设新提交的 change id 为 abc

  1. Make sure you’re editing your new commit: jj edit -r abc 确保你正在编辑新提交:jj edit -r abc
  2. Create a bookmark for the new, current commit: jj b c <name> 为当前新提交创建书签:jj b c <name>
  3. If you’ve modified any of the downstack commits, you need to push the updates: jj git push -r "stack()" 如果你修改了堆栈下方的任何提交,需要推送更新:jj git push -r "stack()"
  4. Re-run link with all stack bookmarks: gh stack link $(jj sb) 重新运行链接命令:gh stack link $(jj sb)

The existing PRs (for everything downstack) will be skipped and the new branch will get a new draft PR and will be linked into the stack. 现有的 PR(堆栈下方的所有内容)将被跳过,新分支将获得一个新的草稿 PR 并被链接到堆栈中。

Add a new commit to the BOTTOM or MIDDLE of the stack / 在堆栈底部或中间添加新提交 You can’t add to the middle of a stack (you’ll get an error: “Cannot update stack: new PRs must be added to the top of the existing stack”), so you have to delete your stack and recreate it. 你不能在堆栈中间添加提交(会报错:“Cannot update stack: new PRs must be added to the top of the existing stack”),因此你必须删除堆栈并重新创建。

  1. Go to the GitHub web UI and remove the stack. 前往 GitHub Web 界面删除堆栈。
  2. Create a bookmark for the new commit: jj b c -r abc <name> 为新提交创建书签:jj b c -r abc <name>
  3. Since you’ve modified the rebased, upstack commits, re-push everything: jj git push -r "stack()" 由于你修改了变基后的上方提交,重新推送所有内容:jj git push -r "stack()"
  4. Re-run link with all stack bookmarks, including the new one: jj top --edit; gh stack link $(jj sb) 重新运行链接命令:jj top --edit; gh stack link $(jj sb)

Remove a commit from the stack / 从堆栈中移除提交 You have to delete your stack and recreate it. 你必须删除堆栈并重新创建。

  1. Go to the GitHub web UI and remove the stack. 前往 GitHub Web 界面删除堆栈。
  2. Make sure you’re at the top of the stack: jj top --edit 确保位于堆栈顶部:jj top --edit
  3. Abandon the commit if you haven’t already: jj abandon -r abc 如果尚未放弃该提交,请执行:jj abandon -r abc
  4. Push your updates: jj git push -r "stack()" 推送更新:jj git push -r "stack()"
  5. Re-run link with all stack bookmarks: jj top --edit; gh stack link $(jj sb) 重新运行链接命令:jj top --edit; gh stack link $(jj sb)

Your removed commit will have an orphaned PR on GitHub. Manually close it and/or delete the remote branch if you want. Or, push all deleted bookmarks with jj git push --deleted. 被移除的提交在 GitHub 上会留下一个孤立的 PR。你可以手动关闭它或删除远程分支。或者使用 jj git push --deleted 推送所有已删除的书签。

Update the existing commits of an existing stack / 更新现有堆栈中的提交 Re-push your stack: jj git push -r "stack()" 重新推送堆栈:jj git push -r "stack()"

Merge your stack / 合并堆栈 Like unstacking, it is theoretically possible to do it from the CLI, but too complicated. So, just do this from the web UI. You’ll probably be there anyway, checking on that CI signal. 🤷🏽‍♀️ 和取消堆栈一样,理论上可以通过命令行完成,但太复杂了。所以,直接在 Web 界面操作吧。反正你可能已经在那里查看 CI 状态了。🤷🏽‍♀️