12k
All articles

Cómo funcionan los pull requests apilados en GitHub

Conoce las pull requests apiladas de GitHub: crea una pila con gh-stack, revisa sus capas, rebasea cambios y fusiona PR dependientes.

OpenReplay Team
OpenReplay Team
Cómo funcionan los pull requests apilados en GitHub

Los pull requests apilados (stacked pull requests) de GitHub dividen un cambio grande en una cadena ordenada de pull requests pequeños: cada uno apunta a la rama del pull request que tiene debajo, y GitHub revisa, hace rebase y fusiona la cadena como una sola unidad.

La mayoría de los equipos conoce la alternativa. Desarrollas una funcionalidad en tres partes dependientes, abres tres PR y el segundo muestra los cambios del primero además de los suyos. Los revisores se rinden, o acabas juntándolo todo en un PR enorme que nadie lee con atención.

Este artículo explica de principio a fin cómo funcionan las pilas nativas de GitHub: cómo crear una pila, cómo funciona la revisión, qué ocurre cuando cambia un PR situado en mitad de la pila y qué hace cada opción de fusión. Si antes necesitas repasar los PR convencionales, consulta cómo crear pull requests desde la terminal.

Puntos clave

  • En una pila de GitHub, la base de cada pull request es la rama del PR que tiene debajo, por lo que cada diff contiene solo los cambios de esa capa.
  • GitHub anunció los pull requests apilados en versión preliminar pública (public preview) el 30 de julio de 2026. La funcionalidad está sujeta a cambios.
  • Según la guía de inicio rápido de GitHub, la extensión de CLI gh-stack requiere GitHub CLI 2.90.0 o posterior y Git 2.20 o posterior.
  • Si cambia una capa intermedia, todas las ramas que tiene encima quedan apuntando a un commit obsoleto. Hay que hacer rebase de esas ramas de abajo arriba y hacer force-push.
  • Al fusionar el PR listo situado más arriba, se fusionan en una sola operación tanto ese PR como todos los PR sin fusionar que tiene debajo. Si la fusión falla a mitad de camino, los PR ya fusionados se mantienen fusionados y el resto sigue abierto. Cada PR se valida contra las reglas de la rama base de la pila.

El problema de los pull requests dependientes

Los pull requests dependientes fracasan en la revisión porque GitHub compara cada PR con su rama base. Supongamos que abres tres PR que apuntan todos a main: auth-middleware, luego api-routes y luego ui-login. El diff del segundo PR también incluye todo el código del middleware, y el del tercero lo incluye todo. Nadie puede saber qué líneas introduce realmente cada PR.

Sin pilas nativas, los desarrolladores suelen sortear el problema de una de dos maneras. O lo fusionan todo en un único PR grande, lo que ralentiza la revisión y oculta errores. O apuntan manualmente cada PR a la rama que tiene debajo, y luego tienen que hacer rebase y cambiar la base de toda la cadena ellos mismos cada vez que algo cambia.

¿Qué son los PR apilados de GitHub?

Un pull request apilado en GitHub es un eslabón de una cadena ordenada. Cada PR usa como base la rama del PR que tiene debajo, de modo que su diff muestra únicamente los cambios realizados en esa capa. La descripción general de los pull requests apilados de GitHub explica que el PR inferior apunta al trunk de la pila, que suele ser main pero puede ser cualquier rama, como una rama de release. Todas las ramas de una pila deben estar en el mismo repositorio, por lo que las pilas no pueden abarcar forks.

Así queda el ejemplo de tres capas una vez apilado:

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)

El modelo sigue basándose en ramas y bases, algo que Git ya entiende. GitHub añade el seguimiento por encima: conoce el orden de los PR, los enlaza entre sí y opera sobre ellos como un grupo.

Crear una pila con la CLI de gh

La extensión gh-stack crea y gestiona pilas desde la terminal. La guía de inicio rápido de GitHub indica como requisitos GitHub CLI 2.90.0 o posterior y Git 2.20 o posterior. La referencia de comandos de la CLI y el README de la extensión indican un mínimo inferior, gh 2.0, por lo que lo más seguro es seguir la cifra de la guía de inicio rápido. También necesitas estar autenticado y tener permisos de push en el repositorio. Si gh es nuevo para ti, empieza por crear pull requests desde la terminal.

gh --version        # 2.90.0 or later
git --version       # 2.20 or later
gh auth login
gh extension install github/gh-stack

A continuación, construye la pila capa por capa:

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 configura el seguimiento local de la pila y crea la primera rama. Salvo que indiques --base, el trunk es la rama predeterminada del repositorio. La referencia de comandos de la CLI señala que push solo sube las ramas y nunca toca los pull requests. submit es el comando que abre los PR, asigna a cada uno la rama base correcta y los une en una pila.

También puedes usar la interfaz web. En github.com, puedes crear una pila abriendo un PR cuya base sea la rama de un PR anterior y seleccionando Create stack. Para ampliar una pila existente, abre cualquiera de sus PR y elige Add to stack en la cabecera. Si tus PR abiertos ya forman una cadena, GitHub muestra un banner que ofrece convertirlos en una pila. Las pilas se pueden usar desde la aplicación móvil de GitHub y por agentes de programación como Copilot a través de la skill gh-stack. GitHub Desktop no las admite.

Revisar una pila capa por capa

Los revisores pueden aprobar cada capa de una pila por separado. Distintos revisores pueden trabajar en distintas capas al mismo tiempo mientras el autor sigue construyendo encima. La principal ventaja de los pull requests apilados es que la revisión se hace sobre diffs pequeños y no hace falta terminar toda la funcionalidad antes de empezar a revisar.

Al abrir cualquier PR de la pila, solo ves el diff de esa capa. El cuadro de fusión incluye un mapa de la pila que lista todos los PR de la cadena con su estado, y el número del icono de pila en la parte superior de la página indica qué capa tienes abierta.

Las capas pequeñas también dejan un historial más útil en main. Cada commit que se integra es acotado, por lo que una sesión de git bisect puede señalar un cambio concreto en lugar de una fusión de mil líneas.

Actualizar un PR en mitad de la pila

Cuando llega un nuevo commit a una rama situada en mitad de una pila, todas las ramas que tiene encima siguen apuntando al commit antiguo. Hay que hacer rebase de esas ramas superiores sobre la capa actualizada y hacer force-push. En el ejemplo, una corrección derivada de la revisión en api-routes deja atrás a ui-login. auth-middleware no se ve afectada.

Con una cadena gestionada a mano, lo haces tú mismo con Git puro (consulta 10 comandos de Git para repasar los fundamentos del rebase):

# 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

Con gh-stack, el tutorial para apilar cambios de código lo reduce a dos comandos:

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

Si el rebase se detiene por un conflicto, corrige los archivos en conflicto, añádelos con git add y ejecuta gh stack rebase --continue. Para desistir, gh stack rebase --abort devuelve todas las ramas al estado en que estaban antes del rebase.

En github.com, aparece un botón Rebase stack en el cuadro de fusión cuando la pila deja de ser lineal. Según la guía para gestionar pull requests apilados, al pulsarlo se reaplican las ramas sobre el trunk más reciente, empezando por abajo, y se hace force-push de cada una. Los commits generados de esta forma en los servidores de GitHub no llevan firma, por lo que los repositorios que exigen commits firmados deben hacer el rebase en local con gh stack rebase.

El rebase reescribe las ramas superiores. Si un compañero tiene una de esas ramas en checkout, debe detenerse y sincronizarse con el remoto antes de hacer ningún otro commit. De lo contrario, su siguiente push entrará en conflicto con el historial reescrito.

Fusionar una pila

Al fusionar el pull request listo situado más arriba, se integra junto con todos los PR sin fusionar que tiene debajo en una sola operación. Si algo falla a mitad de camino, como un conflicto inesperado, la fusión se detiene en ese PR: los PR inferiores que ya se fusionaron permanecen en la rama base, y el PR fallido y todos los que tiene encima siguen abiertos. Si fusionas solo las capas inferiores, los PR superiores siguen abiertos, mientras GitHub les hace rebase y cambia su base a la rama base de la pila. La guía de fusión exige que la pila tenga un historial lineal antes de poder fusionar cualquier parte de ella.

FusionasQué llega a mainQué ocurre con el resto
PR superior listo (ui-login)Los tres PRNo queda nada abierto
PR inferior (auth-middleware)Solo ese PRLos PR superiores hacen rebase y cambian su base a main
PR intermedio (api-routes)Ese PR más todos los que tiene debajoui-login sigue abierto y cambia su base a main

Un PR situado en mitad de una pila de GitHub no se puede fusionar por sí solo. Siempre se integra junto con los PR que tiene debajo. Según la referencia de pull requests apilados de GitHub, las pilas funcionan con merge commits, squash y rebase. Con squash, cada PR se convierte en su propio commit combinado, por lo que fusionar tres PR deja tres commits en main.

Las reglas de fusión provienen de la rama base de la pila, no de la rama a la que apunta directamente cada PR. Por tanto, las protecciones de rama y los checks obligatorios siguen decidiendo qué llega a main. Las pilas también funcionan con merge queues (colas de fusión), que reciben los PR en el orden correcto. El changelog del 30 de julio de 2026 indicaba que la compatibilidad con merge queues se desplegaría de forma progresiva, y la guía de fusión de GitHub ya la describe como totalmente compatible.

Apilar antes de la compatibilidad nativa

Antes de que GitHub admitiera las pilas de forma nativa, hacía falta una herramienta independiente para gestionar la cadena de ramas. Graphite, spr y git-branchless se encargaban de esa gestión al margen del modelo de pull requests propio de GitHub.

Los pull requests apilados nativos de GitHub funcionan con las revisiones, los checks obligatorios y las protecciones de rama que ya tienes, de modo que el equipo no necesita adoptar otra herramienta. Para los equipos que recurrieron a herramientas de apilado solo para sortear los PR dependientes ilegibles, esto elimina el principal motivo para usarlas.

Conclusión

Una pila de GitHub es una cadena de pull requests en la que cada uno usa como base la rama que tiene debajo, y GitHub se encarga del rebase, del cambio de base y de la fusión. Como cada capa es pequeña, los revisores pueden leerla con atención, y un cambio en mitad de la pila solo obliga a hacer rebase de las ramas que tiene encima. Para probarlo, instala github/gh-stack y divide tu próxima funcionalidad de varias partes en tres capas.

Preguntas frecuentes

¿Funciona la fusión automática (auto-merge) con los pull requests apilados de GitHub?

No. La documentación de fusión de GitHub indica que la fusión automática no es compatible con los pull requests apilados. Las herramientas que fusionan a través de la API necesitan la API de fusión asíncrona para las pilas, porque los endpoints de fusión de pull requests más antiguos no pueden fusionar una pila. Para integrar una pila automáticamente cuando pasen los checks, usa en su lugar una merge queue: las pilas son compatibles con las merge queues, y la cola recibe los PR en el orden de la pila.

¿Qué ocurre cuando se retira un pull request apilado de una merge queue?

Todos los pull requests que tiene encima en la pila también salen de la cola. Para mantener la pila unida, la merge queue permite que un grupo de fusión crezca hasta un 50 por ciento por encima de su tamaño máximo configurado. Si una pila es demasiado grande incluso con ese margen, GitHub la reparte en varios grupos de fusión consecutivos.

¿Cómo actualizo mi pila local después de que se fusione el pull request inferior?

Ejecuta gh stack sync. En un solo paso descarga los últimos cambios, avanza el trunk, hace rebase de las ramas restantes sobre él, las sube con push y actualiza el estado de cada pull request. Añade --prune para eliminar las ramas locales de los pull requests ya fusionados. Si sync encuentra un conflicto, devuelve todas las ramas a su estado anterior; en ese caso, ejecuta gh stack rebase para resolver el conflicto y después gh stack push.

¿Cómo reordeno, elimino o renombro capas de una pila existente?

Usa gh stack modify, una interfaz interactiva de terminal que permite eliminar, combinar, insertar, reordenar y renombrar ramas. Requiere un árbol de trabajo limpio, un historial lineal, que no haya ningún rebase en curso y que ningún pull request esté en cola para fusionarse. No puedes reordenar ramas y, en la misma sesión, eliminarlas, combinarlas, insertarlas o renombrarlas. Los cambios solo se aplican al guardar, y gh stack modify --abort restaura la pila tal como estaba antes de empezar. Después, ejecuta gh stack submit para actualizar GitHub.

Understand every bug

Uncover frustrations, understand bugs and fix slowdowns like never before with OpenReplay — self-hosted, with full data ownership.

Star on GitHub

We use cookies to improve your experience. By using our site, you accept cookies.