PRs triagieren (priorisieren und bearbeiten)
Ziel
In einer einzigen fokussierten Sitzung einen Rückstand offener Pull Requests in eine ausgelieferte Menge von Merges umwandeln. Erstelle einen nachverfolgbaren, fortsetzbaren Plan (<VERSION>_PR_TRIAGE.md) und arbeite ihn ab – rebase wo nötig, merge in isolierten, sicheren Batches, führe Follow-ups nach dem Merge durch und schließe supersedierte (überholte) oder nur teilweise anwendbare PRs unter Nennung der Autoren.
Dieser Skill arbeitet mit draft-release-notes und release-bump zusammen: Zuerst triagieren, dann die Entwurfsnotizen gegen den neuen Hauptbranch erstellen, dann den Release durchführen.
Wann verwenden
- Vor einem Minor- oder Major-Release, wenn sich 10+ offene PRs angesammelt haben.
- Wenn du das Mergen voranbringen möchtest, ohne den Überblick darüber zu verlieren, was landet.
- Wenn du weißt, dass du nicht jeden PR im Detail reviewen kannst, aber die kritischen Änderungen schnell landen müssen.
Voraussetzungen
ghCLI ist gegen das Repository authentifiziert.- Ein dedizierter Worktree für das PR-Review (vermeidet die Kontamination von
mainmit Checkouts von Beitragsbranchen). - Klarheit über die Zielversion – das Triage-Dokument wird nach ihr benannt (z. B.
0.4.0_PR_TRIAGE.md).
Arbeitsablauf
1. Richte einen isolierten Worktree für das PR-Review ein
git worktree list # zuerst nach veralteten suchen
git worktree prune
git worktree add ../voicebox-pr-review -b pr-review-<VERSION> main
Behalte den Haupt-Worktree für Release-Vorbereitungen (Changelog-Entwürfe, direkte Follow-ups auf main). Nutze den Review-Worktree für gh pr checkout – jeder Checkout bewegt HEAD auf einen Beitragsbranch, was du im Haupt-Worktree nicht tun möchtest.
2. Sammle Metadaten für jeden offenen PR
gh pr list --state open --limit 50 --json \
number,title,author,isDraft,mergeable,mergeStateStatus,files,additions,deletions,reviewDecision,statusCheckRollup,maintainerCanModify \
--jq '.[] | {num: .number, title, author: .author.login, mergeable, state: .mergeStateStatus, canModify: .maintainerCanModify, changes: "+\(.additions)/-\(.deletions)", files: [.files[].path]}'
Du benötigst für jeden PR:
- Größe (
+Additions/-Deletions) - Merge-Status (
CLEAN,UNSTABLE,DIRTY= Konflikte,UNKNOWN= GitHub berechnet noch) - Ob Maintainer-Änderungen am Branch erlaubt sind (später benötigt, wenn du für den Autor rebasieren möchtest)
- Berührte Dateipfade (hilft, Überschneidungen zwischen PRs zu erkennen)
UNKNOWN ist häufig direkt nach einem Push auf main – versuche einfach den Merge und schau, was passiert.
3. Klassifiziere in Stufen
Sortiere jeden PR in genau einen Eimer:
Stufe 1 – Merge: Klein, mergebar, behebt einen echten Fehler, saubere CI, niedrige Review-Kosten. Einzeiler, Lockerungen von Abhängigkeiten, gezielte Sicherheitshärtungen. Das sind die einfachen Erfolge.
Stufe 2 – Kandidat, Review: Mittlere Größe (50-200 Zeilen), betrifft mehr Oberfläche, sieht solide aus, braucht aber eine genauere Prüfung. Neue benutzerorientierte Funktionen, die zur Produktrichtung passen.
Supersediert (überholt): Der Fehler oder die Funktion wird bereits durch einen gemergten PR abgedeckt. Schließe mit einem Kommentar, der auf den supersedierenden PR verweist. Prüfe sorgfältig – „ähnlicher Titel“ ist kein Beweis; vergleiche die tatsächlichen Diffs.
Auf nächsten Release verschieben: Große Features, dreckige Konflikte, Entwurfs-PRs, alles, was die Release-Pipeline auf eine Weise berührt, die Risiken einführen würde. Merge diese nicht in einem Speedrun – sie brauchen fokussierte Aufmerksamkeit.
4. Schreibe das Triage-Dokument
Erstelle <VERSION>_PR_TRIAGE.md im Wurzelverzeichnis des PR-Review-Worktrees. Struktur:
# <Repo> <VERSION> – PR Triage
Arbeitsdokument zur Verfolgung, welche offenen PRs in <VERSION> landen. Nach dem Release löschen.
Zuletzt aktualisiert: <DATUM>
## Fortschritt
**Stufe 1: 0 / N gemergt**
**Stufe 2: 0 / M bearbeitet**
**Supersede-Triage: ausstehend**
---
## Merge für <VERSION> – kritische Fehlerbehebungen
| PR | Status | Größe | Was wird behoben | Warum unverzichtbar |
|---|---|---|---|---|
| [#123](url) | [ ] | +5/-0 | ... | ... |
## Starker Kandidat – braucht einen schnellen Review
| PR | Status | Größe | Zusammenfassung |
|---|---|---|---|
## Schließen als supersediert
| PR | Status | Grund |
|---|---|---|
## Auf <NÄCHSTE_VERSION> verschieben
- [#xxx](url) ... – Grund
---
## Angriffsreihenfolge
1. Schließe supersedierte PRs (Einzeiler-Kommentare)
2. Merge Stufe 1 in abhängigkeitsfreien Batches – prüfe, dass sich Dateipfade nicht überschneiden
3. Review Stufe 2 einzeln
4. Führe `draft-release-notes` erneut aus, um alles zu erfassen
5. Führe `release-bump` aus
Der Fortschritt-Header ist der wichtigste Teil – er ist deine Anzeigetafel und ermöglicht eine saubere Fortsetzung, falls die Sitzung unterbrochen wird.
5. Arbeite den Kreislauf ab – pro PR
Gehe für jeden PR in der Stufe-1-/Stufe-2-Liste wie folgt vor:
a. Checkout im Review-Worktree:
cd ../voicebox-pr-review
git checkout pr-review-<VERSION> # zurück auf neutrale Basis setzen
git pr checkout <N>
b. Lies den tatsächlichen Commit, nicht main..HEAD:
git show HEAD # die tatsächlichen Änderungen des PRs
git show --stat HEAD # berührte Dateien + Zeilenanzahl
Reviewe NICHT über git diff main..HEAD, wenn der PR-Branch älter als main ist. Dieser Diff enthält jeden Commit, der nach der Abspaltung des PRs auf main gelandet ist als - (Löschungs-) Zeilen. Ein 3-Zeilen-PR kann wie ein 700-Zeilen-Revert aussehen. Dies ist der einfachste Weg, einen PR falsch einzuschätzen.
c. Bewerte Bedenken: Korrektheit, Umfang, Interaktion mit bereits gemergter Arbeit, Versionskompatibilität (z. B. kann keine API verwendet werden, die eine Abhängigkeitsversion erfordert, die wir noch nicht festgelegt haben).
d. Rebase den Branch, wenn er hinter main zurück ist:
git fetch origin main
git rebase origin/main
Dies ist wesentlich vor einem Squash-Merge. GitHub's Squash berechnet diff(PR-Kopf, Merge-Basis) – auf einem veralteten Branch enthält dieser Diff das Rückgängigmachen jedes dazwischenliegenden Commits. Ein Rebase verschiebt die Merge-Basis nach vorne, sodass der Squash sauber ist.
e. Wenn Maintainer-Änderungen erlaubt sind, pushe den Rebase zurück zum Fork des Contributors:
git remote add <autor> https://github.com/<autor>/<repo>.git
git fetch <autor> <branch> # zuerst ihre Referenz holen
git push <autor> HEAD:<branch> --force-with-lease
Dies hält die GitHub-PR-Oberfläche mit dem rebasierten Zustand synchron und macht den Merge von der GitHub-Seite sauber.
f. Merge:
git pr merge <N> --squash
g. Aktualisiere das Triage-Dokument – setze das Kontrollkästchen auf ✅ merged <sha> (verwende die kurze SHA aus gh pr view <N> --json mergeCommit --jq '.mergeCommit.oid[0:7]'). Aktualisiere den Fortschritt-Header.
6. Batch-weise kleine Fehlerbehebungen
PRs mit ≤5 Zeilen Änderung, sauberer CI, nicht überlappenden Dateipfaden und offensichtlich korrekter Absicht (z. B. Einzeiler-Lockerung einer Abhängigkeit, Hinzufügen einer Umgebungsvariable, Korrektur eines Importpfads) können in einer einzigen Schleife ohne das Review-pro-PR-Zeremoniell gemergt werden:
for pr in 425 384 416 429; do
echo "=== Merge PR $pr ==="
gh pr merge $pr --squash
done
Überprüfe anschließend, dass jeder sauber gelandet ist:
for pr in 425 384 416 429; do
gh pr view $pr --json state,mergeCommit --jq "{pr: $pr, state, sha: .mergeCommit.oid[0:7]}"
done
7. Follow-ups nach dem Merge
Manchmal lohnt es sich, einen PR zu mergen, obwohl ein bekanntes kleines Problem besteht (z. B. unvollständige dtype-Zuordnung, veraltete Sentinel-Bereinigung). Blockiere den Merge nicht; wende das Follow-up direkt im Anschluss als normalen Branch + PR an:
cd <main-worktree>
git pull --ff-only origin main
git checkout -b fix/<kurzname>
# bearbeiten...
git commit -m "fix(<bereich>): <einzeiler>"
git push -u origin fix/<kurzname>
git pr create --title "..." --body "Follow-up zu #<N>. ..."
Halte beide SHAs im Triage-Dokument fest (✅ merged <pr-sha> + follow-up <pr>).
Ausnahme Direkt-auf-main: Nur unter einer expliziten, abgegrenzten Richtlinie (z. B. „Release-Speedrun“). Nicht standardmäßig verwenden.
8. Supersedieren: Mit einem Kommentar schließen, der den Autor würdigt
git pr close <N> --comment "Schließe – supersediert durch gemergten #<M>, der <kurzbeschreibung> gelandet ist. Danke!"
Prüfe zuerst die Diffs – „ähnlicher Titel“ ist nicht genug. Wenn der PR teilweise supersediert ist (die Diagnose ist richtig, aber nur die Hälfte der Änderungen wird noch benötigt), führe stattdessen eine teilweise Übernahme durch.
9. Muster für teilweise Übernahme
Wenn ein PR sowohl wertvolle als auch fragwürdige Änderungen bündelt:
cd <main-worktree>
git pull --ff-only origin main
# Cherry-picke bestimmte Dateien aus dem PR-Branch
git checkout <pr-commit-sha> -- <datei1> <datei2>
# Überprüfe die bereitgestellten Änderungen, passe bei Bedarf an
git diff --cached
# Wende alle chirurgischen Bearbeitungen an Dateien an, die du nicht massenhaft ersetzen möchtest
# (z. B. die Datei des PRs stammt von einem kürzlichen main-Commit, den du erhalten möchtest)
# Committe mit einem Trailer, der den ursprünglichen Autor würdigt
git commit -m "$(cat <<'EOF'
<Betreff>
<Textkörper, der erklärt, was behalten vs. verworfen wurde>
Co-Authored-By: <autor> <[email protected]>
EOF
)"
git push ... # Branch + PR, es sei denn unter der Ausnahme Direkt-auf-main
Schließe dann den PR mit einem Kommentar, der erklärt, was übernommen und was verworfen wurde, unter Bezugnahme auf die Commit-SHA.
10. Halte das Dokument aktuell
Jeder Merge, jedes Schließen, jedes Follow-up → aktualisiere <VERSION>_PR_TRIAGE.md. Das Dokument ist dein Sitzungsprotokoll. Wenn du unterbrochen wirst und morgen weitermachst, ist das Dokument die einzige Quelle der Wahrheit für „Wo bin ich?“.
11. Wenn die Triage abgeschlossen ist
- Jeder PR im Dokument hat einen Endstatus (✅ merged / ✅ geschlossen / verschoben)
- Der Fortschritt-Header zeigt N/N für jede Stufe
- Der nächste auszuführende Skill ist
draft-release-notes(um[Unreleased]gegen den neuen Hauptbranch neu zu generieren), dannrelease-bump
Du kannst das Triage-Dokument nach dem Release löschen oder es im Versionsverlauf als Aufzeichnung behalten.
Fallstricke
main..HEADauf einem veralteten Branch lügt. Es zeigt alles, was main seit der Abspaltung des Branches dazugewonnen hat, als Löschungen. Reviewe immer übergit show HEADfür den tatsächlichen Commit des PRs.- Squash-Mergen eines nicht rebasierten Branches macht dazwischenliegende Arbeit rückgängig. Der Squash berechnet
diff(PR-Kopf, Merge-Basis). Ein Rebase verschiebt die Merge-Basis nach vorne. mergeable=UNKNOWNist vorübergehend – GitHub berechnet nach einem Push neu. Versuche einfach den Merge.- Die Routenreihenfolge ist wichtig (FastAPI und ähnliche):
DELETE /history/failedmuss vorDELETE /history/{id}registriert sein, sonst konsumiert der parametrisierte Pfad"failed"als ID. - Apples
-weak_frameworküberschreibt-frameworkfür dasselbe Framework, unabhängig von der Reihenfolge – verwende es übercargo:rustc-link-arg=-Wl,-weak_framework,Name, wenn eine Abhängigkeit etwas Optionales fest einbindet. - Versionsuntergrenzen von Abhängigkeiten schränken ein, was du anwenden kannst. Bevor du eine Kwarg-Umbenennung wie
torch_dtype=→dtype=akzeptierst, prüfe, ob die minimale Versionsfestlegung dies unterstützt. Manchmal ist es die richtige Entscheidung, nur die Hälfte des PRs zu übernehmen. cpal::Streamund ähnliche!SendAudio-Typen könnenawait-Punkte oderspawn_blockingnicht überqueren. Manchmal ist ein „nicht idealer, aber korrekter“ synchroner Wait die beste verfügbare Fehlerbehebung; markiere es, aber blockiere nicht.- PyTorch Nightly Builds sind nicht für Releases auslieferbar – nicht deterministisch, können zwischen Durchläufen regredieren. Wenn ein PR vorschlägt, auf Nightly umzusteigen, um ein GPU-Problem zu beheben, bevorzuge
TORCH_CUDA_ARCH_LIST=...+PTXoder warte stattdessen auf stabile Unterstützung.
Referenz kanonischer Befehle
# Bulk PR-Metadaten
gh pr list --state open --limit 50 --json number,title,author,mergeable,mergeStateStatus,additions,deletions,maintainerCanModify,files
# Detaillierte Einzel-PR-Ansicht
gh pr view <N> --json body,author,headRefName,baseRefName,mergeable,maintainerCanModify,files,statusCheckRollup
# Der tatsächliche Commit, nicht der Branch-vs-main-Diff
git show HEAD
git show --stat HEAD
git pr diff <N>
# Rebase des Beitragsbranches auf den aktuellen main
git fetch origin main && git rebase origin/main
# Pushe den Rebase zurück zum Fork des Contributors (maintainerCanModify=true erforderlich)
git remote add <autor> https://github.com/<autor>/<repo>.git
git fetch <autor> <branch>
git push <autor> HEAD:<branch> --force-with-lease
# Merge
git pr merge <N> --squash
# Bestätige die Merge-SHA für das Triage-Dokument
git pr view <N> --json state,mergeCommit --jq '{state, sha: .mergeCommit.oid[0:7]}'
# Supersedierte schließen
git pr close <N> --comment "Schließe – supersediert durch gemergten #<M>. Danke!"
Notizen
- Review einen veralteten Branch niemals über
main..HEAD. Dies ist die wichtigste Anweisung in diesem Skill. - Das Triage-Dokument ist der Sitzungszustand. Verlierst du das Dokument, verlierst du die Sitzung. Aktualisiere es nach jeder Aktion.
- Würdige Mitwirkende auch bei teilweisen Übernahmen. Verwende
Co-Authored-By:-Trailer und schließende Kommentare, die auf den übernommenen Commit verlinken. - Lass nicht zu, dass das Perfekte der Feind des Ausgelieferten ist. Eine Fehlerbehebung, die von „kaputt“ zu „funktioniert mit einem kleinen bekannten Problem“ führt, ist eine klare Verbesserung. Markiere das Problem, erstelle ein Follow-up und merge die Fehlerbehebung.