Quem nunca abriu aquele pull request de 47 arquivos modificados, 3.200 linhas adicionadas, e viu o reviewer responder com um “LGTM” em 4 minutos? A gente sabe que ninguém leu aquilo. E quem leu, pediu demissão depois.
O GitHub finalmente entregou o que devs pediam há anos: Stacked Pull Requests, agora em public preview para todos os repositórios. A feature permite quebrar mudanças gigantes em camadas menores e independentes, cada uma com seu próprio PR, review e CI. E o melhor: o rebase é automático.
Eu já usei ferramentas de terceiros pra fazer isso (Graphite, ghstack do Facebook, até shell scripts caseiros). Nenhuma delas resolvia o problema de verdade, porque o GitHub não entendia nativamente o conceito de “stack”. Agora entende.
O Problema que Todo Dev Conhece
Você está refatorando um módulo. A mudança envolve alterar o schema do banco, criar novos tipos, atualizar a API, reescrever os testes e mexer no frontend. Se você joga tudo num PR só, acontece uma de duas coisas:
- O reviewer olha, vê 2.000 linhas, e aprova sem ler (perigoso)
- O reviewer olha, vê 2.000 linhas, e não aprova nunca (bloqueante)
Os dois cenários são ruins. O primeiro enfia bug em produção. O segundo trava o sprint inteiro.
A solução clássica era “quebre em PRs menores”, mas na prática isso significava um pesadelo de rebases manuais, conflitos entre branches, e reviewers que não sabiam em que ordem olhar as coisas.
Como Stacked PRs Funcionam
A ideia é simples: em vez de um PR enorme, você cria uma pilha de PRs onde cada camada depende da anterior.
main
└── feat/schema-changes ← PR #1 (schema + tipos)
└── feat/api-layer ← PR #2 (API endpoints)
└── feat/frontend ← PR #3 (componentes React)
Cada PR aponta para o branch abaixo dele, não para main diretamente. O PR #1 aponta para main. O PR #2 aponta para feat/schema-changes. O PR #3 aponta para feat/api-layer.
Na interface do GitHub, cada PR exibe um ícone de stack com o número da camada. Um mapa visual mostra a pilha completa e permite navegar entre as camadas com um clique.
O ponto central: o reviewer do PR #2 só vê o diff daquela camada específica. Não precisa filtrar mentalmente as mudanças do schema que já foram feitas no PR #1. Cada review é focado, curto, e faz sentido isoladamente.
Instalação e Primeiros Passos
O GitHub criou uma extensão oficial do CLI para gerenciar stacks localmente:
# Instalar a extensão
gh extension install github/gh-stack
# (Opcional) Criar alias para digitar menos
gh stack alias
Depois de instalado, o workflow fica assim:
# Iniciar a stack criando o primeiro branch
gs init feat/schema-changes
# Fazer suas mudanças, commitar normalmente
git add .
git commit -m "Add new user schema fields"
# Adicionar uma nova camada na stack
gs add feat/api-layer
# Mais mudanças, mais commits
git add .
git commit -m "Add user profile API endpoints"
# Adicionar mais uma camada
gs add feat/frontend
# Quando estiver pronto, push de tudo
gs push
# Abrir todos os PRs da stack de uma vez
gs submit
O gs submit cria todos os PRs na ordem certa, com cada um apontando para o branch correto. Sem copiar e colar URLs, sem configurar base branches manualmente.
O Rebase Automático (a Parte que Importa)
Rebasing sempre foi o terror de quem tentava fazer stacked PRs manualmente. Alguém faz um fix no PR #1, e agora os PRs #2 e #3 estão desatualizados. Você precisa fazer rebase em cascata, resolver conflitos em cada branch, e rezar para não ter quebrado nada.
O GitHub agora faz isso automaticamente. Existem duas formas:
Rebase server-side (pela interface web):
Dentro de qualquer PR da stack, existe um botão para rebase em cascata. Um clique e o GitHub rebasa todos os PRs acima daquele ponto.
Rebase local (pelo CLI):
# Rebasa toda a stack localmente
gs rebase
E quando você faz merge do PR inferior, os PRs acima são automaticamente re-apontados para main e rebasados. Sem intervenção manual.
Isso sozinho já vale a feature inteira. Quem já perdeu uma tarde fazendo rebases em cascata sabe do que eu estou falando.
Merge: Flexível Como Deveria Ser
Você tem três opções para fazer merge de uma stack:
| Estratégia | O que acontece | |
|---|---|---|
| — | — | |
| Merge do topo | Faz merge de todos os PRs da stack de uma vez, de baixo para cima | |
| Merge do meio | Faz merge até aquele ponto; PRs acima são re-apontados para main |
|
| Merge individual | Faz merge só daquele PR; os de cima são rebased automaticamente |
Os três métodos de merge do GitHub funcionam: merge commit, squash e rebase. O histórico final é o mesmo de ter feito merge de cada PR individualmente, começando de baixo.
E sim, merge queues também são suportadas (rollout progressivo nas próximas semanas).
Branch Protection Funciona Igual
Uma preocupação legítima: “se eu uso branch protection com CODEOWNERS e checks obrigatórios, isso ainda funciona?”
Funciona. Cada PR na stack precisa passar pelas mesmas regras que qualquer PR normal:
- Aprovações de CODEOWNERS são exigidas em cada camada
- Checks de CI rodam em cada PR individualmente
- Status checks obrigatórios precisam passar em todos os PRs antes do merge
- Os requisitos de merge são determinados pelo branch base do PR mais baixo da stack
Não tem atalho. Cada camada é um cidadão de primeira classe no fluxo de review.
Na Prática: Quando Usar (e Quando Não Usar)
Stacked PRs brilham em cenários específicos:
Use quando:
- A mudança toca múltiplas camadas da aplicação (banco, API, frontend)
- A feature é grande demais para um review produtivo
- Você quer continuar trabalhando enquanto o PR anterior está em review
- Múltiplos reviewers precisam olhar partes diferentes da mudança
- Agentes de IA estão gerando código que precisa de review humano em partes
Não use quando:
- A mudança é pequena e atômica (um bugfix de 20 linhas não precisa de stack)
- As mudanças são independentes entre si (use PRs separados normais)
- Você está trabalhando num fork (stacked PRs exigem que todos os branches estejam no mesmo repositório)
O Ecossistema Antes do GitHub
Essa feature não nasceu do nada. O conceito de stacked diffs existe há mais de uma década:
| Ferramenta | Contexto | |
|---|---|---|
| — | — | |
| Phabricator (Meta) | Pioneiro do modelo “uma mudança = um diff”. Usado internamente no Facebook por anos. Descontinuado em 2021 | |
| Gerrit (Google) | Sistema de code review do Google que usa change sets empilhados | |
| Graphite | Startup que trouxe stacked PRs para o GitHub como extensão de terceiros | |
| ghstack (Meta) | CLI open source que simula stacked diffs no GitHub | |
| Aviator | Plataforma de merge que suporta stacked PRs com merge queues |
O Graphite, especificamente, construiu um negócio inteiro em cima dessa lacuna do GitHub. Agora que o GitHub entrega a feature nativamente, a pergunta é: o Graphite ainda tem razão de existir?
A resposta curta: provavelmente sim, pelo menos por enquanto. O Graphite tem analytics de PR, dashboards de produtividade, e integrações que vão além do que o GitHub oferece nativamente. Mas o core da proposta de valor (stacked PRs) agora é commodity.
Integração com Agentes de IA
Um detalhe que passou despercebido no anúncio: o GitHub mencionou que agentes de IA podem aprender o workflow de stacks usando gh skill install github/gh-stack.
Isso abre uma possibilidade interessante. Imagine um agente como o Copilot Workspace recebendo uma task complexa e, em vez de gerar um PR monstruoso, quebrando a implementação em uma stack de PRs focados. Schema num PR. API em outro. Testes em outro.
O reviewer humano consegue analisar cada camada com contexto suficiente para dar feedback real, em vez de olhar 3.000 linhas e torcer para estar tudo certo.
Com a tendência de agentes de código gerando PRs cada vez maiores (Cursor com 1.000 commits por segundo, Claude Code fazendo refactors de 960.000 linhas), stacked PRs podem ser a diferença entre review real e “LGTM” automático.
Tutorial Completo: Stack do Zero ao Merge
Vamos fazer na prática. Suponha que você está adicionando um sistema de notificações push no seu app:
# 1. Instalar a extensão (uma vez só)
gh extension install github/gh-stack
# 2. Criar o primeiro branch da stack
gs init feat/notification-schema
# 3. Criar a migration e os tipos
cat > migrations/add_notifications.sql << 'SQL'
CREATE TABLE notifications (
id UUID PRIMARY KEY DEFAULT gen_random_uuid(),
user_id UUID NOT NULL REFERENCES users(id),
title VARCHAR(255) NOT NULL,
body TEXT,
read_at TIMESTAMPTZ,
created_at TIMESTAMPTZ DEFAULT NOW()
);
CREATE INDEX idx_notifications_user ON notifications(user_id);
SQL
git add . && git commit -m "Add notifications table schema"
# 4. Subir uma camada: API
gs add feat/notification-api
cat > src/routes/notifications.ts << 'TS'
import { Router } from 'express';
import { db } from '../db';
const router = Router();
router.get('/:userId', async (req, res) => {
const notifications = await db.query(
'SELECT * FROM notifications WHERE user_id = $1 ORDER BY created_at DESC',
[req.params.userId]
);
res.json(notifications.rows);
});
router.patch('/:id/read', async (req, res) => {
await db.query(
'UPDATE notifications SET read_at = NOW() WHERE id = $1',
[req.params.id]
);
res.sendStatus(204);
});
export default router;
TS
git add . && git commit -m "Add notification API endpoints"
# 5. Mais uma camada: frontend
gs add feat/notification-ui
# ... código React/Vue/Svelte aqui ...
git add . && git commit -m "Add notification bell component"
# 6. Push e submit de toda a stack
gs push
gs submit
Resultado: três PRs criados, cada um com seu diff isolado, prontos para review em paralelo.
API e Webhooks
Para quem automatiza workflows, o GitHub expôs stacks via API:
# REST API: listar PRs de uma stack
curl -s -H "Authorization: Bearer $GITHUB_TOKEN" \
"https://api.github.com/repos/owner/repo/pulls/123/stack"
Webhooks de pull request agora incluem um objeto stack no payload, com informações sobre a posição do PR na pilha, quantas camadas existem, e o status de cada uma.
Na GraphQL API, campos stack estão disponíveis para consultas read-only.
Limitações (Sim, Tem Algumas)
Nem tudo são flores:
- Cross-fork não funciona. Todos os branches precisam estar no mesmo repositório. Se você trabalha com forks (comum em open source), vai ter que usar outro workflow.
- GitHub Desktop não suporta. Se você depende do Desktop em vez do CLI, não dá para criar stacks por lá.
- Merge queues estão em rollout progressivo. Se seu repo usa merge queue, pode demorar um pouco para funcionar com stacks.
- Curva de aprendizado. Devs que nunca trabalharam com stacked diffs podem demorar para entender quando e como quebrar uma mudança em camadas. Não é intuitivo na primeira vez.
O Que Muda no Dia a Dia
Se sua equipe faz reviews de PRs grandes regularmente, stacked PRs vão mudar o jogo. Reviews ficam mais rápidos, mais focados, e mais úteis. O reviewer não precisa mais fazer ginástica mental para separar “o que é schema” de “o que é lógica de negócio” de “o que é UI”.
Para quem trabalha solo, a utilidade é menor. Mas mesmo assim, a capacidade de continuar codando enquanto o PR anterior está em review, sem criar um emaranhado de branches manuais, já vale a pena.
A feature está disponível agora para todos os repositórios do GitHub. Basta instalar a extensão gh-stack e começar a empilhar.
Comparando com o Workflow Tradicional
Para deixar mais concreto, veja a diferença entre o fluxo antigo e o novo:
Antes (PR monolítico):
1. Dev coda tudo numa branch (3 dias)
2. Abre PR com 2.500 linhas
3. Reviewer demora 2 dias pra revisar
4. 47 comentários, 3 rounds de revisão
5. Merge depois de 5 dias
Agora (stacked PRs):
1. Dev coda a primeira camada (schema) em 4 horas
2. Abre PR #1 com 200 linhas — review em 1 hora
3. Enquanto isso, já está codando a API no PR #2
4. Reviewer aprova PR #1, começa PR #2
5. Tudo mergeado em 2 dias, com reviews reais
A diferença não é só de velocidade. É de qualidade. Um review de 200 linhas é fundamentalmente diferente de um review de 2.500 linhas. No primeiro, o reviewer encontra bugs. No segundo, o reviewer encontra desculpas para aprovar logo.
Estudos mostram que a taxa de detecção de defeitos cai drasticamente acima de 400 linhas por review. Stacked PRs mantêm cada camada dentro dessa zona produtiva.
O que o Phabricator fazia internamente no Meta há uma década, o GitHub finalmente trouxe para todo mundo. Demorou, mas chegou.
Fonte de inspiração: Stacked pull requests are now in public preview (GitHub Blog)













