The Problem: Large PRs Kill Code Review
If you've worked in a team with strict code review requirements, you've felt the pain. You spend a week building a feature, submit a pull request with 50 files changed, and then... silence. The PR sits there. Reviewers open it, see the diff, and quietly close the tab.
Large PRs are where code review goes to die. Reviewers can't hold the full context in their heads. They skim instead of reading. Bugs slip through. The feedback cycle stretches from hours to days.
The solution is well-known: stacked PRs. Break your work into small, logical commits. Submit each as its own PR. Reviewers see focused changes. You get faster feedback. Everyone wins.
But here's the catch — managing stacked PRs is painful. You need to:
- →Create a branch for each commit
- →Set the correct base branch for each PR
- →Update all downstream branches when you amend a commit
- →Keep PR bases in sync after rebasing
- →Clean up branches after merging
That's a lot of git gymnastics. And if your team isn't on GitHub? Most existing tools won't help you.
So I built pilegit.
What pilegit Does
pilegit is a terminal-based tool that lets you develop on a single branch, then submit each commit as a stacked PR. The workflow is simple:
p to submit a commit as a PR with the correct base.s to force-push all branches and update PR bases.
The key insight is that pilegit manages the branch-per-commit mapping for you. Each commit gets a branch named pgit/<username>/<subject>. When you reorder, squash, or amend commits, pilegit updates the branches and syncs with the remote.
Multi-Platform Support
Most stacking tools assume GitHub. But I work with teams on GitLab and Phabricator. I needed something portable.
pilegit supports five platforms out of the box:
| Platform | CLI Tool | Notes |
|---|---|---|
| GitHub | gh |
The most common setup |
| GitLab | glab |
Full MR support |
| Gitea | tea |
For self-hosted setups |
| Phabricator | arc |
Differential workflow |
| Custom | Any shell command | Use {hash}, {subject} placeholders |
This is implemented via a Forge trait. Adding a new platform means implementing a handful of methods:
pub trait Forge {
fn submit(&self, repo: &Repo, hash: &str, subject: &str,
base: &str, body: &str) -> Result<String>;
fn update(&self, repo: &Repo, hash: &str, subject: &str,
base: &str) -> Result<String>;
fn list_open(&self, repo: &Repo) -> (HashMap<String, u32>, bool);
fn edit_base(&self, repo: &Repo, branch: &str, base: &str) -> bool;
fn sync(&self, repo: &Repo, patches: &[PatchEntry],
on_progress: &dyn Fn(&str)) -> Result<Vec<String>>;
fn name(&self) -> &str;
}
How It Works Under the Hood
pilegit doesn't try to reinvent git. Every operation maps to standard git commands:
| Action | Git Operation |
|---|---|
| Reorder commits | git rebase -i with automated todo editing |
| Remove commit | git rebase -i → drop |
| Squash commits | git rebase -i → pick + squash |
| Edit commit | git rebase -i → edit + commit --amend |
| Undo | git reset --hard <saved-HEAD> |
| Submit PR | git branch -f + git push -f + CLI |
Why shell out to git? I considered using git2-rs (libgit2 bindings), but interactive rebase is complex to replicate. Shelling out to git rebase -i with automated todo file editing is more reliable and matches what users expect. The tool works exactly like git because it is git.
The undo system is particularly satisfying. Before any destructive operation, pilegit saves your current HEAD hash. Pressing u runs git reset --hard <saved-HEAD> — your actual git state is restored, not just the UI.
Why Rust?
I chose Rust for a few reasons:
Robustness. Git operations can fail in many ways — network issues, merge conflicts, permission errors. Rust's Result type forces you to handle every failure path. The compiler catches bugs that would be runtime surprises in other languages.
Performance. The TUI needs to feel instant. Rust compiles to native code with no runtime overhead. Parsing the commit graph, rendering the UI, and handling input all happen without perceptible lag.
Ecosystem. The ratatui library makes building terminal UIs surprisingly pleasant. Combined with crossterm for cross-platform terminal handling, you get a polished experience on Linux, macOS, and Windows.
Single binary. cargo install pilegit gives you a self-contained pgit binary. No Python virtual environments, no Node.js, no runtime dependencies. Copy it anywhere and it works.
Comparison with Existing Tools
There are other tools in this space. Here's how pilegit compares:
| Feature | pilegit | git-branchless | Graphite | ghstack | Stacked Git |
|---|---|---|---|---|---|
| Interactive TUI | ✓ | ✓ | – | – | – |
| Single-branch workflow | ✓ | ✓ | – | ✓ | ✓ |
| Stacked PR submission | ✓ | partial | ✓ | ✓ | – |
| Multi-platform | 5 forges | git only | GitHub | GitHub | git only |
| Undo/redo | ✓ | ✓ | – | – | – |
| No daemon required | ✓ | – | – | ✓ | ✓ |
git-branchless is excellent for local commit graph manipulation but doesn't handle PR submission across forges. Graphite is polished but GitHub-only and requires a hosted service. ghstack is GitHub-only. Stacked Git (StGit) manages patch series but doesn't submit PRs.
pilegit fills the gap: a local-first, multi-platform tool that handles the full workflow from commit organization to PR submission.
Getting Started
Install with Cargo:
cargo install pilegit
Then run pgit in any git repository. On first run, it prompts you to configure your platform and base branch. The config is saved to .pilegit.toml:
[forge]
type = "github" # github | gitlab | gitea | phabricator | custom
[repo]
base = "origin/main"
From there, the keybindings are intuitive:
| Key | Action |
|---|---|
j/k |
Move cursor up/down |
Ctrl+j/Ctrl+k |
Reorder commit (real git rebase) |
V |
Start visual selection for squash |
e |
Edit/amend commit |
p |
Submit or update PR for commit |
s |
Sync all submitted PRs |
u |
Undo (restores git state) |
? |
Full help screen |
Feedback Welcome
pilegit is open source under the MIT license. I'm actively maintaining it and would love feedback:
- →Found a bug? Open an issue on GitHub — I'll fix it.
-
→Want a new forge? The
Forgetrait makes it straightforward to add. - →Have ideas? I'm happy to discuss workflow improvements.
Check out the project on GitHub: github.com/hokwangchoi/pilegit
Happy stacking.