spr:GitHub上的堆叠拉取请求

Lobsters Hottest 工具

摘要

spr 是一个 CLI 工具,可将 Git 分支上的每个提交转换为 GitHub 上的独立拉取请求,无需手动管理分支即可实现堆叠式 PR。

<p><a href="https://lobste.rs/s/txnyjt/spr_stacked_pull_requests_on_github">评论</a></p>
查看原文
查看缓存全文

缓存时间: 2026/05/18 04:26

ejoffe/spr

来源:https://github.com/ejoffe/spr 徽标 许可证:MIT (https://opensource.org/licenses/MIT) 构建状态 (https://github.com/ejoffe/spr/actions/workflows/ci.yml) 发布页面 (https://GitHub.com/ejoffe/spr/releases/)

每个提交都变成一个拉取请求。别再折腾分支了。
git spr 管理 GitHub 上的堆叠拉取请求,您无需再手动操作。只需在单个分支上编写提交,spr 就会将每个提交转为其自己的拉取请求——保持同步、顺序正确且随时可合并。

终端录屏

为什么要用堆叠 PR?

  • 小型 PR 审核更快。 50 行变更能获得有意义的反馈;500 行变更只能得到“看起来不错”。
  • 不再有分支体操。 别再创建 feature-part-1feature-part-2,再在它们之间变基和解决冲突了。
  • 增量交付。 今天部署数据库迁移,明天部署 API,后天部署 UI——每个都独立审核和合并。
  • 原生 GitHub 体验。 无需额外服务,无需自定义合并机器人。只需拉取请求和分支,spr 为您管理。

快速开始

通过 brew、nix 或下载二进制文件 (https://github.com/ejoffe/spr/releases) 安装:

brew install ejoffe/tap/spr # macOS/Linux
nix profile install github:ejoffe/spr # Nix

然后像普通 git 一样使用——只需把 git push + 手动创建 PR 替换为 git spr update

git commit -m "添加用户认证"
git commit -m "添加登录页面"
git commit -m "添加会话管理"
git spr update # 创建 3 个按顺序堆叠的拉取请求
git spr status # 显示堆叠状态
git spr merge # 合并所有已就绪的 PR

就是这样。每个提交就是一个 PR。修改一个提交后再次运行 git spr update 即可同步变更。

命令

命令别名描述
git spr updateu, up为堆叠中的提交创建并更新拉取请求
git spr statuss, st显示打开的拉取请求的状态
git spr merge合并所有可合并的拉取请求
git spr amenda修改堆叠中的一个提交
git spr edite编辑堆叠中的一个提交(交互式变基)
git spr sync将本地堆叠与远程同步
git spr check运行合并前检查(由 mergeCheck 配置)
git spr version显示版本信息

全局标志: --detail(显示状态位标题)、--verbose(记录 git 命令和 GitHub API 调用)、--debug--profile

安装

Brew

brew tap ejoffe/homebrew-tap
brew install ejoffe/tap/spr

Nix

nix profile install github:ejoffe/spr

或者不安装直接运行:

nix run github:ejoffe/spr

Apt

echo "deb [trusted=yes] https://apt.fury.io/inigolabs/ /" | sudo tee /etc/apt/sources.list.d/inigolabs.list
sudo apt update
sudo apt install spr

二进制文件

从发布页面 (https://github.com/ejoffe/spr/releases) 下载预编译的二进制文件。

从源码构建

make bin # 需要 goreleaser;二进制文件输出到 dist/

使用指南

工作流

像平常一样将更改提交到分支。每个提交都会变成一个拉取请求。

git add feature_1.go
git commit -m "功能 1"
git add feature_2.go
git commit -m "功能 2"
git add feature_3.go
git commit -m "功能 3"
git spr update

提交标题成为 PR 标题;提交正文成为 PR 描述。无需创建分支或调用 git push——git spr update 会处理一切。

进行中的工作: 在提交消息前加上 WIP 前缀可跳过该提交的 PR 创建。准备好后移除前缀即可。

更新拉取请求

运行 git spr update 以同步整个堆叠。新提交会获得新 PR;已修改的提交会自动更新现有 PR。

> git spr update
[⌛❌✅❌] 60: 功能 3
[✅✅✅✅] 59: 功能 2
[✅✅✅✅] 58: 功能 1
标志别名描述
--count-c仅更新堆叠底部指定数量的 PR
--reviewer-r为新建的拉取请求添加审核者
--no-rebase--nr禁用变基(也支持 SPR_NOREBASE 环境变量)

修改提交

暂存更改,然后使用 git spr amend 选择要修改的提交:

> git add feature_2.go
> git spr amend
3 : 5cba235d : 功能 3
2 : 4dc2c5b2 : 功能 2
1 : 9d1b8193 : 功能 1
要修改的提交 [1-3]: 2

使用 --update-u)可在修改后自动运行 git spr update

编辑提交

使用 git spr edit 在特定提交上启动交互式变基会话:

> git spr edit
3 : 5cba235d : 功能 3
2 : 4dc2c5b2 : 功能 2
1 : 9d1b8193 : 功能 1
要编辑的提交 [1-3]: 2

完成后使用 git spr edit --done(添加 -u 也会更新)。取消使用 git spr edit --abort

同步

使用 git spr sync 将远程更改拉取到本地堆叠。在 PR 在 GitHub 上被合并或更新后很有用。

合并

使用 git spr merge 代替 GitHub UI 以按正确顺序合并:

> git spr merge
MERGED #58 功能 1
MERGED #59 功能 2
MERGED #60 功能 3
[✅❌✅✅] 61: 功能 4

spr 会找到堆叠中最顶部的可合并 PR,将该 PR 之前的所有提交整合到一个 PR 中,合并它,并关闭中间的 PR。这避免了触发多余的 CI 运行。

使用 --count N 仅合并底部 N 个拉取请求。

合并状态位

每个 PR 显示四个状态位:

 [✅❌✅✅] 61: 功能 4
 │ │ │ └─ 堆叠:下方所有 PR 均已就绪
 │ │ └──── 冲突:无合并冲突
 │ └─────── 审批:PR 已获批
 └────────── 检查:CI 检查通过
检查待定失败通过不必须
审批未获批已获批不必须
冲突有冲突无冲突
堆叠下方被阻塞全部畅通

通过 .spr.yml 中的 requireChecksrequiredChecksrequireApproval 配置检查和审批要求。当 requiredChecks 列出了特定的检查名称时,仅评估这些检查——忽略所有其他检查。当可选检查(如 linter、部署预览)会导致状态显示为失败时,此功能很有用。

开始新堆叠

从最新的推送状态创建新分支:

git checkout -b new_stack @{push}

配置

配置在首次运行时自动创建。仓库配置位于仓库根目录的 .spr.yml;用户配置位于 ~/.spr.yml

仓库配置 (.spr.yml)

设置类型默认值描述
requireChecksbooltrue要求检查通过才能合并
requiredCheckslist必须通过的检查名称列表。设置后仅评估这些检查,其他忽略
requireApprovalbooltrue要求 PR 获批才能合并
githubRepoOwnerstrGitHub 所有者(从 git 远程自动检测)
githubRepoNamestrGitHub 仓库名称(从 git 远程自动检测)
githubRemotestrorigin使用的 git 远程名称
githubBranchstrmain拉取请求的目标分支
githubHoststrgithub.comGitHub 主机(用于 GitHub Enterprise 时更新)
mergeMethodstrrebase合并方法:rebasesquashmerge
mergeQueueboolfalse使用 GitHub 合并队列
prTemplateTypestrstackPR 模板:stackbasicwhy_whatcustom
prTemplatePathstr自定义 PR 模板文件路径(自动将类型设为 custom
prTemplateInsertStartstr自定义模板中用于插入提交正文的起始标记
prTemplateInsertEndstr自定义模板中用于插入提交正文的结束标记
mergeCheckstrgit spr check 时运行的命令(合并前)
forceFetchTagsboolfalsegit spr update 时获取标签
showPrTitlesInStackboolfalse在 PR 正文的堆叠描述中显示 PR 标题
branchPushIndividuallyboolfalse逐个推送分支而不是原子推送
defaultReviewerslist每个新拉取请求要添加的审核者

.spr.yml 示例:

requireChecks: true
requiredChecks:
  - "ci/test"
  - "ci/build"
requireApproval: true
mergeMethod: squash
defaultReviewers:
  - 队友

用户配置 (~/.spr.yml)

设置类型默认值描述
showPRLinkbooltrue显示完整拉取请求 URL
shortPRLinkboolfalse显示可点击的 PR- 而非完整 URL
showCommitIDboolfalse显示提交哈希的前 8 个字符
logGitCommandsboolfalse将 git 命令记录到标准输出
logGitHubCallsboolfalse将 GitHub API 调用记录到标准输出
statusBitsHeaderbooltrue显示状态位类型标题
statusBitsEmojisbooltrue使用表情符号状态位
createDraftPRsboolfalse将新 PR 创建为草稿
preserveTitleAndBodyboolfalse更新时不要覆盖 PR 标题和正文
noRebaseboolfalsegit spr update 时跳过变基
deleteMergedBranchesboolfalsePR 合并后删除分支
branchPrefixstrsprspr 管理分支名称的前缀

对比

spr 与 Graphite (https://graphite.dev)、ghstack (https://github.com/ezyang/ghstack) 和 Gerrit (https://www.gerritcodereview.com/) 的堆叠审查模型类似——但它纯粹基于 GitHub 的原生拉取请求。无需额外服务、无需自定义合并机器人、无锁定。

贡献

发现 bug?请在 issue 中提出。(https://github.com/ejoffe/spr/issues)
欢迎拉取请求。如果您觉得 spr 有用,点个星标可以帮助其他人发现它。

许可证

MIT 许可证

相似文章

Show HN: Haystack – 审查需要人工关注的PR

Hacker News Top

Haystack 是一个新工具,它用队列取代了 GitHub 的 PR 审查系统,将拉取请求分类为可安全合并、需要修复或需要人工审查三个类别,帮助团队应对来自编码代理的 PR 激增。

在$dayjob审查所谓的Pull Requests

Lobsters Hottest

一位开发者描述了他使用git命令(如range-diff和log -p)来审查pull requests的工作流程,以规避基于Web的UI的缺陷。

Haystack

Product Hunt

Haystack 是一个工具,帮助开发者审查拉取请求,通过过滤掉那些不需要人工关注的请求,从而简化代码审查流程。