🪟 Windows TippsAxeos erhält ISO 9001:2015-Zertifizierung(17.09.2026 um 10:00 Uhr)
🤖 Android TippsAxeos erhält ISO 9001:2015-Zertifizierung(17.09.2026 um 10:00 Uhr)
🔧 ProgrammierungQ&D: Flutter App and Android-SDK(17.09.2026 um 10:00 Uhr)
🔧 ProgrammierungThe Code Worked. Then I Started Asking What Happens Next.(17.09.2026 um 10:00 Uhr)
🔧 ProgrammierungRegular Expressions Without the Fear(17.09.2026 um 10:00 Uhr)
🔧 AI Nachrichten Keep ChatGPT UI observations out of your API denominator(17.09.2026 um 10:01 Uhr)
🪟 Windows TippsAxeos erhält ISO 9001:2015-Zertifizierung(17.09.2026 um 10:00 Uhr)
🤖 Android TippsAxeos erhält ISO 9001:2015-Zertifizierung(17.09.2026 um 10:00 Uhr)
🔧 ProgrammierungQ&D: Flutter App and Android-SDK(17.09.2026 um 10:00 Uhr)
🔧 ProgrammierungThe Code Worked. Then I Started Asking What Happens Next.(17.09.2026 um 10:00 Uhr)
🔧 ProgrammierungRegular Expressions Without the Fear(17.09.2026 um 10:00 Uhr)
🔧 AI Nachrichten Keep ChatGPT UI observations out of your API denominator(17.09.2026 um 10:01 Uhr)
🔧 Programmierung 🕛 vor 1 Monat 11 Min Lesezeit
0

Github Stacked PR

↗ Quelle (dev.to)
🗣️ Stimme:
📑 Inhaltsübersicht




🎯 What a “Stacked PR” Is (and Why You’ll Want One)



A stacked pull request (sometimes called a stacked PR, stacked diff, or dependent PR) is a series of PRs that build on top of each other, each one containing a small, logically‑isolated change.




CODE
main ──► A ──► B ──► C
│ │ │
│ │ └─ PR‑C (depends on B)
│ └─ PR‑B (depends on A)
└─ PR‑A (directly on main)








  • A is based on main.


  • B is based on A (its head).


  • C is based on B, etc.



When you eventually merge the stack in order (A → B → C), each change lands cleanly, and reviewers can focus on one cohesive piece at a time.






Why Stack PRs?
































Problem Stacked PR Solution

Huge, monolithic PRs that are hard to review & cause long CI times
Break the work into bite‑size PRs (e.g., “feature flag”, “data model”, “UI”)

Inter‑dependent changes (e.g., a new API + its consumer)
Each dependent change lives in its own PR, but they still get tested together because they are built on top of each other

Rebasing on main constantly drags in unrelated changes
Only the bottom PR needs to be rebased onto main; the rest stay on top of it
Need to ship part of a larger change early Merge the first PR in the stack; the rest stay pending until they’re ready
CI resources Only the bottom PR runs the full suite against main; higher PRs can run a lighter subset because they already passed lower‑level tests








📦 The Landscape of Tools (as of 2026)




















Tool / Service Key Features Installation / Setup Typical Workflow

ghstack (GitHub CLI plugin)
- Creates stacked PRs automatically from a series of commits.
- Handles base‑branch updates, resolves merge conflicts, and can re‑stack after rebases.
- Works with GitHub's GraphQL API, so you get “dependent PR” links in the UI.

pip install ghstack (or brew install ghstack).
Requires a personal access token with repo scope.




bash git checkout -b feature/stacked\n# create many commits …\nghstack push\n# later, after rebasing on main\nghstack rebase



. |

| GitTown (aka git-town) | - git town ship can ship a stack of dependent branches in order.
- Not GitHub‑specific, works with any remote. | brew install git-town / cargo install git-town. |



bash git town new featureA\n# commit …\ngit town new featureB\n# work on B …\ngit town sync



|

| gstack (open‑source script) | - Very lightweight Bash script that creates a series of PRs from sequential commits.
- Good for CI‑only pipelines. | curl -L https://raw.githubusercontent.com/…/gstack.sh | bash. |



bash gstack create



. |

| GitHub’s “Draft PR” + “Depends on” labels | - No external tool needed; you manually create PRs and add a depends-on:<PR#> label (or a comment).
- GitHub UI now shows a “This PR depends on #123” banner (rolled out in early 2026). | No install. Just enable the “Pull request dependencies” preview in your org settings. | Create PR‑A → PR‑B → PR‑C, add depends-on: #A comment on B, etc. |

| pullrequest.io (SaaS) | - Managed service that visualises stacks, auto‑updates bases, and adds “stack‑status” checks.
- Works with public & private repos. | Sign up, link GitHub repo, generate a machine‑user token. | UI‑driven: select commits → “Create stack”. |

| Gerrit (if you’re on a hybrid workflow) | - Has native support for “dependent changes”.
- Works great if you already use Gerrit for code review. | Already part of Gerrit install. | Use git review -d <change-id> etc. |




Bottom‑line: If you just need a quick, “no‑install” solution, the built‑in draft‑PR + depends-on label works fine. If you want to automate the entire stack lifecycle (create, rebase, update, merge), ghstack is the most mature and GitHub‑native option in 2026.








🛠️ Step‑by‑Step Guide Using ghstack (the most popular choice)



Below is a complete workflow you can copy‑paste into a terminal. It assumes you have:




  • Git 2.40+ (or newer)

  • GitHub CLI (gh) installed and authenticated

  • Python 3.9+ (for ghstack)





1️⃣ Install the tools





CODE
# GitHub CLI (if you don’t have it)
brew install gh # macOS
# or: sudo apt install gh # Ubuntu

# ghstack (Python package)
pip install --user ghstack
# make sure ~/.local/bin is on your $PATH







2️⃣ Prepare a branch and make a series of commits





CODE
# Start from the latest main
git checkout main
git pull origin main

# Create a “stack” branch (the base of the stack)
git checkout -b feature/stacked

# 1️⃣ First logical change (e.g., add a new API)
# -------------------------------------------------
echo "def hello(): return 'world'" > hello.py
git add hello.py
git commit -m "feat: add hello() helper"

# 2️⃣ Second logical change that depends on the first
# -------------------------------------------------
cat >> hello.py <<'EOF'

def greet(name):
return f"Hello, {name}! " + hello()
EOF
git add hello.py
git commit -m "feat: add greet() that uses hello()"

# 3️⃣ Third logical change (e.g., tests)
# -------------------------------------------------
mkdir -p tests
cat > tests/test_hello.py <<'EOF'
import unittest
from hello import greet

class TestHello(unittest.TestCase):
def test_greet(self):
self.assertIn("Hello, Alice!", greet("Alice"))
EOF
git add tests/
git commit -m "test: add unit tests for greet()"





Now you have three commits that you want to turn into three stacked PRs.





3️⃣ Push the stack to GitHub





CODE
# ghstack will create a separate remote branch for every commit
ghstack push





What happens under the hood:
































Commit Remote branch created PR title (auto‑derived) Base branch
1️⃣ ghstack/1 feat: add hello() helper main
2️⃣ ghstack/2 feat: add greet() that uses hello() ghstack/1
3️⃣ ghstack/3 test: add unit tests for greet() ghstack/2


Each PR appears in GitHub with the “depends on #XYZ” banner (thanks to the new UI feature). The PR descriptions contain a tiny block:




CODE
--- ghstack metadata ---
base: ghstack/2
stack: [ghstack/1, ghstack/2, ghstack/3]
--- end ---









4️⃣ Review & Iterate




  • Reviewers see each PR separately.

  • CI runs on each branch; GH‑Actions can be configured to run only the diff against its base (fast) because the lower PR already passed the full suite.



If you need to amend the second commit:




CODE
git checkout ghstack/2   # switch to the branch created for commit #2
# Make change, amend commit
git commit --amend -m "feat: improve greet() implementation"
# Push the new version (ghstack takes care of the dependent PRs)
ghstack push






ghstack will automatically re‑stack all downstream PRs (3, 4, …) on top of the updated commit.






5️⃣ Rebase the whole stack onto a newer main



Suppose main has moved forward and you want to keep your stack up‑to‑date:




CODE
git checkout main
git pull # get latest
ghstack rebase






Result:





  • ghstack/1 is rebased onto the new main.


  • ghstack/2 and ghstack/3 are automatically rebased onto the new ghstack/1.

  • All open PRs get updated automatically – no manual git push -f gymnastics.






6️⃣ Merging the stack



When every PR is approved:




CODE
# Merge bottom‑most PR first (or let GitHub auto‑merge with “Require linear history”)
gh pr merge ghstack/1 --merge
gh pr merge ghstack/2 --merge
gh pr merge ghstack/3 --merge






Because each PR’s base is the previous PR, merging in order results in a perfectly linear history on main.


If you enable GitHub’s “auto‑merge when all checks pass” on each PR, the merges will happen automatically as soon as the lower PR merges.





7️⃣ Clean up





CODE
# Delete the temporary remote branches
ghstack delete-branches





You’re left with a clean main branch plus the series of logical commits merged in order.







📋 Alternative Workflows (No‑Tool, “Manual Stack”)



If you prefer not to install anything, you can still get a stacked workflow using plain Git:




CODE
# 1️⃣ Create the base branch (on main)
git checkout -b feature/a main
# commit A … push and open PR‑A

# 2️⃣ Create B *on top of* A
git checkout -b feature/b feature/a
# commit B … push and open PR‑B
# In PR‑B comment: “Depends on #PR-A”

# 3️⃣ Create C on top of B
git checkout -b feature/c feature/b
# commit C … push and open PR‑C
# Comment: “Depends on #PR-B”






Key manual steps to remember:
























Action How to do it manually
Keep the base up‑to‑date
git fetch origin && git rebase origin/main on the bottom branch, then git checkout feature/b && git rebase feature/a, etc.
Close a PR when you want to drop a change Delete the branch (git push origin --delete feature/b) and remove the dependent PRs (or git rebase them onto the new base).
Show the dependency in GitHub UI Add a comment Depends on #123 (GitHub renders a banner). You can also add a label depends-on:123.


Pros: No extra tooling, works everywhere.


Cons: You have to re‑base manually, risk of diverging PR bases, and you won’t get the nice “re‑stack” automation that ghstack offers.







🧩 Integrating Stacked PRs with CI/CD





1️⃣ Split CI Jobs





  • Full‑suite job runs on the bottom PR (the one that targets main).


  • Incremental job runs on higher PRs, using git diff against its base to only test the new changes.



GitHub Actions example (.github/workflows/ci.yml):




CODE
name: CI

on:
pull_request:
types: [opened, synchronize, reopened]

jobs:
test:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0 # needed for diffing

- name: Find base commit
id: base
run: |
# GH provides GITHUB_BASE_REF (the branch PR is based on)
echo "base=$(git merge-base HEAD origin/${{ github.base_ref }})" >> $GITHUB_OUTPUT

- name: Run incremental tests
run: |
# Example with pytest: run only changed files
git diff --name-only ${{ steps.base.outputs.base }} | grep '\.py$' | xargs -r pytest






Higher PRs get a quick feedback loop; the bottom PR still validates the full integration test suite.






2️⃣ Guardrails (Branch Protection)





  • Require “dependents merged first”: In your repo’s Branch protection rules enable the optional “Require status checks to pass before merging” and add a custom check that verifies “All dependent PRs are merged”.


  • Enforce linear history: Turn on “Require linear history”—this guarantees that merges happen in order and never create merge commits that would break the stack.









📚 Best‑Practice Checklist































































Practice Why it matters
1️⃣
One logical change per PR (e.g., “add API”, “add consumer”, “add tests”)
Keeps review size small and makes stacking natural.
2️⃣
Name branches feature/stack‑N‑<description> (or let ghstack generate them).
Makes it obvious which branch belongs to which stack level.
3️⃣
Keep the bottom PR always rebased onto main.
Guarantees that merging the stack never introduces merge conflicts.
4️⃣
Add explicit “Depends on #XYZ” comments or labels (if you’re not using ghstack).
Human reviewers and bots can see the order at a glance.
5️⃣
Enable GitHub’s “Pull request dependencies” preview (Org → Settings → Features).
Gives the UI banner and a built‑in dependency graph.
6️⃣
Run incremental CI on top‑of‑stack PRs.
Faster feedback for downstream changes.
7️⃣
Never force‑push the bottom PR without re‑stacking downstream.
If you do, downstream PRs will diverge and CI will fail.
8️⃣
When a stack is ready to ship, merge bottom‑up (or enable auto‑merge with “Merge when the head branch is up‑to‑date”).
Guarantees linear history and avoids “merge commit” noise.
9️⃣
Delete temporary ghstack/* branches after the stack lands.
Keeps the repo tidy and avoids accidental pushes.
🔟
Document the stack in the PR description (e.g., “Stack: #12 → #13 → #14”).
Future maintainers know the intent and can locate related changes quickly.








📦 Example: Real‑World Scenario (Feature Flag Rollout)



Suppose you need to:




  1. Add a feature flag in the config library.

  2. Guard a new endpoint behind that flag.

  3. Add integration tests for the endpoint.

  4. Deploy a monitoring dashboard.



You can create four stacked PRs:






































PR Description Branch (ghstack) Base
#101 feat: add “new‑feature” flag ghstack/1 main
#102 feat: new endpoint (guarded by flag) ghstack/2 ghstack/1
#103 test: integration tests for new endpoint ghstack/3 ghstack/2
#104 chore: dashboard for new feature ghstack/4 ghstack/3


Team workflow:





  • Day 1: Open PR #101, get flag reviewed.


  • Day 2: Merge #101, rebase the rest automatically (ghstack rebase).


  • Day 3: Open #102, review the endpoint.


  • Day 4: Merge #102 → #103 now runs against the updated code.


  • Day 5: Merge #103 → #104, then ship the whole stack in one go if you want the dashboard to go live only after tests pass.



If a stakeholder decides to skip the dashboard for now, you simply close #104—no need to rewrite history.









🔧 Quick Reference Cheat Sheet












































Command What it does
ghstack push Creates a remote branch for each local commit and opens a PR for each.
ghstack rebase Rebases the entire stack onto the current main (or any other base you specify).
ghstack status Shows the current stack layout (base → ... → HEAD).
ghstack delete-branches Deletes the temporary ghstack/* branches after the stack is merged.
git checkout -b feature/X <base> Manual way to start a new stacked branch off <base>.
git rebase <new-base> Rebase the bottom branch onto a newer base; then re‑base the children manually (git checkout B && git rebase A).
gh pr merge <num> --merge Merge a specific PR (use --squash or --rebase if you prefer those strategies).
`gh pr comment --body "Depends on
Vollständiger Original-Artikel
Den kompletten Beitrag mit allen Details direkt auf dev.to lesen.
↗ Original-Artikel auf dev.to lesen
Wie bewertest du diesen Beitrag?
1 Klick Feedback
Teilen mit Netzwerk & Team:

Community-Analysen & Experten-Meinungen 0

Verfasse deine eigene Analyse, teile Workarounds oder diskutiere diesen Vorfall im Blog.
Noch keine Community-Analyse verfasst. Markiere einen Textabschnitt oder klicke oben auf Eigene Analyse verfassen“!
Community Pulse: Relevanz-Einschätzung
1 Klick Experten-Votum
🔴 Akute Relevanz 0%
🟡 In Evaluierung 0%
🟢 Keine Auswirkung 0%
Spannende Innovation 0%
Verwandte Story-Cluster & Quellen (Vektor-KI)
Port 8095 Engine
2 Quellen
Axeos erhält ISO 9001:2015-Zertifizierung
1 Quelle
Amazon bietet Soundcore-In-Ears zum ersten Mal günstiger an: Mit ANC, Dolby Atmos & mehr Highlights
1 Quelle
Höllenmaschine HMX 6 im Halo-Design – passend zum Spiele-Release!