Un stacked PR (PR encadenat) divideix un canvi gran en diversos pull requests petits que depenen l'un de l'altre: el PR 2 surt de la branca del PR 1, el PR 3 surt del PR 2, i així successivament. GitHub no té cap concepte natiu de 'pila': es simula apuntant cada PR a la branca base correcta i mantenint les branques sincronitzades amb rebase encadenat, cosa que des de Git 2.38 es pot automatitzar amb una sola ordre.
Què és un stacked PR (i què no és a GitHub)
Un stacked PR no és una funció de GitHub: és un patró de treball construït sobre branques i git rebase. En lloc d'obrir una única branca feature/checkout-v2 amb 40 arxius modificats i esperar que algú trobi una tarda lliure per revisar-la sencera, la divideixes en peces lògiques — per exemple 'model de dades', 'endpoint API', 'lògica de frontend' i 'tests e2e' — cadascuna amb la seva pròpia branca i el seu propi PR. Cada PR apunta com a base a la branca del PR anterior, no a main. El resultat és que un revisor pot aprovar i fusionar la peça 1 mentre la peça 4 encara s'està escrivint, i cada PR es llegeix en minuts en lloc d'hores. GitHub mostra això correctament a la comparació de diff quan defineixes bé la branca base en obrir el PR, però no ofereix cap vista agregada de 'pila' ni gestiona el reordenament per tu: això ho fas tu, a mà o amb una eina externa.
L'error que ningú explica: el squash merge trenca la pila
Aquí hi ha el fallo que gairebé cap tutorial esmenta i que explica per què la majoria d'equips que proven stacked PRs els abandonen a la primera. Si el teu repositori té 'Squash and merge' com a estratègia per defecte — l'opció més habitual perquè deixa l'historial de main net — en fusionar el PR 1, GitHub reescriu tots els seus commits en un de sol amb un hash nou. La branca del PR 2, que seguia apuntant als commits originals del PR 1, passa a tenir una història divergent respecte a main: els canvis 'ja fusionats' reapareixen com a pendents al diff. El resultat visual és aterridor — un PR de 3 arxius que de sobte mostra 40 arxius modificats — i és la raó number one per la qual a un equip li 'explota' la pila i jura no tornar-ho a provar. La solució no és evitar els stacked PRs: és no usar squash merge en branques amb fills pendents, o rebasejar la branca filla sobre main just després de cada fusió.
El mecanisme que ho fa viable sense pagar una eina externa
El motiu pel qual els stacked PRs eren un malson fins fa poc i ara són manejables té nom: git rebase --update-refs, incorporat a Git 2.38 (setembre de 2022). Abans d'aquesta versió, si rebasejaves la branca base de la pila havies de rebasejar manualment cada branca filla una per una, resolent els mateixos conflictes diverses vegades. Amb --update-refs, Git detecta quines altres branques locals apunten a commits dins del rang que estàs rebasejant i mou els seus punters juntament amb el teu en la mateixa operació. És exactament el mecanisme intern que fan servir eines de pagament com Graphite o extensions com git-spice: no fan màgia nova, orquestren la mateixa ordre amb una interfície més còmoda al damunt. A la pràctica el patró es redueix a tres ordres: git checkout -b feature/pas-2 feature/pas-1 per arrencar cada branca filla des de l'anterior, gh pr create --base feature/pas-1 per fixar l'esglaó correcte, i git rebase main --update-refs seguit de git push --force-with-lease en cada branca afectada.
Guia pràctica pas a pas amb gh CLI
Preparar i obrir la pila
- Divideix el canvi en peces que es puguin revisar i fusionar de forma independent
- Crea la primera branca des de main i obre el PR 1 normal amb gh pr create
- Crea la segona branca des de la primera (no des de main) i obre-la amb gh pr create --base <branca-1>
- Repeteix el patró per a cada peça següent, sempre apuntant a la branca immediatament anterior
- Etiqueta cada PR al títol amb la seva posició ('1/4', '2/4'...) perquè el revisor entengui l'ordre
- Desactiva 'Squash and merge' com a única opció al repositori, o pacta usar 'Rebase and merge' per a les branques intermèdies
Quan canvia la base: el moment en què la majoria es rendeix
El punt de fricció real no és crear la pila, és mantenir-la viva mentre arriben comentaris de revisió. Si un revisor demana un canvi al PR 1 i ja existeixen PR 2 i PR 3 construïts al damunt, aquest canvi s'ha de propagar cap avall abans que ningú més revisi res. El flux correcte és: apliques el canvi a la branca del PR 1, fas commit, i executes git rebase feature/pas-1 --update-refs perquè Git reordeni tota la cadena d'una sola vegada. Després fas push --force-with-lease a cada branca que s'hagi mogut; GitHub actualitza els PR afectats automàticament. Això només funciona bé si l'equip té la disciplina de rebasejar la pila el mateix dia que arriba el comentari.
ritme de revisió amb màxima detecció de defectes segons l'estudi de Cisco sobre code review (Cohen, 'Best Kept Secrets of Peer Code Review', SmartBear, 2006); per sobre d'aquest volum l'efectivitat cau amb força
- PR únic d'1.200 línies i 35 arxius: revisió posposada dies, comentaris superficials, un sol aprovador disposat a 'empassar-s'ho sencer'
- 4 PRs encadenats de 150-300 línies cadascun: revisió el mateix dia, comentaris específics per peça, possibilitat de fusionar el ja aprovat sense esperar la resta
Necessites Graphite, git-spice o similar, o et basta amb git a seques?
Aquí convé ser sincers: per a un equip de 2-4 desenvolupadors que obre stacked PRs de forma ocasional, pagar per Graphite o una altra eina dedicada sol ser gastar diners a resoldre un problema que git rebase --update-refs i uns àlies de shell ja resolen gratis. Aquestes eines aporten valor real quan l'organització té desenes de desenvolupadors obrint piles en paral·lel cada dia, però per al volum de treball d'una PIME tecnològica catalana aquest cost rarament s'amortitza. A Blurtek hem preferit en més d'un projecte quedar-nos amb git pla i una convenció de noms de branca clara abans d'introduir una dependència més al flux d'un equip petit; l'eina externa comença a justificar-se quan l'equip creix.
Quan no val la pena muntar una pila de PRs
Els stacked PRs no són la resposta a tot. Si el teu equip és d'una o dues persones, si el canvi és realment petit, o si esteu en fase de prototip on el codi canviarà de forma radical en dies, el cost de mantenir branques encadenades sincronitzades supera de llarg el benefici. La senyal que sí que compensa és una altra: quan veus que un PR porta més de dos dies obert sense revisar perquè 'és massa gran per mirar-lo ara', o quan el mateix arxiu de configuració es toca en tres features diferents. Fora d'aquests casos, un PR normal i una revisió ràpida són més barats que aprendre a gestionar una pila.
El vostre equip arrossega PRs de dies sense revisar o piles de branques que es trenquen a cada rebase? A Blurtek ajudem equips de desenvolupament petits a definir un flux de Git i de revisió de codi que encaixi amb la seva mida real, sense imposar eines que no amortitzareu.
Solicitar diagnóstico