projects
patch-stack-action
Mar 2026
Maintaining a fork is easy until it isn’t. You pick up a few local features, upstream marches on, and within weeks you’re thousands of commits behind. Every sync becomes branch surgery: rebase, fix conflicts, pray nothing broke, repeat.
patch-stack-action treats each fork modification as a discrete patch branch. A reusable GitHub Actions workflow discovers your patches, rebases them onto fresh upstream, rebuilds fork/main, and uses Claude Code to resolve conflicts when git can’t.
Branch naming as dependency graph
Dependencies between patches are encoded in the branch name itself. No config file, no metadata; the name is the schema.
patch/fix-auth # root — rebases onto upstream
patch/fix-auth--improve-token-refresh # depends on fix-auth
patch/fix-auth--improve-token-refresh--cleanup # depends on improve-token-refresh
patch/perf-improvement # independent root
Strip the last --segment and you get the parent. Roots rebase directly onto the fork-local upstream mirror branch.
The rebuild model
Each run reconstructs fork/main as a clean stack:
fork/upstream + preserved base commits + patch-stack commits
Commits already on fork/main that aren’t patch-stack-generated are preserved. Local fork plumbing (workflow files, README tweaks) stays put while patches are rebuilt on top.
Patch-stack commits use a patch-stack: subject prefix and a Patch-Stack-Branch: trailer so future runs can tell them apart from preserved work.
Lifecycle
When a patch’s upstream PR is merged, the branch is deleted. When upstream fixes the same problem by other means, the PR is closed and the branch is renamed to archived/*. Dependent branches collapse upward: patch/merged--child becomes patch/child.
AI conflict resolution
When a rebase produces conflicts that git can’t resolve mechanically, the workflow hands them to Claude Code. It reads the PR description, the patch intent, and the conflicting hunks, then produces a resolution. This turns what would be a manual intervention into an automated step.