Prologue: The Problem of Patch-Based Development
In the early 2000s, the Linux kernel development community faced a unique challenge. Thousands of developers contributed patches via email to mailing lists, where maintainers would review, request changes, and eventually merge them. Unlike modern pull request workflows, patches were iterative—often going through 10, 20, or even 30 revisions before acceptance.
Developers needed a way to maintain stacks of patches: organized series of changes that could be reordered, modified, and rebased while preserving their logical separation. Git, which Linus Torvalds released in April 2005, provided the foundation, but lacked native tooling for this workflow.
The Patch Stack Philosophy
A patch stack treats each logical change as an independent unit. Instead of one monolithic branch with mixed concerns, developers maintain discrete patches that can be individually modified, reordered, or dropped. This creates cleaner commit histories and easier code review.
Catalin Marinas, an ARM Linux kernel engineer, felt this pain acutely. Managing dozens of patches for ARM architecture support meant constant rebasing, careful tracking of what had been upstreamed, and painful merge conflicts. He needed tooling that understood patch stacks natively.
"With a patch stack workflow, multiple patches can be developed concurrently and efficiently, with each patch focused on a single concern, resulting in both a clean Git commit history and improved productivity." — StGit README
On July 10, 2005—just three months after Git's initial release—Catalin committed the first version of Stacked Git. The tool that would serve kernel developers for over two decades was born.
2005-2020 Era 1: The Python Foundation
The original StGit was a Python application of surprising sophistication. The initial commit (Release 0.4) shipped with 20 files totaling 2,871 lines of code, implementing the core operations that would define the tool: new, push, pop, refresh, and series.
The Initial Architecture (v0.4)
The founding release established patterns that would persist for 17 years:
stgit/
├── main.py # Command dispatch, 819 lines of interleaved commands
├── stack.py # Patch stack data model, 535 lines
├── git.py # Git operations wrapper, 413 lines
├── config.py # Configuration handling
└── utils.py # Shared utilities
Command Structure Architecture
How should StGit organize its growing set of subcommands?
Release 0.5: The Mailing List Revolution (August 2005)
Within a month, StGit gained the features that made it indispensable for kernel development. The mail command (b4bddc06) allowed developers to send patch series directly to mailing lists—a critical feature when email was the primary collaboration mechanism.
stg mail
Send patches via SMTP with proper threading and cover letters. Integrated maintainer aliases.
stg import
Import patches from files, mbox format, or URLs. Parse email headers to extract authorship.
stg pull
Integrate upstream changes while preserving the patch stack. Automatic rebasing.
stg clean
Remove empty patches after conflicts are resolved. Stack hygiene.
How to integrate with upstream mailing lists?
Kernel patches flow through email. How should StGit participate?
Release 0.6-0.7: Clone, Fold, Pick (September 2005)
The pace was relentless. September brought clone for initializing stacks in new repositories, fold for merging patches, id for showing patch hashes, and crucially, pick for cherry-picking patches between stacks.
Release 0.7 also restored the tutorial to the repository (d1c8fcd7)—a sign that adoption was growing and documentation mattered.
Release 0.8-0.9: Branch Management and UX (October 2005)
These releases focused on ergonomics. Branch cloning (cc3db2b1) allowed creating new stacks from existing ones. The show command displayed patch contents. Pager support (52f3900c) made reading diffs comfortable. And refresh --undo provided a safety net.
Release 0.10: The Testing Foundation (November 2005)
A pivotal release. Catalin copied Git's testsuite framework (aa9b1b9d), establishing automated testing that would protect the codebase through decades of changes.
How to ensure StGit quality and prevent regressions?
The goto command also appeared in 0.10 (994fdba7)—allowing direct navigation to any patch in the stack. Help output was classified by command category (5dc51fea), improving discoverability.
The Long Tail: v0.11 - v0.22 (2006-2020)
Over the next 14 years, StGit evolved steadily. Each release addressed real-world pain points from kernel developers and other users:
apt. Series file editing allowed reordering patches with a text editor.
git status -s alias (aa99027f). Philosophy: don't duplicate Git where unnecessary.
python2 executable explicitly (97987532), preparing for the Python 3 transition.
Notable Issues from Era 1
GitHub Issues provided visibility into real-world usage patterns and pain points:
Key Decisions Throughout Era 1
How to bring external patches into a stack?
How to integrate upstream changes while preserving the patch stack?
Should StGit duplicate Git functionality or wrap it?
How should StGit convert regular commits to patches?
How should StGit integrate with editors?
Era 1 Summary
In 15 years, Era 1 established StGit as the definitive patch stack tool. Starting from 2,871 lines of Python, it grew to a comprehensive system with 22 releases, supporting the Linux kernel's patch-email workflow. The architecture was stable, the test suite comprehensive, and the user base loyal.
But Python was showing its age. Startup time was noticeable. The codebase had accumulated technical debt. And a new maintainer was about to ask: what if we rewrote it in Rust?
2020-2022 Era 2: Python Maturation
Between 2020 and 2022, StGit underwent significant modernization while still in Python. This era saw the project professionalize its processes, reach v1.0 after 15 years, and prepare the foundation for what would become the Rust rewrite.
Release v0.23: Project Modernization (October 2020)
CONTRIBUTING.md was added (91cf6737), signaling a new focus on community growth. GitHub CI Actions replaced Travis CI (c2dfe597). Black formatting was applied (cb053a02). The Python codebase was being prepared for serious maintainership.
How should StGit prepare for Python 3 exclusively?
Release v1.0: First Major Version (February 2021)
After 15+ years of 0.x releases, StGit finally reached v1.0. This wasn't a dramatic feature release—it was a statement of stability and maturity.
-C option added to import/fold (51ffa0b4).
stgit.new.verbose config option added.
stgit.autosign configuration.
Era 2 Summary
Era 2 transformed StGit from a mature tool into a professionally maintained project. CI/CD, code formatting, contribution guidelines, and a proper version scheme brought StGit into the modern development era. But even as v1.5 shipped, the Rust rewrite was already underway.
2022 Era 3: The Rust Rewrite
In 2021, Peter Grayson began what would become StGit's most ambitious transformation: a complete rewrite from Python to Rust. The goal wasn't just language migration—it was to make StGit faster, safer, and more maintainable for the next 20 years.
Why Rust?
Python's startup overhead was noticeable when running many stg commands in scripts (see #145). Type safety was enforced only by discipline. Error handling was inconsistent. And the git2 library for Rust provided robust Git operations without shelling out to git commands.
How to rewrite StGit from Python to Rust?
The Rewrite Timeline
git format-patch and git send-email with StGit patch name support (97ba3cad). The mail workflow preserved.
unsafe blocks in the codebase. Safety achieved.
Notable Issues During the Rewrite
Key Technical Decisions in the Rewrite
clap for CLI
Command-line parsing with clap. Type-safe argument handling. Automatic help generation.
git2 crate
Rust bindings to libgit2. Direct Git operations without shelling out. Faster and safer.
Zero unsafe
No unsafe blocks in the StGit codebase. Memory safety guaranteed by the compiler.
Typed Arguments
Patch names, ranges, and specifiers are now strongly typed. Compile-time correctness.
Era 3 Summary
The Rust rewrite was a triumph of incremental migration. By maintaining feature parity throughout and using a hybrid pyo3 approach, Peter Grayson delivered a complete language migration in under a year. The result: a faster, safer, more maintainable StGit ready for the next two decades.
2022-Present Era 4: Rust Maintenance & Evolution
With the Rust foundation in place, Era 4 has focused on refinement, new features, and keeping StGit current with the Rust ecosystem. In just 3 years, there have been 886 commits and 35 releases—more than all of Era 1.
Post-Rewrite Stabilization (v2.0.1 - v2.0.4)
The first months after v2.0.0 focused on catching edge cases and ensuring the Rust implementation matched Python's behavior exactly. Issues like #256: author set to gitoxide and #273: Windows errors drove rapid iteration.
v2.1.0: Configurable Conflict Policy (December 2022)
The first feature release post-rewrite. Configurable conflict resolution policies gave users control over how StGit handles merge conflicts during push operations. This addressed #212: stg rebase conflict handling.
Should StGit switch from git2 to gitoxide?
gitoxide is a pure-Rust Git implementation under active development.
v2.2.0: gitoxide Adoption (February 2023)
A significant architectural change. StGit migrated from git2 (Rust bindings to libgit2, a C library) to gitoxide (pure Rust Git implementation). This removed the last non-Rust dependency and improved build portability.
v2.3.0: Official Packages (Mid 2023)
Official deb, rpm, and msi packages published. Addressed #324: more .deb versions needed. StGit became installable on Debian, RedHat/Fedora derivatives, and Windows without building from source.
v2.4.0: After a 1-Year Gap (Late 2024)
After a longer development cycle, v2.4.0 brought accumulated improvements and dependency updates. Fixed #471: stg import --reject broken.
v2.5.0: New Year 2025 Release (January 2025)
New name subcommand for patch renaming
(PR #513).
stg rebase can now be called without arguments
(PR #507).
Commands organized by group in help output
(PR #514).
v2.5.5: Current Latest (November 2025)
Squash improvements preserving consensus authors (#490). Continuous stgit.el Emacs mode updates (PR #536, PR #552, PR #573). gix (gitoxide) updated to 0.74.
Continuous stgit.el Maintenance
Throughout Era 4, the Emacs integration (stgit.el) has received continuous attention, driven by issues like
#521: stgit.el update and
#560: Emacs backwards compatibility:
- Migrated to
with-eval-after-loadfrom deprecated patterns - Switched from
defadvicetoadvice-add - Fixed checkdoc warnings
- Enabled lexical-binding
- Support for Emacs versions < 31
- Proper
--no-colorflag handling
Recent and Upcoming Work
Active development continues with PRs for new features:
Era 4 Velocity
| Metric | Era 1 (15 years) | Era 4 (3 years) |
|---|---|---|
| Releases | 22 | 35 |
| Commits | ~1,200 | ~886 |
| Releases/Year | 1.5 | 11.7 |
The Rust codebase enables dramatically faster iteration. Monthly releases are now common.
The People Behind StGit
StGit's 21-year history is remarkable not just for its technical evolution, but for the continuity of its maintainership. Just two primary maintainers have guided the project across two decades.
The Maintainers
Catalin Marinas
Founder, 554 commits
Peter Grayson
Current maintainer, 1,862 commits
Catalin Marinas created StGit in 2005 while working on ARM Linux kernel development. He maintained the project through Era 1, establishing the core concepts and API that persist today.
Peter Grayson took over maintainership and led the Rust rewrite. His 1,862 commits represent over half of all StGit development, including the complete Era 3 and Era 4 work.
Key Contributors
Karl Wiberg
343 commits
Gustav Hållberg
188 commits
Yann Dirson
140 commits
David Kågedal
70 commits
Chuck Lever
62 commits
Topher Brown
29 commits
The Two-Maintainer Model
What's remarkable about StGit's history is the continuity. Unlike many open-source projects that cycle through maintainers every few years, StGit has had essentially two maintainers in 21 years. This has resulted in:
- Consistent vision: The patch stack philosophy remains unchanged from 2005
- Stable API: Commands added in Era 1 still work identically in Era 4
- Deep knowledge: Maintainers understand every corner of the codebase
- Trust: The community knows who stands behind the tool
Conclusion: 21 Years and Counting
Stacked Git is a rare example of open-source longevity. Born from the practical needs of kernel development, it has evolved while staying true to its original purpose: making patch-based workflows manageable.
The decision graph you can explore captures every major choice, every release, and every architectural shift. From Python to Rust, from gna.org to GitHub, from v0.4 to v2.5.5—the history is preserved.
StGit continues to serve developers who need the precision of patch stacks. Whether you're maintaining Linux kernel drivers, developing for Chromium, or managing any complex series of changes, the tool Catalin Marinas created in 2005 remains relevant today.
Explore the Full Decision Graph
This story is derived from a comprehensive decision graph with 416 nodes and 495 edges, tracing every major decision, action, and outcome in StGit's history. Click below to explore the interactive visualization.