Communitygithub.com

landing-stacked-prs

Desenreda una cadena de PRs apilados (cada uno basado en la rama del PR anterior) y los fusiona en la rama base (develop/main/master) una capa a la vez, sin necesidad de una lista de permitidos de CI para ramas intermedias. Maneja pilas nativas de GitHub a través de la API merge-async. Se activa en: fusionar la pila, desenredar los PRs apilados, fusionar la pila de PRs en develop, redirigir la pila a main, parte de una pila, merge-async, auto-merge no está soportado para pull requests apilados.

¿Qué es landing-stacked-prs?

Esta habilidad permite a agentes de IA como Claude Code o Cursor gestionar la fusión de una cadena de Pull Requests apilados (PRs) donde cada PR depende de la rama del PR anterior. En lugar de depender de verificaciones de CI en ramas intermedias, el principio clave es que la protección de la rama base es la que realmente importa. La habilidad retargetea cada capa a la rama base justo a tiempo y deja que el CI nativo de GitHub valide. Soporta tanto pilas convencionales (usando comandos `gh`) como pilas nativas de GitHub que requieren la API `merge-async`. Incluye pasos para establecer el orden de fusión basado en dependencias reales, resolver conflictos (especialmente en archivos de flujo de trabajo y colisiones de formato), y mantener la seguridad evitando force-push o reescritura de historial. También proporciona orientación sobre cómo manejar aprobaciones de CODEOWNERS y mantener los PRs abiertos sincronizados con la base entre fusiones.

Compatible con✓Claude Code~Codex CLI~Cursor
npx skills add https://github.com/sblattj/agent-chandlery/tree/main/skills/landing-stacked-prs

Preguntar en tu IA favorita

Abre un nuevo chat con esta habilidad de agente ya precargada.

Documentación

Fusionando PRs apilados en la rama base

Úsalo cuando varios PRs están encadenados (PR N basado en la rama del PR N-1) y necesitan llegar a la rama base real. El principio clave: el CI de la rama intermedia no es la puerta de entrada. La protección de la rama base sí lo es. Así que redirige cada capa a la base justo a tiempo y deja que el CI nativo la valide. Nunca confíes en codificar nombres de ramas intermedias en los desencadenadores de CI.

Repositorio: pasa -R owner/repo a gh, o ejecuta desde el clon (gh repo view --json nameWithOwner -q .nameWithOwner lo resuelve). Abajo, R es ese owner/repo.

Principios

  • El orden de fusión está dictado por dependencias reales (dependencias de contenido + archivos editados por más de una capa). Establece ese orden primero; no lo reordenes para que sea conveniente.
  • Solo fusiona una capa en la rama base, una a la vez. Nunca fusiones un hijo en su antigua rama prerequisito.
  • Antes de que importe el CI de una capa, fusiona la base actual en esa capa para que su diff se reduzca a solo su propio cambio y vea todo lo ya fusionado.
  • La rama punta contiene cada capa de forma acumulativa; una ejecución de CI en la rama punta (redirigida a la base) valida toda la pila ensamblada. Úsala como un pre-vuelo opcional.

Paso 0: establecer el orden y detectar conflictos

Resuelve la base real del repositorio (rama predeterminada del remoto git, p. ej. develop o main; el archivo de instrucciones del agente (AGENTS.md / CLAUDE.md) puede nombrar bases conocidas). Para cada PR, prueba conflictos contra la base, no contra su base apilada obsoleta (que se leerá LIMPIA y te engañará):

git fetch origin <base> <head> --quiet
git merge-tree --write-tree origin/<base> origin/<head> | grep -iE 'CONFLICT|changed in both' || echo "clean vs base"

Regla general de orden: contenido prerequisito antes de la puerta que lo necesita (p. ej. limpieza de lint antes de habilitar lint); cuando dos capas editan el mismo archivo, la primera en fusionarse va primero.

Paso 1..N: por capa, en orden

PR=<numero>
gh pr edit $PR -R $R --base <base>     # redirige fuera de la rama apilada
# un worktree separado para la rama head mantiene tu checkout principal limpio:
WT=../<repo>-<head>                    # cualquier ruta fuera de tu checkout principal
git worktree add "$WT" <head> 2>/dev/null || true
git -C "$WT" fetch origin --quiet
git -C "$WT" merge origin/<base>       # sincroniza la base; resuelve conflictos (ver abajo)
git -C "$WT" push
gh pr ready $PR -R $R                  # cuando es la capa activa
gh pr checks $PR -R $R --watch         # CI nativo, base=<base>
# solo después de la aprobación de la revisión:
gh pr merge $PR -R $R --squash --delete-branch
# luego pasa a la siguiente capa (su redirección + sincronización de base absorberá esta)

Pilas nativas de GitHub (merge-async)

Un PR creado con la función de pila nativa de GitHub rechaza los pasos clásicos anteriores:

  • gh pr edit --base: GraphQL: Cannot change the base branch because the pull request is part of a stack. (updatePullRequest)
  • gh pr merge --auto: GraphQL: Auto-merge is not supported for stacked pull requests.
  • gh pr merge: This pull request is part of a stack and must be merged using the asynchronous merge REST API.

Usa la API asíncrona, primero el PR inferior (GitHub redirige el siguiente a la base por sí mismo, dale ~30s):

sha=$(gh pr view $PR -R $R --json headRefOid -q .headRefOid)
u=$(gh api -X PUT repos/$R/pulls/$PR/merge-async -f merge_method=squash -f sha=$sha \
      -f merge_action=direct_merge --jq '.details.uuid // .status')
gh api repos/$R/pulls/$PR/merge-async/$u --jq '.status+" "+(.details.message//"")'   # espera hasta que no sea "pending"
  • Fusionar un PR apilado de esta manera también fusiona cada PR abierto por debajo de él, así que solo fusiona la capa que deseas incorporar.
  • Después de cada squash, la siguiente capa a menudo está SUCIA en archivos que ambos tocaron (un ADR, una lista de versiones): fusiona la base en ella, resuelve, haz push, espera al CI, luego fusiona-asíncronamente.
  • Las aprobaciones sobreviven a las sincronizaciones de base en repositorios que no descartan revisiones obsoletas (comprueba required_pull_request_reviews.dismiss_stale_reviews en la protección de la rama). La puerta real suele ser la aprobación de CODEOWNERS para cada ruta tocada, no el conteo de aprobaciones (pr-approval-gate enumera las brechas).
  • Para mantener cada PR abierto actualizado con su base entre fusiones, ejecuta un pase de sincronización de base: fusiona la base en cada rama de PR abierto y haz push (fusiones simples, sin force-push).

Resolución de conflictos

  • Archivos de flujo de trabajo editados por múltiples capas (flujos de trabajo de compilación reutilizables, un flujo de trabajo orquestador de CI): conserva AMBAS ediciones, no elijas un lado.
  • Colisiones de barrido de formato (una capa de barrido de Spotless/Prettier vs cambios de contenido en la base): toma el CONTENIDO de la base para el archivo en conflicto, luego vuelve a ejecutar el formateador sobre él (mvn -pl <modulo> -am spotless:apply o pnpm fmt). Tomar el lado del barrido descarta cambios reales; tomar la base sin reformatear falla la puerta de formato. Las ejecuciones del formateador necesitan que la compilación se resuelva (algunos repositorios obtienen dependencias de un registro privado que requiere un inicio de sesión en la nube primero; actualízalo si la compilación no puede obtener dependencias).

Seguridad

  • No hagas force-push, reescribas historial ni hagas push a ramas protegidas.
  • Sigue las convenciones de autoría de commits del repositorio (algunos prohíben trailers de coautoría de IA).
  • Pausa para la aprobación de la revisión humana antes de cada fusión en la rama base.
  • Si existe un PR de lista de permitidos de CI de rama intermedia (el antipatrón que esta habilidad reemplaza), recomienda cerrarlo; si ya se fusionó, revierte los nombres de rama y tipos de evento añadidos.

Relacionado

  • opening-a-stacked-pr-sequence: abrir la pila (bases, orden de fusión) y la corrección de reordenamiento por tipo de fusión (stack.sh restack).
  • pr-approval-gate: qué propietarios de código necesita aún cada capa.
  • resolve-pr-threads-and-conflicts-and-merge: fusionar una capa una vez que sus hilos y aprobaciones están listos.

Individual skills in this repo

This repo contains 1 individual skill — each has its own dedicated page.

Skills relacionados