π¦ I'm writing this post much earlier than I usually would for all of my work friends. I've been using
gh stacksince the preview was made available in the GitHub UI a few weeks ago. It's a game changer when it comes to working across multiple branches β or it will be just as soon as they get the rest of the kinks worked out.Hopefully this helps explain exactly what the extension does and when you should definitely be using it. Don't miss the agent setup near the end! π₯π¦Ύ
Make Your Diffs Smaller π©»
My boss told me to make my diffs smaller β consistently, and for long enough that I could recite the follow-up before it showed up in the comments: is this really required?
My answer was nearly always yes, and it got overridden often enough that substantial changes stopped making it out the door at all. The obvious problem, the one we all already know, is that large diffs are difficult to read. GitHub agrees in their docs:
Large pull requests are difficult to review and create bottlenecks, especially when AI helps you generate a high volume of code in a short time.
gh stack fixes the thing I'd abandoned trying forever ago: stacking branches so the diffs stay contained and still get released in a single merge.
The concept isn't new, and I've tried to maintain these by hand several times, which is not at all recommended. What's changed is that it's easy to work with β which matters as much on a repo my lead reads as it does on one nobody but an AI ever opens.
A Stack of Pancakes π₯
Think of each PR as a pancake, with the plate being main or whatever trunk branch you started from. Every pancake in the stack targets the layer below it, and GitHub is in charge of the syrup between every layer from the top one down to the plate.
Change a layer at the bottom and those changes have to propagate up through the syrupy goodness into the next one, which used to mean a rebase and a force-push, one at a time, in order, and made the whole thing useless for heavy dev work. Now gh stack manages all the syrup for you.
Building One πͺ
You need gh installed and authenticated, push access to origin, and a clean tree on your trunk branch. Stacked PRs are still in public preview, so expect the edges to move accordingly.
gh extension install github/gh-stack
gh stack init auth-middleware # creates a branch and checks it out
git add . && git commit -m "Add auth middleware"
gh stack add api-routes # next layer, branched off the current one
git add . && git commit -m "Add API routes"
gh stack submit # pushes everything, opens the linked PRs
Branch names pass through exactly as given, slashes and all, so gh stack add refactor/foo gets you refactor/foo. Leave the name off and it stops to ask.
submit is the half that opens pull requests. sync pushes branches and refreshes PRs that already exist, but it has no create path, so a stack you've synced ten times still has nothing on GitHub until you submit.
Getting Around π§
Past two layers I stop remembering which branch I'm standing on, so this is most of what I actually type:
gh stack view
Arrows move through the layers, β΅ checks out whichever one you're sitting on, o opens its PR in the browser, and c and f expand that layer's commits and files without moving you anywhere β so I look at the whole stack, stop on the right pancake, and hit enter.
When I already know where I'm going, the jumps are shorter:
gh stack bottom # the layer sitting on main
gh stack top # the newest layer
gh stack down # one toward the plate
gh stack up 2 # two toward the top
gh stack trunk # back to main itself
Changing a Layer πͺ‘
Editing something at the bottom after the stack exists is the thing gh stack actually buys you. Go to the pancake that owns the change, edit it, commit, and run one command:
gh stack bottom
git add . && git commit -m "Fix the config default"
gh stack sync
If two layers touch the same lines, sync stops on the conflict and restores every branch to where it was, so nothing is left half-rebased.
Dropping a layer takes the stack apart and rebuilds it from the branches you're keeping, in order:
gh stack unstack # drops local tracking and the stack on GitHub
gh stack init auth-middleware api-routes # rebuild without the layer you're dropping
gh stack submit # re-points the bases and relinks the stack
Those branches already exist, so init adopts them rather than creating anything β the commits, the branches, and their open PRs all survive it. The only thing thrown away is the chain between them.
Merging From Where You Stand π΄
One rule covers all of merging: whatever layer you're on merges everything from that layer down to the trunk, using whichever merge option you picked.
Say you've got five layers sitting on main. If you only want the first one, merge layer 1 β layers 2 through 5 stay open and re-target onto the new trunk behind it. If you start from layer 5, you get all five, because everything between layer 5 and the plate goes with it.
That one's open on layer 5, which is why it's offering all five.
Stop Typing Any of That π°οΈ
Everything above this line is optional if you integrate with AI, because of one command sitting in a tip box on GitHub's quickstart page and never mentioned again:
gh skill install github/gh-stack
That's an agent skill, and installing it hands the whole workflow over. The agent creates the stack, puts each concern in its own layer, commits into the layer that owns the change instead of whatever branch happens to be checked out, rebases everything above it, and submits the chain. I stopped running stack commands almost entirely β I describe the layers and read what comes back.
One thing it can't do is decide the layers. Buried in the Copilot tutorial: you own the shape of the stack. The agent proposes them, and I decide whether the boundary between the data model and the endpoints is a real dependency or just where the model ran out of steam.
I've used the skill since I found it and it makes my life a whole lot easier. I also have to keep reminding Claude to use it.
What It Actually Bought Me πͺ
Work started grading us on file diffs per PR, which finally put a price on a habit I'd had for years β sneaking small workflow changes and lint fixes into whatever branch I already had open, because they needed doing and I knew I wouldn't get another chance any time soon. Stacking gave me both halves: the cleanup gets its own layer, the diffs per PR stay small enough not to hurt my score, and the whole chain still goes out in one release.
Nobody's grading my portfolio site, and every layer there gets reviewed by an AI instead of my lead. I redid the whole thing out of a series of prompts and came out with five PRs that were all still too big, because at work I ask for a small chunk and on my own stuff I ask for "rewrite this."
Splitting them still earned its keep, and for exactly the reason GitHub gives: a smaller diff gets reviewed better. The diff doesn't care who's reading it, and handing an agent one layer instead of a whole feature leaves it less to review. I built a stack of reviewable layers to make AI more accurate, not me.
The One-Sentence Version π₯
gh stack does one thing, which is keep each diff small enough to get read properly. At work the reader is my lead and on my own projects it's an AI, and the tool doesn't care which β which is why it's worth running on a repo no other person will ever open.
So before the next agent session, write the layer list yourself and paste it in with the ask using the /gh-stack skill:
1. data model and migration
2. CRUD endpoints that use the model
3. auth middleware and guards
4. integration tests
π‘οΈ Is This Footer Really Required?
Claude read GitHub's entire stacked-PR documentation set so I wouldn't have to, then a second pass caught that the draft had accused those docs of hiding four things they say plainly. It wrote this footer immediately after, which I'm choosing to read as contrition.






Top comments (1)
Iβm curious how you modeled this feature ?