View as Markdown

Mergify Stacks vs Plain Git

An honest comparison of Mergify Stacks and stacking by hand with git rebase and gh pr create.


You don’t need a tool to stack pull requests. Git already lets you split work into a chain of commits, and gh pr create opens a PR for each one. Plenty of teams run a small shell wrapper around exactly that. This page is an honest look at what you give up, and what you get back, by letting Stacks manage the chain instead of doing it by hand.

The manual recipe is straightforward, at least at first. You create a branch per change, rebase each branch onto the one below it, push them all, and open a PR for each with the right base:

Terminal window
git checkout -b feat/model main
# work, commit
git checkout -b feat/endpoint feat/model
# work, commit
git checkout -b feat/tests feat/endpoint
# work, commit
git push -u origin feat/model feat/endpoint feat/tests
gh pr create --base main --head feat/model
gh pr create --base feat/model --head feat/endpoint
gh pr create --base feat/endpoint --head feat/tests

It works. The cost shows up later, every time the stack changes. Amend the bottom commit and you re-push three branches by hand. Reorder two changes and you rebase each dependent branch in turn. When the bottom PR merges, you re-target the next PR to main yourself and clean up the merged branch. Each of these is a few commands, and each is easy to get subtly wrong.

Stacks keeps you on a single branch of ordinary commits. There are no per-PR branches to create, name, or rebase:

You work on a single branch. Each commit maps to a PR automatically:

feat/auth A B C PR #1 base: main PR #2 base: PR #1 PR #3 base: PR #2

Under the hood, mergify stack push creates a remote branch per commit and chains the PRs:

Local CommitsRemote BranchesGitHub PRs A: add model stack/.../add-model--a1b2c3d4 PR #1 B: add endpoint stack/.../add-endpoint--d4e5f6a7 PR #2 C: add tests stack/.../add-tests--b7c8d9e0 PR #3

You never see or manage these remote branches. They're an implementation detail.

A Change-Id trailer (added by a commit-msg hook) ties each commit to its PR, so the mapping survives amends, rebases, and reorders. mergify stack push rebases on the target branch, pushes a remote branch per commit, opens or updates one PR each, and chains them in dependency order, in one command.

TaskPlain Git + ghMergify Stacks
ModelOne branch per PR, rebased in a treeOne branch, many commits
Map commit to PRYou track which branch is which PRChange-Id trailer, automatic
Open PRsgh pr create per branch, set each baseIncluded in mergify stack push
Amend mid-stackRebase every dependent branch, re-push eachmergify stack edit <commit>, then push
ReorderManual git rebase -i across branchesmergify stack reorder / mergify stack move
Squash / dropgit rebase -i, then re-push affected branchesmergify stack squash / fixup / drop
Push only what changedYou decide which branches to pushSmart updates: only changed PRs are touched
After a mergeRe-target next PR, delete merged branchmergify stack sync detects and drops merged commits
Re-targeting on mergeManual base change per PRAutomatic when the bottom PR lands
Stack overview on the PRNone (or hand-written)Stack comment + revision history on every PR
Merge QueuePer-PR, no stack awarenessStack-aware queueing

Stacks earns its keep on changes that span several commits and get reworked during review. If that’s not your situation, the manual path is fine, and honestly simpler:

  • Your changes are already small. A one-commit fix is one PR. There’s nothing to stack, so gh pr create is all you need.

  • You rarely reorder or amend mid-stack. The manual cost is in reworking a chain. If you push once and merge, you never pay it.

  • You only stack occasionally. For a one-off pair of dependent PRs, three gh commands beat installing a tool.

Stacks doesn’t change this calculus by force. Even with the CLI installed, a single small commit is still a single small PR.

The chain maintains itself. Most of the work is keeping a stack correct through review, not creating it. Smart updates push only the PRs whose commits changed, re-targeting happens automatically as PRs merge, and mergify stack sync drops already-merged commits and rebases the rest. By hand, each of those is a manual step you can forget.

Identity survives history rewrites. Because the Change-Id lives in the commit message, amending or reordering a commit keeps it mapped to the same PR. A hand-rolled script keyed on branch names loses that mapping the moment you rebase, which is why homegrown wrappers tend to recreate PRs or orphan branches.

Reviewers get context for free. Every PR carries a stack comment and a revision-history timeline showing where it sits in the chain and what changed between pushes. A custom script would have to generate and maintain that itself.

Stack comment showing a PR's position in the chain

Merge Queue integration. Stacks are queued as a unit: @mergifyio queue on the top PR enqueues the whole chain bottom-up, and a failure cascades cleanly to the rest. See Stacked PRs in the Merge Queue.

If you already wrap git rebase and gh pr create, you don’t have to throw anything away. Stacks runs on the same Git primitives, so you can adopt it incrementally:

Terminal window
uv tool install mergify-cli
mergify stack setup

Setup installs the commit-msg hook that adds Change-Ids and a pre-push hook that nudges you toward mergify stack push. From there:

  • Existing commits without Change-Ids get one when you reword them: run git rebase -i <base>, mark each commit reword, and the hook fills in the trailer on save.

  • Re-runs are safe. mergify stack push compares each commit’s Change-Id and SHA against GitHub and only touches what changed, so running it twice does no extra work.

  • There’s an off-ramp. On GitHub, Stacks creates ordinary branches and PRs, plus the stack and revision-history comments it posts on each PR. None of it is a proprietary format. The only local artifact is the Change-Id: trailer in your commit messages. Stop using the CLI and your history is still clean, standard Git; the trailer is just an inert line of text.

Terminal window
uv tool install mergify-cli
mergify stack setup
mergify stack push

See the setup guide for the full walkthrough, or Creating Stacks to push your first stack.

Was this page helpful?