So funktionieren gestapelte Pull Requests auf GitHub
Erfahren Sie, wie gestapelte Pull Requests auf GitHub funktionieren: Stacks mit gh-stack erstellen, Ebenen prüfen, Änderungen rebasen und abhängige PRs mergen.
Gestapelte Pull Requests (Stacked Pull Requests) auf GitHub teilen eine große Änderung in eine geordnete Kette kleiner Pull Requests auf: Jeder Pull Request zielt auf den Branch des darunterliegenden Pull Requests, und GitHub behandelt die gesamte Kette beim Review, Rebase und Merge als eine Einheit.
Die Alternative kennen die meisten Teams. Sie entwickeln ein Feature in drei voneinander abhängigen Teilen und öffnen drei PRs. Der zweite PR zeigt dann sowohl die eigenen Änderungen als auch die des ersten. Reviewer geben auf, oder Sie packen alles in einen riesigen PR, den niemand gründlich liest.
Dieser Artikel erklärt, wie die nativen Stacks von GitHub von Anfang bis Ende funktionieren: wie Sie einen Stack anlegen, wie das Review abläuft, was passiert, wenn sich ein PR in der Mitte des Stacks ändert, und was die einzelnen Merge-Optionen bewirken. Wenn Sie zunächst Ihr Wissen über gewöhnliche PRs auffrischen möchten, lesen Sie wie Sie Pull Requests im Terminal erstellen.
Das Wichtigste in Kürze
- In einem GitHub-Stack ist die Basis jedes Pull Requests der Branch des darunterliegenden PRs. Jeder Diff enthält daher nur die Änderungen der jeweiligen Ebene.
- GitHub hat gestapelte Pull Requests am 30. Juli 2026 als Public Preview angekündigt. Das Feature kann sich noch ändern.
- Laut GitHubs Quickstart benötigt die CLI-Erweiterung gh-stack GitHub CLI 2.90.0 oder neuer sowie Git 2.20 oder neuer.
- Ändert sich eine mittlere Ebene, verweisen alle darüberliegenden Branches auf einen veralteten Commit. Diese Branches müssen von unten nach oben rebased und per Force-Push aktualisiert werden.
- Wird der oberste mergebereite PR gemergt, landen er und alle darunterliegenden, noch nicht gemergten PRs in einem einzigen Merge. Schlägt der Merge zwischendurch fehl, bleiben bereits gemergte PRs gemergt und die übrigen geöffnet. Jeder PR wird anhand der Regeln des Basis-Branches des Stacks geprüft.
Das Problem mit abhängigen Pull Requests
Abhängige Pull Requests scheitern im Review, weil GitHub jeden PR mit seinem Basis-Branch vergleicht. Angenommen, Sie öffnen drei PRs, die alle auf main zielen: zuerst auth-middleware, dann api-routes, dann ui-login. Der Diff des zweiten PRs enthält zusätzlich den gesamten Middleware-Code, der dritte enthält alles. Niemand kann erkennen, welche Zeilen ein bestimmter PR tatsächlich einführt.
Ohne native Stacks behelfen sich Entwickler meist auf eine von zwei Arten. Entweder fassen sie alles in einem großen PR zusammen, was das Review verlangsamt und Fehler verschleiert. Oder sie richten jeden PR manuell auf den darunterliegenden Branch aus und müssen die gesamte Kette bei jeder Änderung selbst rebasen und neu ausrichten.
Was sind gestapelte PRs auf GitHub?
Ein gestapelter Pull Request auf GitHub ist ein Glied in einer geordneten Kette. Jeder PR verwendet den Branch des darunterliegenden PRs als Basis, sodass sein Diff nur die Änderungen dieser Ebene zeigt. Wie GitHubs Überblick über gestapelte Pull Requests erläutert, zielt der unterste PR auf den Trunk des Stacks. Das ist in der Regel main, kann aber jeder beliebige Branch sein, etwa ein Release-Branch. Alle Branches eines Stacks müssen im selben Repository liegen, Stacks können sich also nicht über Forks erstrecken.
So sieht das Beispiel mit drei Ebenen als Stack aus:
main
└─ auth-middleware PR → main (diff: middleware only)
└─ api-routes PR → auth-middleware (diff: routes only)
└─ ui-login PR → api-routes (diff: login UI only)
Das Modell beruht weiterhin auf Branches und Basen, die Git bereits kennt. GitHub ergänzt das Tracking: Es kennt die Reihenfolge der PRs, verknüpft sie miteinander und behandelt sie als Gruppe.
Einen Stack mit der gh CLI erstellen
Mit der Erweiterung gh-stack erstellen und verwalten Sie Stacks im Terminal. GitHubs Quickstart nennt GitHub CLI 2.90.0 oder neuer und Git 2.20 oder neuer als Voraussetzungen. Die CLI-Befehlsreferenz und die README der Erweiterung geben mit gh 2.0 eine niedrigere Mindestversion an. Die Angabe aus dem Quickstart ist daher die sicherere Wahl. Außerdem müssen Sie authentifiziert sein und Push-Zugriff auf das Repository haben. Falls Sie gh noch nicht kennen, beginnen Sie mit Pull Requests im Terminal erstellen.
gh --version # 2.90.0 or later
git --version # 2.20 or later
gh auth login
gh extension install github/gh-stack
Bauen Sie den Stack anschließend Ebene für Ebene auf:
gh stack init # prompts for the first branch name, e.g. auth-middleware
git add -A
git commit -m "Auth middleware"
gh stack add api-routes
git add -A
git commit -m "API routes"
gh stack add ui-login
git add -A
git commit -m "Login UI"
gh stack push # pushes branches only
gh stack submit # opens PRs with correct bases and links them
gh stack view # branches, PR links, statuses, latest commits
gh stack init richtet das lokale Tracking für den Stack ein und legt den ersten Branch an. Sofern Sie nicht --base angeben, ist der Trunk der Default-Branch des Repositorys. Die CLI-Befehlsreferenz weist darauf hin, dass push nur Branches hochlädt und Pull Requests nie verändert. Erst submit öffnet die PRs, weist jedem den richtigen Basis-Branch zu und fügt sie zu einem Stack zusammen.
Alternativ können Sie die Weboberfläche verwenden. Auf github.com erstellen Sie einen Stack, indem Sie einen PR öffnen, dessen Basis der Branch eines früheren PRs ist, und Create stack auswählen. Um einen bestehenden Stack zu erweitern, öffnen Sie einen beliebigen PR darin und wählen im Header Add to stack. Bilden Ihre offenen PRs bereits eine Kette, blendet GitHub ein Banner ein, über das Sie sie in einen Stack umwandeln können. Stacks lassen sich auch in der mobilen GitHub-App und von Coding Agents wie Copilot über den gh-stack-Skill nutzen. GitHub Desktop unterstützt sie nicht.
Einen Stack Ebene für Ebene reviewen
Reviewer können jede Ebene eines Stacks einzeln freigeben. Verschiedene Reviewer können gleichzeitig an verschiedenen Ebenen arbeiten, während der Autor weiter darauf aufbaut. Der Hauptvorteil gestapelter Pull Requests: Das Review findet auf kleinen Diffs statt, und das Feature muss nicht vollständig fertig sein, bevor das Review beginnen kann.
Wenn Sie einen beliebigen PR im Stack öffnen, sehen Sie nur den Diff dieser Ebene. Die Merge-Box enthält eine Stack-Übersicht, die jeden PR der Kette mit seinem Status auflistet. Die Zahl am Stack-Symbol oben auf der Seite zeigt, welche Ebene gerade geöffnet ist.
Kleine Ebenen hinterlassen außerdem eine aussagekräftigere Historie auf main. Jeder eingehende Commit ist fokussiert, sodass eine git bisect-Sitzung auf eine konkrete Änderung zeigen kann statt auf einen Merge mit tausend Zeilen.
Einen PR in der Mitte des Stacks aktualisieren
Landet ein neuer Commit auf einem Branch in der Mitte eines Stacks, verweisen alle darüberliegenden Branches weiterhin auf den alten Commit. Diese oberen Branches müssen auf die aktualisierte Ebene rebased und per Force-Push hochgeladen werden. Im Beispiel lässt ein Review-Fix auf api-routes den Branch ui-login zurück. auth-middleware ist davon nicht betroffen.
Bei einer manuell verwalteten Kette erledigen Sie das selbst mit reinem Git (Grundlagen zum Rebasing finden Sie in 10 Git-Befehle):
# plain Git, no gh-stack
git checkout ui-login
git rebase api-routes # resolve any conflicts
git push --force-with-lease
# repeat for every branch above, bottom to top
Mit gh-stack reduziert sich das laut dem Tutorial zum Stapeln von Codeänderungen auf zwei Befehle:
gh stack checkout api-routes
git add -A
git commit -m "Fix API routes"
gh stack rebase --upstack # rebases only the branches above api-routes
gh stack push # per-branch --force-with-lease
Hält der Rebase bei einem Konflikt an, beheben Sie die betroffenen Dateien, fügen sie mit git add hinzu und führen gh stack rebase --continue aus. Wenn Sie abbrechen möchten, setzt gh stack rebase --abort alle Branches auf den Stand vor dem Rebase zurück.
Auf github.com erscheint in der Merge-Box die Schaltfläche Rebase stack, sobald der Stack nicht mehr linear ist. Laut dem Leitfaden zur Verwaltung gestapelter Pull Requests spielt ein Klick darauf die Branches von unten beginnend auf den neuesten Trunk ein und führt für jeden einen Force-Push aus. Auf diese Weise auf GitHubs Servern erzeugte Commits sind nicht signiert. In Repositorys, die signierte Commits verlangen, sollten Sie daher stattdessen lokal mit gh stack rebase rebasen.
Rebasing schreibt die oberen Branches um. Hat ein Teammitglied einen dieser Branches ausgecheckt, sollte es innehalten und sich mit dem Remote synchronisieren, bevor es weitere Commits erstellt. Andernfalls kollidiert sein nächster Push mit der umgeschriebenen Historie.
Einen Stack mergen
Wird der oberste mergebereite Pull Request gemergt, landet er zusammen mit allen darunterliegenden, noch nicht gemergten PRs in einem einzigen Merge. Schlägt dabei etwas fehl, etwa durch einen unerwarteten Konflikt, stoppt der Merge an diesem PR: Die bereits gemergten PRs darunter bleiben auf dem Basis-Branch, der fehlgeschlagene PR und alle darüberliegenden bleiben geöffnet. Mergen Sie nur die unteren Ebenen, bleiben die darüberliegenden PRs geöffnet, während GitHub sie rebased und ihre Basis auf den Basis-Branch des Stacks umstellt. Laut dem Merge-Leitfaden muss der Stack eine lineare Historie haben, bevor irgendein Teil davon gemergt werden kann.
| Sie mergen | Was auf main landet | Was mit dem Rest geschieht |
|---|---|---|
Obersten mergebereiten PR (ui-login) | Alle drei PRs | Nichts bleibt offen |
Untersten PR (auth-middleware) | Nur diesen PR | Obere PRs werden rebased und auf main umgestellt |
Mittleren PR (api-routes) | Diesen PR plus alle darunterliegenden PRs | ui-login bleibt offen und wird auf main umgestellt |
Ein PR in der Mitte eines GitHub-Stacks kann nicht einzeln gemergt werden. Er landet immer zusammen mit den darunterliegenden PRs. Laut GitHubs Referenz zu gestapelten Pull Requests funktionieren Stacks mit Merge-Commits, Squash und Rebase. Beim Squash wird jeder PR zu einem eigenen Squash-Commit, sodass das Mergen von drei PRs drei Commits auf main erzeugt.
Die Merge-Regeln stammen vom Basis-Branch des Stacks, nicht von dem Branch, auf den der jeweilige PR direkt zielt. Branch Protections und Required Checks entscheiden daher weiterhin, was auf main gelangt. Stacks funktionieren auch mit Merge Queues, die die PRs in der richtigen Reihenfolge erhalten. Laut Changelog vom 30. Juli 2026 sollte die Unterstützung für Merge Queues schrittweise ausgerollt werden; GitHubs Merge-Leitfaden beschreibt Merge Queues inzwischen als vollständig unterstützt.
Stacking vor der nativen Unterstützung
Bevor GitHub Stacks nativ unterstützte, benötigten Sie ein separates Tool, um die Branch-Kette zu verwalten. Graphite, spr und git-branchless übernahmen die Verwaltung jeweils außerhalb von GitHubs eigenem Pull-Request-Modell.
Die nativen gestapelten Pull Requests von GitHub arbeiten mit Ihren bestehenden Reviews, Required Checks und Branch Protections zusammen, sodass das Team kein zusätzliches Tool einführen muss. Für Teams, die nur auf Stacking-Tools umgestiegen sind, um unlesbare abhängige PRs zu umgehen, entfällt damit der Hauptgrund für deren Einsatz.
Fazit
Ein GitHub-Stack ist eine Kette von Pull Requests, in der jeder den darunterliegenden Branch als Basis verwendet, während GitHub Rebasing, Neuausrichtung und Merging übernimmt. Da jede Ebene klein ist, können Reviewer sie gründlich lesen, und eine Änderung in der Mitte des Stacks erfordert nur das Rebasing der darüberliegenden Branches. Zum Ausprobieren installieren Sie github/gh-stack und teilen Ihr nächstes mehrteiliges Feature in drei Ebenen auf.
FAQs
Funktioniert Auto-Merge mit gestapelten Pull Requests auf GitHub?
Nein. Laut GitHubs Merge-Dokumentation wird Auto-Merge für gestapelte Pull Requests nicht unterstützt. Tools, die über die API mergen, benötigen für Stacks die asynchrone Merge-API, da die älteren Merge-Endpunkte für Pull Requests keinen Stack mergen können. Um einen Stack automatisch zu mergen, sobald die Checks bestanden sind, verwenden Sie stattdessen eine Merge Queue: Stacks unterstützen Merge Queues, und die Queue übernimmt die PRs in Stack-Reihenfolge.
Was passiert, wenn ein gestapelter Pull Request aus einer Merge Queue entfernt wird?
Alle darüberliegenden Pull Requests im Stack verlassen die Queue ebenfalls. Damit ein Stack zusammenbleibt, erlaubt die Merge Queue, dass eine Merge-Gruppe ihre konfigurierte Maximalgröße um bis zu 50 Prozent überschreitet. Ist ein Stack selbst dafür zu groß, verteilt GitHub ihn auf mehrere aufeinanderfolgende Merge-Gruppen.
Wie aktualisiere ich meinen lokalen Stack, nachdem der unterste Pull Request gemergt wurde?
Führen Sie gh stack sync aus. Der Befehl holt in einem Schritt die neuesten Änderungen, schiebt den Trunk nach vorn, rebased die verbleibenden Branches darauf, pusht sie und aktualisiert den Status jedes Pull Requests. Mit --prune löschen Sie lokale Branches gemergter Pull Requests. Stößt sync auf einen Konflikt, setzt es alle Branches in ihren vorherigen Zustand zurück. Lösen Sie den Konflikt dann mit gh stack rebase und führen Sie anschließend gh stack push aus.
Wie kann ich Ebenen in einem bestehenden Stack neu anordnen, entfernen oder umbenennen?
Verwenden Sie gh stack modify, eine interaktive Terminal-Oberfläche, mit der Sie Branches entfernen, zusammenfalten, einfügen, neu anordnen und umbenennen können. Voraussetzung sind ein sauberer Working Tree, eine lineare Historie, kein laufender Rebase und kein Pull Request in der Merge-Warteschlange. Branches neu anordnen und sie gleichzeitig entfernen, zusammenfalten, einfügen oder umbenennen ist in derselben Sitzung nicht möglich. Ihre Änderungen werden erst beim Speichern übernommen, und gh stack modify --abort stellt den Stack im Ausgangszustand wieder her. Führen Sie danach gh stack submit aus, um GitHub zu aktualisieren.