GitHub and GitLab
Fetch GitHub pull requests and commits, or pass --gitlab to download merge requests and commits from gitlab.com, including projects nested under subgroups.
Rust CLI for GitHub PR and GitLab MR patch streams
Download a GitHub Pull Request or GitLab merge request as one patch per commit, export its net changes as a single diff with --squash, or fetch one commit by hash with --commit. Review, share, or apply changes without cloning the source repository.
$ 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.patchPatchsplit
The tool keeps the workflow explicit: fetch the PR or MR patch stream, split by commit boundaries, and write predictable files without surprise overwrites.
Fetch GitHub pull requests and commits, or pass --gitlab to download merge requests and commits from gitlab.com, including projects nested under subgroups.
Keep one patch per commit, use --squash to export net PR changes as pr-<pr-number>.patch, or pass --commit <hash> to download a single commit.
Each file starts with a four-digit index and a sanitized commit subject, such as 0001-add-parser.patch.
Existing output files are protected by default. Add --force only when replacing them is intentional.
System curl handles downloads; thiserror 2 provides Rust error types. Rust and Cargo are needed only for source builds, and Git is used to apply patches and run Unix tests.
i18n
User-facing CLI text now runs through a PO-based i18n layer. Chinese translations are built in, and external UTF-8 .po catalogs can be loaded at runtime.
Patchsplit checks PATCHSPLIT_LANGUAGE, LANGUAGE, LC_ALL, LC_MESSAGES, then LANG, using the first matching locale.
Set PATCHSPLIT_LOCALEDIR or place .po catalogs next to the executable in locale/, po/, or ../share/locale.
Run scripts/update-pot.sh to regenerate po/patchsplit.pot from the files listed in po/POTFILES.in.
PATCHSPLIT_LANGUAGE=zh_CN patchsplit openai codex 42
scripts/update-pot.shFlow
Patchsplit builds the GitHub or GitLab .patch URL from the repository and PR/MR number.
curl follows redirects, fails on HTTP errors, and identifies itself with the patchsplit version.
Mail-style From markers define commit boundaries. A raw single patch is kept as one file.
Output lands in patches/ by default, or in the directory supplied with --out.
CLI
GitHub and GitLab commands share the same flags: per-commit output by default, --squash for the net diff, and --commit for a single commit. Apply patches inside the target repository checked out at a compatible base.
patchsplit <owner/repo> <pr-number> [--out <dir>] [--force] [--squash]
patchsplit rust-lang/rust 12345patchsplit <owner> <repo> <pr-number> [--out <dir>] [--force] [--squash]
patchsplit openai codex 42 -o pr-42-patchespatchsplit <owner/repo> --commit <hash> [--out <dir>] [--force]
patchsplit zitzhen/patchsplit --commit b430113
patchsplit zitzhen patchsplit -commit b430113patchsplit --gitlab <namespace/project> <mr-number> [--out <dir>] [--force] [--squash]
patchsplit --gitlab zitzhen/patchsplit 1
patchsplit --gitlab group/subgroup/project 1 --squash -o mr-1-patchesNumbered mail patches retain commit messages and authorship. Apply them with git am from inside the target repository.
patchsplit openai/codex 42 -o pr-42-patches
git am /path/to/pr-42-patches/*.patchThe aggregate .diff contains net changes from merge base to head. Repeated edits merge and reverted changes disappear. GitHub writes pr-<pr-number>.patch and GitLab writes mr-<number>.patch; neither has commit messages or authorship and both are applied with 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.patchPass --commit <hash> with a short or full commit hash instead of a PR number. The mail-formatted patch is saved verbatim as <hash>.patch, keeping its commit message and authorship. It cannot be combined with --squash.
patchsplit zitzhen/patchsplit --commit b430113 -o commit-patches
git am /path/to/commit-patches/b430113.patchPass --gitlab to fetch a merge request from gitlab.com and split it into numbered mail patches, keeping commit messages and authorship. Project paths may include subgroups. Apply with git am.
patchsplit --gitlab zitzhen/patchsplit 1 -o mr-1-patches
git am /path/to/mr-1-patches/*.patchAn empty net diff is an error and writes no file. Binary content is limited to what the platform includes in its diff. Combined output is not a git am mailbox.
Packages
Install from the Ubuntu PPA, a distribution package, a prebuilt archive, or source. curl must be available in PATH for the CLI.
tar -xzf patchsplit-linux-x86_64.tar.gz
chmod +x patchsplit
sudo install -m 755 patchsplit /usr/local/bin/patchsplit
patchsplit --versioncurl -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 --versionDebian / Ubuntu: this release provides an Ubuntu 26.04 build. Check compatibility with your distribution; apt resolves the declared curl dependency.
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 --versionFedora / RHEL: this artifact targets Fedora 44. Use a compatible system and choose the main package, excluding debuginfo and debugsource.
tar -xzf patchsplit-macos-x86_64.tar.gz
chmod +x patchsplit
sudo install -m 755 patchsplit /usr/local/bin/patchsplit
patchsplit --versionIf macOS blocks a binary you have verified and trust, remove its quarantine attribute: xattr -d com.apple.quarantine /usr/local/bin/patchsplit
Expand-Archive .\patchsplit-windows-x86_64.zip -DestinationPath .\patchsplit
.\patchsplit\patchsplit.exe --versionAdd the extracted directory to your user Path for global use. curl.exe must also be in Path.
Add the project PPA, refresh the package index, and install Patchsplit:
sudo add-apt-repository ppa:zitzhen/patchsplit
sudo apt update
sudo apt install patchsplitInstall Rust, Cargo, and Git; system curl is required to run the CLI. Ensure the Cargo binary directory (usually ~/.cargo/bin) is in PATH:
git clone https://github.com/zitzhen/patchsplit.git
cd patchsplit
cargo install --path . --locked
patchsplit --versionThe community-maintained patchsplit-bin package is maintained by lingbopro. Install with either AUR helper:
paru -S patchsplit-binyay -S patchsplit-binAutomation
Push a v* tag, or run the Release workflow manually with a ref and release tag. A missing tag points to the workflow commit. Review and publish the draft containing x86_64 archives and distribution packages. Publishing triggers Notify PPA to sign and upload a source package to Launchpad for building.
git tag v1.x.x
git push origin v1.x.x