面向 GitHub PR 与 GitLab MR patch 流的 Rust CLI

Patchsplit

逐 commit 下载 GitHub Pull Request 或 GitLab merge request 的 patch,通过 --squash 导出最终变更的一份 diff,或用 --commit 按哈希获取单个 commit。无需克隆来源仓库,即可审阅、分享或应用变更。

$ patchsplit openai codex 42 -o pr-42-patches
downloaded https://github.com/openai/codex/pull/42.patch
wrote 2 patch file(s)
pr-42-patches/0001-add-parser.patch
pr-42-patches/0002-wire-cli.patch
v1.3.0最新版本
1 个 PR/MR输入
N / 1patch 文件数
curl运行时依赖

Patchsplit

为 patch 级 review 工作流而写

它把流程保持得很明确:拉取 PR 或 MR 的 patch,按 commit 边界拆分,并写出可预测且不会意外覆盖的文件。

01

GitHub 与 GitLab 双平台

下载 GitHub pull request 和 commit,或通过 --gitlab 从 gitlab.com 下载 merge request 和 commit,支持含子群组的项目路径。

02

三种补丁模式

逐 commit 保留 patch,用 --squash 将 PR 的最终变更导出为 pr-<pr-number>.patch,或通过 --commit <hash> 下载单个 commit。

03

可预测文件名

每个文件使用四位序号加清理后的 commit subject,例如 0001-add-parser.patch。

04

默认拒绝覆盖

已存在的输出文件默认会被保护。只有明确传入 --force 时才会替换。

05

克制的依赖面

系统 curl 负责下载,thiserror 2 提供 Rust 错误类型。源码构建需要 Rust 和 Cargo;应用 patch 和运行 Unix 测试需要 Git。

i18n

CLI 输出本地化

用户可见的 CLI 文本现在通过基于 PO 的 i18n 层处理。简体中文翻译已内置,也可以在运行时加载外部 UTF-8 .po catalog。

Locale 选择

Patchsplit 会依次检查 PATCHSPLIT_LANGUAGE、LANGUAGE、LC_ALL、LC_MESSAGES、LANG,并使用第一个匹配的 locale。

Catalog 位置

可以设置 PATCHSPLIT_LOCALEDIR,也可以把 .po catalog 放在可执行文件旁边的 locale/、po/ 或 ../share/locale。

刷新模板

运行 scripts/update-pot.sh,可从 po/POTFILES.in 列出的源码文件重新生成 po/patchsplit.pot。

PATCHSPLIT_LANGUAGE=zh_CN patchsplit openai codex 42
scripts/update-pot.sh

Flow

从 PR 到 patch 集

01

指向 Pull Request

Patchsplit 根据仓库和 PR/MR 编号拼出 GitHub 或 GitLab 的 .patch URL。

02

下载 patch 流

curl 会跟随跳转、在 HTTP 错误时失败,并带上 patchsplit 版本作为 user agent。

03

按 commit 拆分

mail patch 中的 From 标记定义 commit 边界;原始单 patch 会保留为一个文件。

04

写出可移植文件

默认输出到 patches/,也可以通过 --out 指定目录。

CLI

用法

GitHub 与 GitLab 命令共享相同的参数:默认逐 commit 输出,--squash 导出最终 diff,--commit 下载单个 commit。应用 patch 时,请在目标仓库中切换到兼容的基线。

仓库简写

patchsplit <owner/repo> <pr-number> [--out <dir>] [--force] [--squash]
patchsplit rust-lang/rust 12345

拆开 owner 和 repo

patchsplit <owner> <repo> <pr-number> [--out <dir>] [--force] [--squash]
patchsplit openai codex 42 -o pr-42-patches

单个 commit

patchsplit <owner/repo> --commit <hash> [--out <dir>] [--force]
patchsplit zitzhen/patchsplit --commit b430113
patchsplit zitzhen patchsplit -commit b430113

GitLab merge request

patchsplit --gitlab <namespace/project> <mr-number> [--out <dir>] [--force] [--squash]
patchsplit --gitlab zitzhen/patchsplit 1
patchsplit --gitlab group/subgroup/project 1 --squash -o mr-1-patches

逐 commit 的 patch

带序号的邮件格式 patch 保留提交信息与作者身份。在目标仓库内使用 git am 应用。

patchsplit openai/codex 42 -o pr-42-patches
git am /path/to/pr-42-patches/*.patch

一份合并 diff

下载从 merge base 到 head 的最终 .diff,合并重复修改,消除已撤销的变更。GitHub 输出 pr-<pr-number>.patch,GitLab 输出 mr-<number>.patch,均不含提交信息和作者身份,使用 git apply 应用。

patchsplit openai/codex 42 --squash -o pr-42-patches
patchsplit --gitlab zitzhen/patchsplit 1 --squash -o mr-1-patches
git apply --check /path/to/pr-42-patches/pr-42.patch
git apply /path/to/pr-42-patches/pr-42.patch

单个 commit 的补丁

不传 PR 编号,改用 --commit <hash> 传入短哈希或完整哈希。该 commit 的邮件格式补丁会原样保存为 <hash>.patch,保留提交信息与作者身份,且不能与 --squash 同时使用。

patchsplit zitzhen/patchsplit --commit b430113 -o commit-patches
git am /path/to/commit-patches/b430113.patch

GitLab merge request

通过 --gitlab 从 gitlab.com 获取 merge request 并拆分为带序号的邮件格式 patch,保留提交信息与作者身份,项目路径可包含子群组。使用 git am 应用。

patchsplit --gitlab zitzhen/patchsplit 1 -o mr-1-patches
git am /path/to/mr-1-patches/*.patch

最终 diff 为空时会报错且不写入文件。二进制内容受平台 diff 提供的数据限制。合并输出不是可供 git am 使用的邮件格式。

参数

-o, --out <dir>
指定拆分后 patch 文件的输出目录,默认是 patches/。
-f, --force
允许覆盖已存在的 patch 文件。
-h, --help
显示帮助。
-s, --squash
将 Pull Request 的最终 diff 写成一个 patch,配合 git apply 使用。
--gitlab
从 gitlab.com 下载 merge request 或单个 commit。
--commit <hash>
下载单个 commit 的 .patch,接受短哈希或完整哈希,不能与 --squash 同时使用。
-V, --version
显示版本。

Packages

安装 Patchsplit

可以通过 Ubuntu PPA、发行版软件包、预构建归档或源码安装。运行时需确保 PATH 中有 curl。

Linux

下载 Linux (x86_64)
tar -xzf patchsplit-linux-x86_64.tar.gz
chmod +x patchsplit
sudo install -m 755 patchsplit /usr/local/bin/patchsplit
patchsplit --version

Debian

下载 Debian (x86_64)
curl -fLO https://github.com/zitzhen/patchsplit/releases/download/v1.3.0/patchsplit_1.3.0-1.ubuntu26.04.1_amd64.deb
sudo apt install ./patchsplit_1.3.0-1.ubuntu26.04.1_amd64.deb
patchsplit --version

Debian / Ubuntu:本次附件是 Ubuntu 26.04 构建,请确认与发行版兼容。apt 会处理声明的 curl 依赖。

Fedora

下载 Fedora (x86_64)
curl -fLO https://github.com/zitzhen/patchsplit/releases/download/v1.3.0/patchsplit-1.3.0-1.fc44.x86_64.rpm
sudo dnf install ./patchsplit-1.3.0-1.fc44.x86_64.rpm
patchsplit --version

Fedora / RHEL:本次附件面向 Fedora 44,请在兼容系统上使用。选择主软件包,不要选择 debuginfo 或 debugsource。

macOS

下载 macOS (x86_64)
tar -xzf patchsplit-macos-x86_64.tar.gz
chmod +x patchsplit
sudo install -m 755 patchsplit /usr/local/bin/patchsplit
patchsplit --version

如果 macOS 阻止已验证且可信的二进制,可移除隔离属性:xattr -d com.apple.quarantine /usr/local/bin/patchsplit

Windows

下载 Windows (x86_64)
Expand-Archive .\patchsplit-windows-x86_64.zip -DestinationPath .\patchsplit
.\patchsplit\patchsplit.exe --version

将解压目录加入用户 Path 后可全局使用。还需确保 curl.exe 位于 Path 中。

Ubuntu(PPA)

添加项目 PPA,刷新软件包索引,然后安装 Patchsplit:

sudo add-apt-repository ppa:zitzhen/patchsplit
sudo apt update
sudo apt install patchsplit

从源码安装

准备 Rust、Cargo 和 Git;运行 CLI 需要系统 curl。请确保 Cargo 二进制目录(通常为 ~/.cargo/bin)位于 PATH:

git clone https://github.com/zitzhen/patchsplit.git
cd patchsplit
cargo install --path . --locked
patchsplit --version

Arch Linux(AUR)

patchsplit-bin 是由 lingbopro 维护的社区包,可选择以下任一 AUR 助手安装:

paru -S patchsplit-binyay -S patchsplit-bin
查看 AUR 包

Automation

发版流程

推送 v* tag,或手动运行 Release workflow 并指定 ref 和发布 tag。不存在的 tag 指向 workflow 的 commit。检查包含 x86_64 归档和发行版软件包的草稿后发布;发布会触发 Notify PPA,对源码包签名并上传至 Launchpad 构建。

发布产物

git tag v1.x.x
git push origin v1.x.x

让 Pull Request patch 小到可以逐个检查。

打开项目仓库