guia prático · github
Pull Requests e Code Review no GitHub
Do primeiro commit até o merge, com as telas reais da interface atual e um repositório de verdade para acompanhar. Escrito para quem está entrando no mercado e precisa entender como esse processo funciona dentro de uma equipe.
Índice
Seção 1Por que Pull Requests e Code Review existem
Imagine a sua primeira semana em uma equipe. Você recebe uma tarefa pequena — um
bug no checkout, digamos —, resolve em vinte linhas e quer ver aquilo funcionando
em produção. Em um projeto pessoal, bastaria um git push na
main. Em praticamente nenhuma equipe profissional é assim:
o push direto na branch principal costuma estar bloqueado, e o
caminho passa por um Pull Request.
Essa fricção é deliberada. A branch principal normalmente é a que vai para produção, direta ou indiretamente, e uma mudança que entra nela deixa de ser problema de quem escreveu para ser problema de todo mundo. O Pull Request é o ponto de controle antes disso acontecer: ele isola a sua mudança em um diff que dá para ler, dispara os testes automatizados, abre espaço para quem conhece aquela parte do sistema comentar e só libera o merge quando as condições combinadas pela equipe foram satisfeitas.
O efeito colateral mais subestimado é o registro. Daqui a seis meses, alguém vai
rodar
git blame em uma linha estranha, chegar no commit e, a partir dele,
no Pull Request — e encontrar não só o que mudou, mas
por que mudou, quem discordou e qual argumento venceu.
Código conta o como. O histórico de PRs é onde fica o porquê.
O caminho que uma tarefa percorre
O fluxo abaixo é o fio condutor deste guia. Cada etapa vai aparecer com a tela correspondente, na ordem em que acontece no dia a dia:
- Tarefa / issue
- Branch
- Commits
- Push
- Pull Request
- CI
- Code Review
- Ajustes
- Merge
Para não falar no abstrato, tudo acontece em um repositório de verdade: AffonsoPaulo/pr-and-code-review. É um módulo minúsculo em JavaScript que calcula o total de um carrinho de compras aplicando cupons de desconto. A tarefa que vamos acompanhar é a issue #1: um cupom inexistente derruba o checkout inteiro. A correção virou o Pull Request #3, e é dele que vêm quase todas as capturas deste artigo (AFFONSO, 2026).
No mercado
Nenhuma empresa usa exatamente o mesmo processo. Numa startup de cinco pessoas, um PR pode sair aberto e mergeado no mesmo dia com uma aprovação. Num banco, o mesmo PR pode precisar de duas aprovações, uma delas de um time específico, mais checagens de segurança e uma janela de deploy. O que não muda é a peça central: alguém propõe, alguém revisa, a máquina verifica, e só então o código entra.
Seção 2Antes do Pull Request: o mínimo de Git
Você não precisa dominar Git para entender Pull Requests, mas precisa de um punhado de conceitos. Esta seção cobre só o necessário para o resto do artigo fazer sentido.
Um repositório é a pasta do projeto junto com todo o seu histórico. Ele
existe em dois lugares ao mesmo tempo: o repositório local, no seu
computador, e o repositório remoto, hospedado no GitHub.
git clone cria o local a partir do remoto, e a partir daí os dois
vivem separados até você sincronizá-los de propósito com push e
pull.
Um commit é uma fotografia do projeto em um instante, com autor, data,
mensagem e um identificador (o SHA, aquele d16452f que aparece na
interface). Commits encadeiam-se: cada um aponta para o anterior, e essa corrente
é o histórico.
Uma branch é um ponteiro móvel para um commit dessa corrente. É por isso
que criar uma branch é instantâneo e barato: não se copia nada,
só se anota "a partir daqui, meus commits seguem por este caminho". A
main é a branch principal — a versão oficial do projeto. Uma
branch de feature é uma linha paralela onde você trabalha sem afetar a
main enquanto a mudança não estiver pronta
(CHACON; STRAUB, 2014).
Na prática, foram estes comandos que produziram a branch que o PR #3 propõe:
Terminal# baixa o repositório remoto para a sua máquina (uma vez só)
git clone https://github.com/AffonsoPaulo/pr-and-code-review.git
cd pr-and-code-review
# parte sempre de uma main atualizada, senão você constrói em cima de código velho
git switch main
git pull
# cria a branch de trabalho e já muda para ela
git switch -c fix/1-cupom-invalido
# ... edita src/cupom.js ...
# seleciona o que entra no commit e registra a mudança
git add src/cupom.js
git commit -m "Ignora cupom inexistente ou expirado em vez de quebrar"
# publica a branch no GitHub; -u liga a branch local à remota
git push -u origin fix/1-cupom-invalido
git switch -c é a forma moderna de criar e trocar de branch;
git checkout -b faz o mesmo e continua funcionando — você vai ver os
dois por aí. O git add existe porque
nem tudo que você editou precisa entrar no mesmo commit: ele é a
chance de separar o que é a mudança de verdade do arquivo de teste que você sujou
sem querer.
Dica
Nomes de branch curtos e previsíveis ajudam mais do que parece. Um padrão comum
é
tipo/numero-descricao, como fix/1-cupom-invalido ou
feat/431-user-avatar: o tipo diz o que é, o número liga à tarefa e
a descrição evita que você abra três branches e não lembre qual é qual.
main.
Observe as colunas Behind e Ahead: quantos commits aquela
branch está atrás e à frente da main.
fix/1-cupom-invalido está 4 commits à frente e 1 atrás — e a
coluna Pull request já liga cada branch ao PR correspondente.
Até aqui nada saiu do seu controle: os commits existem na sua máquina e, depois do
push, também numa branch remota que ninguém está usando. O Pull Request é o passo
seguinte —
o momento em que você pede que esse trabalho seja incorporado à
main. Se quiser exercitar esses comandos antes de seguir, o GitHub mantém cursos
gratuitos que rodam dentro de repositórios de exercício
(GITHUB, 2026m).
Seção 3O que é um Pull Request
Um Pull Request é um pedido formal para que os commits de uma branch sejam incorporados a outra. Ele não é uma operação do Git: é um objeto do GitHub, com número, título, descrição, comentários, revisões e resultado de checks automatizados, construído em volta da comparação entre duas branches (GITHUB, 2026f).
O nome vem de antes do GitHub. No fluxo original do Git, um colaborador publicava
sua cópia do repositório e enviava ao mantenedor um pedido para que ele
puxasse (pull) aquelas alterações — o comando
git request-pull existe até hoje e gera exatamente esse texto
(GIT, 2026). O GitHub transformou esse
pedido em uma página com discussão, revisão e um botão de merge.
Commit, branch e Pull Request não são a mesma coisa
| Conceito | O que é | Onde vive |
|---|---|---|
| Commit | Uma mudança registrada no histórico, com mensagem e identificador. | Git (local e remoto) |
| Branch | Um ponteiro para o commit mais recente de uma linha de trabalho. | Git (local e remoto) |
| Pull Request | Uma proposta de integrar uma branch em outra, com discussão, revisão e checks. | Só no GitHub |
A consequência prática: apagar um Pull Request não apaga commits, e um PR fechado sem merge deixa os commits existindo na branch dele. Da mesma forma, o PR não "contém" código — ele aponta para duas branches e mostra a diferença entre elas a cada instante.
Branch de origem e branch de destino
Todo PR tem dois lados. A base é a branch de destino, para onde as mudanças
vão — quase sempre a main. A compare (ou head) é a
branch de origem, onde estão os seus commits. O GitHub calcula a diferença entre
as duas e é essa diferença que as pessoas revisam.
main, recebe commits
próprios e volta por um merge. Enquanto ela existe, a main continua
andando — e é por isso que o GitHub recalcula o diff o tempo todo, comparando a
sua branch com o estado atual da base.
O que acontece dentro do PR
Aberto o Pull Request, quatro coisas passam a acontecer no mesmo lugar. O GitHub mostra a comparação entre as branches, arquivo por arquivo. A automação roda os checks configurados no repositório e devolve o resultado ali. As pessoas convidadas fazem a revisão, comentando linhas específicas ou o PR como um todo. E, quando tudo o que a equipe exige está satisfeito, alguém aciona o merge.
Vale insistir num ponto que confunde quem está começando:
o PR acompanha a branch. Todo commit novo que você empurrar para
fix/1-cupom-invalido aparece automaticamente no PR #3, sem precisar
abrir outro. É isso que torna o ciclo "revisa, ajusta, revisa de novo" possível —
e é o assunto da seção 12.
Seção 4Criando um Pull Request na prática
O ponto de partida é uma tarefa. Em times que usam GitHub Issues, ela é uma issue;
em times que usam Jira, Linear ou similares, é um ticket, e a issue talvez nem
exista. O que importa é que exista um lugar onde está escrito o que precisa ser
feito e por quê — no nosso caso, a
issue #1, que descreve o TypeError lançado quando alguém digita um cupom
inexistente.
Closes #1 na
descrição.
Com a branch criada e os commits feitos (o passo a passo está na
seção 2), o git push publica a branch. É
aí que o GitHub percebe que há trabalho novo e sugere o próximo passo
(GITHUB, 2026j).
Escolher base e compare
A primeira decisão da tela de criação é qual branch recebe o quê. A base é o destino, a compare é a origem. Inverter as duas é um erro comum e silencioso: o diff simplesmente aparece vazio ou com as mudanças ao contrário.
Título e descrição
O GitHub preenche o título sozinho a partir do nome da branch, e o resultado costuma ser ruim. "Fix/1 cupom invalido" não diz o que mudou nem o que deixou de acontecer. Esse campo é a primeira coisa que aparece na lista de PRs, nas notificações e no histórico depois do merge — vale o esforço de reescrever.
.github/pull_request_template.md do repositório.
Observe: quando existe um template, o GitHub o carrega automaticamente. Os
trechos entre <!-- --> são comentários de Markdown — servem
de instrução para quem escreve e não aparecem no PR publicado.
bug marcada na lateral.
Observe a barra lateral: Reviewers, Assignees, Labels e
a seção Development, que lembra de usar palavras-chave como
Closes #1 para fechar a issue no merge.
Dica
Escrever Closes #1 na descrição cria um vínculo real: a issue
aparece ligada ao PR e é fechada automaticamente quando o merge acontece. As
palavras-chave aceitas são close, closes,
closed, fix, fixes, fixed,
resolve, resolves e resolved. O
fechamento automático só vale quando o PR aponta para a branch padrão do
repositório; para outra base, o link até existe, mas a issue não fecha sozinha
(GITHUB, 2026o).
Reviewers e labels
Reviewers são as pessoas de quem você está pedindo revisão, e só é possível marcar quem tem acesso ao repositório: a lista mostra os colaboradores e os times disponíveis. Em uma equipe, esse campo costuma ser preenchido automaticamente pelo arquivo CODEOWNERS ou pela regra interna do time ("quem tocou nesse módulo por último revisa").
Labels não mudam nada tecnicamente — elas servem para filtrar.
bug, enhancement, documentation e afins
ajudam a responder perguntas como "quantos bugs entraram nesta semana" sem ler PR
por PR. Use as que o repositório já tem; inventar labels novas por conta própria
costuma atrapalhar mais do que ajudar.
Criar
O botão final tem duas opções, e a diferença entre elas importa: Create pull request abre o PR pronto para revisão e já solicita os code owners; Create draft pull request abre um rascunho, que não pede revisão e não pode ser mergeado enquanto estiver nesse estado.
main from fix/1-cupom-invalido" — é a forma como o
GitHub resume base e compare.
Erro comum
Abrir o PR e sair para almoçar sem olhar a aba Files changed. Boa parte
dos comentários que um reviewer faria — o console.log esquecido, o
arquivo de configuração local que entrou junto, a indentação bagunçada — você
mesmo encontra lendo o próprio diff antes de pedir revisão.
Seção 5Como escrever um bom Pull Request
Quem revisa chega no seu PR sem contexto nenhum. Não sabe qual bug você estava perseguindo, não acompanhou a conversa no chat, não viu a tela quebrada. A descrição existe para reconstruir esse contexto — e a diferença entre um PR bem escrito e um PR jogado na fila é literalmente a diferença entre receber uma revisão hoje ou daqui a três dias.
Como não fazer
Títulofix bug
Descrição
(vazia)
O reviewer precisa abrir o diff, deduzir qual bug era, adivinhar se aquela mudança de indentação foi proposital e perguntar no chat como testar. Cada uma dessas perguntas é uma ida e volta de horas.
Como fazer
TítuloCorrige queda do checkout ao
informar cupom inválido
Descrição
## Contexto
A issue #1 relata que o checkout
inteiro cai quando a pessoa digita
um cupom que não existe...
O título diz o efeito para quem usa o sistema. A descrição explica a causa, lista o que mudou, ensina a testar e admite o que ficou de fora.
O título merece atenção especial porque ele sobrevive ao PR. Com
squash and merge, o título vira a mensagem do commit na main;
em qualquer estratégia, ele é o que aparece na lista de PRs, no changelog e na
busca. "Corrige queda do checkout ao informar cupom inválido" responde sozinho o
que mudou. "fix bug" obriga a abrir o diff.
Um template que funciona
Colocar um arquivo .github/pull_request_template.md no repositório
faz o GitHub preencher a descrição automaticamente a cada PR novo
(GITHUB, 2026k). É o que acontece no
repositório de exemplo, e o formulário da seção 4 mostra
o resultado:
## Contexto
<!-- Por que essa mudança é necessária? O que estava acontecendo antes? -->
## O que foi alterado
-
-
## Como testar
1.
2.
## Riscos e pontos de atenção
<!-- O que pode quebrar? O que o reviewer deveria olhar com mais cuidado? -->
## Issue relacionada
Closes #
Cada seção resolve um problema concreto de quem revisa. O contexto evita a pergunta "por que estamos mexendo nisso?" e permite avaliar se a solução ataca a causa certa. A lista do que foi alterado dá um mapa do diff — quando alguém abre doze arquivos modificados, saber que dez deles são consequência mecânica de uma renomeação muda completamente o tempo de revisão. O como testar permite verificar de fato, em vez de só ler; e é onde ficam evidentes os casos que você não cobriu.
A seção de riscos é a que mais separa gente experiente de gente iniciante. Escrever "o cupom inválido agora falha em silêncio; quem chama não distingue 'não tinha cupom' de 'cupom recusado'" não enfraquece o PR — pelo contrário, mostra que você pensou no limite da sua própria solução e direciona a atenção do reviewer para onde ela rende mais. Foi exatamente esse parágrafo que gerou o comentário mais útil da revisão do PR #3.
Boa prática
Quando a mudança é visual, screenshots de antes e depois valem mais do que qualquer parágrafo. Quando é de API, um exemplo de requisição e resposta. Quando é de performance, o número antes e o número depois. O objetivo é sempre o mesmo: permitir que a pessoa avalie sem precisar rodar o projeto.
Vale lembrar que a descrição não substitui boas mensagens de commit, e vice-versa.
A mensagem de commit explica uma mudança específica; a descrição do PR explica o
conjunto. No PR #3, o commit
78c0e07 tem no corpo a justificativa da injeção da data — quem fizer
git log daqui a um ano encontra o raciocínio sem precisar abrir o
navegador.
Seção 6O que é Code Review
Code Review é a leitura crítica de uma mudança proposta por outra pessoa, antes que ela entre no código principal. A definição é simples; o que costuma estar errado é a expectativa. Quem começa imagina que revisar é caçar bugs, e conclui que não tem competência para revisar o código de alguém mais experiente. Caçar bugs é só uma das coisas que acontecem ali, e nem é a mais frequente.
Na prática, uma revisão responde a várias perguntas ao mesmo tempo. A solução resolve o problema que a tarefa descreve? O código vai ser compreensível daqui a seis meses, por alguém que não participou desta conversa? Existe algum caso de borda não tratado — nulo, lista vazia, timeout, concorrência? Os testes cobrem o comportamento novo ou só o caminho feliz? A mudança segue os padrões que este projeto já adota, mesmo quando eles não são os que você prefere? Há algo aqui com implicação de segurança — dado sensível em log, entrada não validada, permissão que ficou aberta?
Existe ainda um objetivo que não aparece em nenhum checklist e é talvez o mais valioso a longo prazo: espalhar conhecimento. Quando você revisa o módulo de pagamentos, você aprende o módulo de pagamentos. Times que revisam bem não têm aquela pessoa insubstituível que é a única capaz de mexer em determinada parte do sistema — e, quando ela sai de férias, o trabalho continua.
Code Review
Revisar não é aprovar ou reprovar uma pessoa. É avaliar uma proposta de mudança, com a hipótese de que quem escreveu tinha bons motivos e informações que você talvez não tenha. Um comentário que começa com "por que você optou por…" descobre mais coisa do que um que começa com "isso está errado".
O lado humano não é um detalhe. Um PR é trabalho de alguém, muitas vezes de vários dias, exposto publicamente para outras pessoas comentarem. Times onde a revisão é hostil produzem PRs defensivos, gigantes e raros — porque ninguém quer passar por aquilo com frequência. Times onde a revisão é específica, respeitosa e rápida produzem PRs pequenos e constantes, que é exatamente o que se quer.
Uma última distinção que economiza discussão: revisão não é controle de qualidade automatizado. Formatação, lint, tipos e testes são trabalho de máquina, e devem estar no CI (veja a seção 15). Reviewer humano que gasta a atenção apontando ponto e vírgula está fazendo mal o trabalho de duas pessoas: o dele e o do linter.
Seção 7Fazendo um Code Review no GitHub
A página de um Pull Request tem quatro abas principais, e cada uma responde a uma pergunta diferente (repositórios com recursos de segurança ligados podem exibir outras). Conversation traz a descrição, a linha do tempo de eventos e todos os comentários — é por onde se começa, para entender a intenção. Commits mostra os commits da branch, um a um. Checks traz o resultado detalhado da automação. Files changed é o diff, onde a revisão de fato acontece.
Comece pela descrição, não pelo código. Sem saber o que a mudança deveria fazer, você só consegue avaliar estilo. Depois passe à aba Commits se o PR for grande: commits bem separados contam a história na ordem em que o autor pensou, e revisar por etapas é mais fácil do que encarar trezentas linhas de uma vez.
Lendo o diff
- em fundo avermelhado
saíram; linhas com + em fundo esverdeado entraram. As duas colunas
de números mostram a numeração antes e depois da mudança.
Observe: 0 / 1 viewed e a caixa Viewed ao lado do arquivo.
Marcar um arquivo como visto colapsa ele e ajuda a não se perder em PRs com
muitos arquivos — se ele mudar depois, o GitHub desmarca sozinho.
O cabeçalho @@ -5,7 +5,9 @@ indica qual pedaço do arquivo está sendo
mostrado: a partir da linha 5, sete linhas na versão antiga viraram nove na nova.
Entre os blocos alterados o GitHub esconde o código que não mudou; clicar nas
setas expande o contexto, o que costuma ser necessário para julgar se uma mudança
faz sentido no fluxo em volta dela.
O ícone de engrenagem no topo permite alternar entre Unified (antes e depois intercalados) e Split (lado a lado), além de ignorar diferenças de espaço em branco — opção que salva a revisão de um PR cuja indentação inteira mudou.
Comentando em uma linha
Passar o mouse sobre uma linha do diff revela um botão azul de comentário na margem. Para comentar em várias linhas de uma vez, clique no número da primeira e arraste (ou use Shift + clique) até a última (GITHUB, 2026p).
Enquanto a revisão está pendente, dá para editar e apagar os comentários à vontade. Nada disso chega ao autor antes de você clicar em Submit review e escolher o tipo da revisão — que é o assunto da próxima seção.
Threads e resolução
Cada comentário em linha vira uma thread: o autor responde abaixo, vocês conversam ali, e o assunto fica ancorado ao trecho de código que o originou. Quando o ponto está encerrado, alguém clica em Resolve conversation e a thread colapsa, tirando ruído da página sem apagar nada — o botão Show resolved reabre.
78c0e07) e o botão para encerrar.
Observe a etiqueta Outdated no cabeçalho: o código daquela linha mudou
depois do comentário, então o GitHub avisa que o trecho citado não é mais o
atual.
Atenção
Quem resolve a conversa, por convenção, é quem a abriu — ou o autor, depois de responder. Resolver o próprio comentário do reviewer sem responder nem corrigir é uma forma silenciosa de ignorar a revisão, e times percebem isso rápido. Alguns repositórios inclusive exigem todas as conversas resolvidas para liberar o merge (veja a seção 16).
Seção 8Approve, Comment e Request changes
Ao enviar a revisão, o GitHub pede que você escolha entre três opções. Elas não são variações de tom: cada uma tem um efeito diferente no estado do PR (GITHUB, 2026e).
| Opção | O que significa | Efeito prático |
|---|---|---|
| Comment | Feedback sem tomar posição sobre o merge. | Não aprova nem bloqueia. Use para dúvidas, sugestões opcionais ou quando você revisou só uma parte. |
| Approve | Na sua avaliação, a mudança está pronta para entrar. | Conta como aprovação para as regras do repositório. É o que destrava o merge quando há exigência de revisões. |
| Request changes | Há algo que precisa ser resolvido antes do merge. | Bloqueia o merge em repositórios protegidos até que você (ou outra pessoa com acesso) reavalie. |
Na prática, a fronteira entre Comment e Request changes é onde os times mais divergem. Um critério que funciona bem: use Request changes quando existe algo que você não aceitaria ver em produção — um bug, um vazamento de dado, uma regressão de comportamento. Para preferências de estilo, refatorações que você faria diferente ou ideias para depois, Comment comunica a mesma coisa sem parar a fila de ninguém.
Há também o Approve com ressalvas, que não é um botão e sim uma prática: aprovar e deixar um comentário dizendo "aprovo; só ajuste o nome daquela variável antes de mergear". Funciona bem em times pequenos e com confiança estabelecida, e mal em times onde ninguém lê o comentário depois da aprovação.
No mercado
As regras variam bastante. Alguns times tratam Request changes como
normal e frequente; outros consideram um gesto forte, reservado a problemas
sérios, e preferem resolver o resto conversando. Em muitos lugares existe a
convenção de prefixar comentários opcionais com nit: (de
nitpick) justamente para deixar claro que não bloqueiam. Pergunte qual é
o costume do time nas primeiras semanas — é uma pergunta que ninguém acha ruim.
Seção 9Como escrever bons comentários de revisão
Um comentário útil costuma ter três partes: o que você observou, por que isso importa e o que você sugere. Comentários ruins normalmente têm só a primeira — e, muitas vezes, nem isso.
Pouco útil
Isso está errado.
O autor não sabe o que está errado, por que está errado nem o que fazer. A resposta provável é "errado como?", e vocês perderam um dia.
Útil
Esse trecho lança exceção quando
userénull— acontece no fluxo de convite, em que o registro existe antes do usuário. Dá para validar antes de acessaruser.id?
Observação concreta, cenário em que acontece e um caminho de solução. O autor consegue agir sem responder nada.
Deixar explícito o tipo do comentário economiza mais tempo do que qualquer outra convenção. Quando o autor abre dez comentários e não sabe quais bloqueiam, ele trata todos como bloqueantes — ou, pior, nenhum. Um prefixo curto resolve:
| Categoria | Exemplo de abertura | Bloqueia? |
|---|---|---|
| Bug |
"Isso quebra quando a lista vem vazia: reduce sem valor
inicial lança."
|
Sim |
| Segurança |
"O token está indo para o log em catch. Dá para logar só o
id?"
|
Sim |
| Testes | "O caminho de erro novo não tem teste — dá para cobrir o caso do cupom vencido?" | Geralmente |
| Arquitetura | "Essa regra está na camada de rota; o resto do projeto mantém regra no serviço." | Depende |
| Performance | "Essa consulta roda dentro do laço; com 500 itens são 500 idas ao banco." | Depende |
| Legibilidade | "d é data ou desconto? Um nome inteiro aqui ajudaria." |
Não |
| Dúvida | "Por que 300ms e não o valor do config? Tem algum motivo que eu não conheço?" | Não |
| Sugestão (nit) |
"nit: dá para trocar por Object.entries, mas do jeito que
está funciona."
|
Não |
O comentário mais produtivo da revisão do PR #3 seguiu essa fórmula: apontou que
new Date() dentro de estaValido prendia a regra ao
relógio da máquina, explicou o cenário concreto em que isso morderia (o cupom
BLACK25 vence em 30/11/2026) e propôs uma alternativa específica. O
autor implementou sem precisar de uma única mensagem de ida e volta.
O tom também é técnico
"Você não entendeu o requisito" descreve a pessoa; "essa validação aceita datas futuras, e o requisito na issue pede só passadas" descreve o problema — e é o segundo que leva à correção. Perguntar quando você não tem certeza também evita gastar credibilidade à toa; não raro a resposta revela uma restrição real que você desconhecia.
Criticar o código e não a pessoa não é cortesia vazia: é precisão.
Reconhecer o que ficou bom parece supérfluo e não é. Um "boa, não tinha pensado em extrair essa função" custa uma linha, ensina outras pessoas que leem o PR e equilibra uma conversa que, por natureza, é uma lista de problemas.
Erro comum
Transformar a revisão em um pedido de reescrita completa porque você faria diferente. Se a solução do autor funciona, está testada e segue os padrões do projeto, "eu teria feito de outro jeito" não é motivo para bloquear. Guarde esse capital para quando houver um problema de verdade.
Seção 10Sugestões de código
Quando a mudança que você quer propor cabe em poucas linhas,
o GitHub permite escrever o código exato em vez de descrevê-lo. É
o recurso de suggested changes: dentro de um comentário em linha, um bloco
de código marcado como suggestion vira uma proposta aplicável com um
clique.
O nome do teste não diz qual é a condição de "fora da validade"...
```suggestion
test('cupom vencido (VOLTASAS10, 28/02/2026) não aplica desconto', () => {
```
O conteúdo do bloco substitui exatamente as linhas comentadas. O botão de sugestão na barra da caixa de comentário já insere o bloco com a linha original preenchida — mais seguro do que digitar à mão, porque a indentação vem correta (GITHUB, 2026p).
Sugestões funcionam bem para correções pequenas e objetivas: um
nome melhor, um typo em texto visível, uma condição invertida, um
const no lugar de let. Funcionam mal quando a mudança
envolve mais de um arquivo, exige contexto que não cabe em três linhas ou merece
discussão — nesses casos, um comentário explicando o raciocínio rende mais do que
um bloco de código pronto que o autor aplica sem entender.
Seção 11Recebendo um Code Review
Receber quinze comentários no primeiro PR assusta, e a leitura mais comum — "então meu código é ruim" — quase sempre está errada. Volume de comentários costuma dizer mais sobre o tamanho do diff e sobre a cultura do time do que sobre a qualidade do que você escreveu. Reviewers experientes comentam bastante porque conhecem o histórico do sistema, não porque estão procurando defeito.
O primeiro passo é ler tudo antes de responder qualquer coisa. Comentários isolados parecem exigências; lidos em conjunto, eles se organizam em três grupos: o que é bug ou risco real, o que é sugestão de melhoria e o que é dúvida. Esse é o grupo que define a ordem do seu trabalho.
Para cada comentário, existem basicamente três respostas legítimas. Você concorda
e corrige — e aí responda dizendo em qual commit, como no exemplo do PR #3
("Ajustado em 78c0e07"). Você concorda que é um problema, mas acha
que ele não pertence a este PR — e aí explique, abra uma issue e cite o número;
foi o que aconteceu com a
issue #4. Ou você discorda — e aí apresente o motivo técnico, não a sua preferência.
Dica
Discordar é normal e esperado. O que muda o resultado é a forma: "não vou mudar" encerra a conversa; "considerei extrair isso, mas as duas chamadas têm ciclos de vida diferentes e a abstração ficaria vazando parâmetro — prefiro manter separado, o que você acha?" convida a pessoa a decidir junto. O guia de code review do Google recomenda exatamente essa ordem: buscar consenso com quem revisou antes de escalar, e nunca responder no calor do momento (GOOGLE, 2026a). Se o impasse continuar depois de duas trocas, leve para uma conversa síncrona: comentário de PR é péssimo meio para debate longo.
Quando terminar os ajustes, responda as threads, resolva as que ficaram encerradas e peça nova revisão. Na barra lateral, ao lado do nome de cada reviewer, existe um ícone de recarregar que dispara um novo pedido de revisão (GITHUB, 2026n) — mais eficaz do que esperar que a pessoa perceba sozinha que o PR mudou.
Boa prática
Responda todos os comentários, mesmo os que você só aceitou. Um emoji de joinha não conta: quem revisou precisa saber se você concordou, discordou ou não viu. Threads abertas sem resposta deixam o PR parado sem que ninguém saiba por quê.
Seção 12O que acontece quando chegam novos commits
O Pull Request não é uma fotografia da branch no momento em que foi aberto:
ele aponta para a branch e acompanha o que acontece nela.
Qualquer commit novo empurrado para fix/1-cupom-invalido aparece no
PR #3 automaticamente, atualizando o diff, disparando o CI de novo e avisando quem
está participando da conversa.
- PR aberto
- Comentário do reviewer
- Commit local
- git push
- PR atualizado
- CI roda de novo
- Nova revisão
Isso tem duas consequências práticas. A primeira: os comentários antigos não somem, mas podem receber a etiqueta Outdated quando o trecho citado deixa de existir na versão atual — o GitHub mantém o contexto histórico e sinaliza que ele envelheceu. A segunda: dependendo das regras do repositório, aprovações anteriores podem ser descartadas a cada push novo (a opção dismiss stale reviews, que veremos na seção 16), obrigando uma nova rodada de revisão.
Atenção
Evite git push --force em uma branch que já está em
revisão.
Reescrever o histórico quebra a âncora dos comentários existentes e faz o
reviewer perder o rastro do que já tinha olhado. Se for inevitável — um
rebase pedido pelo time, por exemplo — use
--force-with-lease e avise no PR.
Seção 13Merge: as três estratégias
Com tudo aprovado e os checks verdes, resta escolher como os commits entram na branch de destino. O botão de merge tem um menu com as três estratégias que o GitHub oferece — e o repositório pode habilitar apenas algumas delas nas configurações.
main. No squash, os
originais continuam existindo na página do PR, mas não no histórico da
main.
Merge commit
Todos os commits da branch entram na main e um commit extra registra
a junção. O histórico fica fiel ao que aconteceu: dá para ver que aqueles cinco
commits foram feitos juntos, em uma branch, e integrados de uma vez. O custo é um
grafo mais cheio — em um repositório movimentado, o git log vira uma
trança difícil de ler.
Squash and merge
Todos os commits da branch viram um só na main.
É uma escolha frequente em times de produto, porque o histórico
da branch principal passa a ter uma entrada por mudança entregue, e não por passo
intermediário — "wip", "ajusta teste", "corrige lint" desaparecem. Foi o que
usamos no PR #3: quatro commits viraram e6e9ab2, com o título do PR e
o número entre parênteses.
e6e9ab2 Corrige queda do checkout ao informar cupom inválido (#3)
8d3597a Configura CI, template de Pull Request e CODEOWNERS
519ddb2 Adiciona cálculo de subtotal e aplicação de cupom
cd28284 Cria estrutura inicial do projeto de exemplo
A contrapartida é perder o detalhe. Se um dos commits tinha uma explicação valiosa no corpo da mensagem, ela só continua acessível pela página do PR. Por isso o título e a descrição importam tanto quando o time usa squash: eles são o que sobra.
Rebase and merge
Os commits da branch são reaplicados um a um no topo da main, sem
commit de junção. O histórico fica linear e preserva os commits individuais. Duas
ressalvas documentadas pelo GitHub: os commits ganham identificadores novos (não
são os mesmos objetos da sua branch local) e commits vazios são descartados
(GITHUB, 2026d). É a estratégia preferida
por times que cuidam do histórico com disciplina e fazem commits pequenos e
autocontidos.
| Estratégia | Histórico | Vantagem | Desvantagem |
|---|---|---|---|
| Merge commit | Ramificado, com ponto de junção | Fiel ao que aconteceu; fácil reverter o conjunto | Grafo poluído em repositórios movimentados |
| Squash | Linear, um commit por PR | Log limpo e legível; git bisect mais direto |
Perde os passos intermediários |
| Rebase | Linear, todos os commits | Detalhe preservado sem commit extra | Reescreve identificadores; exige commits bem feitos |
Depois do merge, o GitHub oferece Delete branch.
Apagar é seguro: os commits já estão na main e a
branch pode ser restaurada pela própria página do PR. Deixar branches mergeadas
acumulando só torna a lista de branches inútil.
main.
Observe o botão Revert: ele cria um PR novo desfazendo a mudança — o
caminho recomendado quando algo dá errado em produção, porque mantém o
histórico íntegro.
Seção 14Merge conflicts
Um conflito acontece quando o Git não consegue decidir sozinho como combinar duas mudanças. O caso clássico é duas branches editando as mesmas linhas do mesmo arquivo; também conta uma branch alterando um arquivo que a outra apagou (GITHUB, 2026b). Não é erro de ninguém: é o resultado normal de duas pessoas trabalharem em paralelo sobre o mesmo código.
No repositório de exemplo, o PR #7 propõe uma solução alternativa para a mesma
issue #1 que o PR #3 já resolveu. Como ele saiu de uma main anterior
ao merge e reescreveu exatamente as mesmas linhas, o GitHub não consegue integrar:
Quando o conflito é simples, dá para resolver no próprio navegador. O editor mostra o arquivo com os marcadores que o Git insere:
main significa descartar o CupomInvalidoError, que
era o ponto do PR. Resolver conflito é uma decisão de projeto, não uma escolha
mecânica.
<<<<<<< fix/erro-explicito-cupom (Current change)
if (cupom === undefined) {
throw new CupomInvalidoError(codigo);
=======
if (!cupom || !estaValido(cupom, hoje)) {
return subtotal;
>>>>>>> main (Incoming change)
Entre <<<<<<< e ======= está a sua
versão; entre ======= e >>>>>>>, a
da branch de destino. Resolver significa deixar no arquivo o código final desejado
e apagar os três marcadores — inclusive quando a resposta certa é uma terceira
versão, diferente das duas.
Conflitos que envolvem vários arquivos ou exigem rodar os testes se resolvem melhor na máquina:
Terminalgit switch fix/erro-explicito-cupom
git fetch origin
git merge origin/main # aqui o Git aponta os conflitos
# edite os arquivos, resolva os marcadores e rode os testes
npm test
git add src/cupom.js
git commit # a mensagem de merge já vem preenchida
git push
Boa prática
A melhor forma de lidar com conflitos é encurtar a janela em que eles podem
nascer:
PRs pequenos, revisados rápido e mergeados no mesmo dia raramente conflitam.
Quando um PR precisa viver mais tempo, traga a main para dentro
dele com frequência (git merge origin/main ou o botão
Update branch na própria página) em vez de descobrir tudo de uma vez no
final.
Atenção
Nem todo problema de integração aparece como conflito. No
repositório de exemplo, o PR #5 adiciona um console.warn que lê
cupom.percentual — o Git mesclou sem reclamar, porque as linhas não
colidiam, mas o código resultante volta a quebrar com cupom inexistente. Quem
pegou isso foi o CI, não o merge. É exatamente para esse tipo de caso que servem
os checks automatizados.
Seção 15Checks, CI/CD e Pull Requests
Uma parte grande do que se verifica em um PR não precisa de gente. Compilar, rodar testes, checar formatação, verificar tipos, procurar dependência vulnerável — tudo isso é trabalho mecânico, repetitivo e que uma máquina faz melhor. É o papel da integração contínua: a cada push, um servidor baixa o código, executa um conjunto de verificações e devolve o resultado para dentro do Pull Request.
No GitHub, a ferramenta nativa para isso é o GitHub Actions. Um arquivo
YAML dentro de .github/workflows/ descreve quando rodar e o que rodar
(GITHUB, 2026l). O repositório de exemplo
tem um workflow pequeno com dois jobs:
name: CI
on:
push:
branches: [main]
pull_request:
jobs:
testes:
name: Testes automatizados
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v5
with:
node-version: 22
- name: Rodar a suíte de testes
run: npm test
lint:
name: Análise estática
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v5
- uses: actions/setup-node@v5
with:
node-version: 22
- name: Verificar sintaxe dos módulos
run: |
for arquivo in $(find src test -name '*.js'); do
node --check "$arquivo"
done
O gatilho pull_request faz o workflow rodar a cada push em qualquer
branch que tenha um PR aberto. Cada job vira um check no PR, identificado
pelo nome definido no YAML — "Testes automatizados" e "Análise estática", no nosso
caso.
- push
- PR atualizado
- CI executa
- checks reportam
- review
- aprovação
- merge
O resultado aparece na caixa de status, logo acima do botão de merge. Verde quando tudo passou; vermelho com o nome do job que falhou quando algo quebrou.
npm test definido no YAML. Quando um teste falha, é aqui que está
a mensagem original.
Vale distinguir dois termos que aparecem na documentação. Checks são criados por GitHub Apps e pelo Actions, com log, anotações no diff e capacidade de re-execução. Commit statuses são o mecanismo mais antigo e simples, usado por serviços externos, que apenas marcam um commit como sucesso ou falha. Na interface do PR, os dois aparecem juntos na mesma lista (GITHUB, 2026h).
Por padrão, um check vermelho não impede o merge — ele só informa. Para que passe a impedir, ele precisa ser marcado como obrigatório nas regras do repositório, que é o assunto da próxima seção.
Erro comum
Reexecutar o check até ele passar sem investigar por quê. Teste que falha às vezes ("flaky") é um problema real do projeto, não um contratempo; ignorar é ensinar o time a desconfiar do CI, e um CI em que ninguém confia não protege nada.
Seção 16Branch protection e Rulesets
Nada do que foi descrito até aqui é obrigatório por padrão. Em um
repositório recém-criado, qualquer pessoa com acesso de escrita pode dar
git push direto na main e pular o processo inteiro.
Proteção de branch é o combinado da equipe transformado em algo que a plataforma cobra.
O GitHub tem hoje dois mecanismos para isso, e os dois continuam funcionando. As branch protection rules são o modelo clássico: uma regra por padrão de branch, visível apenas para quem administra. Os rulesets são o modelo mais novo e mais flexível: podem ser empilhados (várias regras valendo sobre a mesma branch, sempre prevalecendo a mais restritiva), podem ser ligados e desligados sem serem apagados, e são visíveis para qualquer pessoa com acesso ao repositório — o que ajuda quem está começando a entender por que o merge está bloqueado (GITHUB, 2026c), (2026g).
Em Settings → Rules → Rulesets, um ruleset define três coisas: quais branches ele atinge, em que modo está (ativo, desativado ou apenas avaliando) e quais regras aplica.
As regras que mais aparecem no dia a dia de uma equipe são estas (GITHUB, 2026i):
| Regra | O que passa a acontecer |
|---|---|
| Require a pull request before merging | Push direto na branch protegida é recusado. Toda mudança passa por um PR. |
| Required approvals | Define o número mínimo de aprovações. Uma costuma bastar; times maiores ou código crítico às vezes exigem duas. |
| Dismiss stale reviews | Cada push novo invalida as aprovações anteriores, forçando nova revisão do que mudou. |
| Require review from Code Owners | Exige aprovação de quem é dono dos arquivos tocados, conforme o CODEOWNERS. |
| Require conversation resolution | Bloqueia o merge enquanto houver thread de revisão não resolvida. |
| Require status checks to pass | Escolhe quais checks são obrigatórios. Falhou, não mergeia. |
| Require branches to be up to date | Obriga a branch a incorporar a base antes do merge, para que o CI teste a combinação real. |
| Block force pushes | Impede reescrita de histórico na branch protegida. |
O efeito no PR é imediato e explícito. Depois de ativar o ruleset no repositório de exemplo, o PR #5 passou a mostrar exatamente o que falta:
No mercado
É por isso que, na empresa, você não vai conseguir "só empurrar rapidinho na main". A proteção é o que garante que todo código em produção passou por revisão e por testes, e é também o que torna auditável responder "quem aprovou esta mudança?" — pergunta rotineira em setores regulados. Quando há uma emergência real, o caminho é a bypass list ou uma exceção registrada, não desligar a regra.
Seção 17CODEOWNERS
Em um repositório com trinta pessoas e duzentos diretórios, ninguém sabe de cabeça
quem precisa revisar o quê. O arquivo CODEOWNERS resolve isso: ele
associa padrões de arquivo a pessoas ou times, e o GitHub passa a solicitar a
revisão automaticamente quando um PR toca esses arquivos.
O arquivo pode ficar em .github/, na raiz do repositório ou em
docs/ — o GitHub procura nessa ordem e usa o primeiro que encontrar
(GITHUB, 2026a). A sintaxe lembra a do
.gitignore, com o dono listado na mesma linha do padrão:
# Dono padrão de tudo que não tiver regra mais específica
* @AffonsoPaulo
# Regras de negócio do carrinho
/src/ @AffonsoPaulo
# Pipeline e configuração de repositório
/.github/ @AffonsoPaulo
Em um repositório de equipe, as linhas normalmente apontam para times:
* @minha-org/plataforma
*.tsx @minha-org/front-end
/infra/ @minha-org/sre
/src/pagamentos/ @minha-org/pagamentos @ana-silva
/docs/ @minha-org/tech-writers
A regra de precedência é a que mais confunde:
a última linha que casa com o arquivo é a que vale. No exemplo acima, um
arquivo /src/pagamentos/cartao.tsx não pertence ao time de front-end,
apesar da extensão — a linha de pagamentos vem depois e sobrepõe. Por isso a
convenção de escrever do mais genérico para o mais específico.
Três detalhes que economizam tempo de depuração. O arquivo precisa existir na branch de destino do PR para valer — adicioná-lo na sua branch de feature não surte efeito naquele mesmo PR. Os donos listados precisam ter acesso de escrita ao repositório; quem não tem é silenciosamente ignorado. E Pull Requests em rascunho não acionam a solicitação automática: ela acontece quando o PR sai de draft.
Sozinho, o CODEOWNERS apenas sugere reviewers. Combinado com a regra Require review from Code Owners da seção 16, ele passa a ser obrigatório — e é essa combinação que garante que ninguém altere o módulo de cobrança sem que o time de cobrança olhe.
Seção 18Draft Pull Requests
Um Draft Pull Request é um PR marcado explicitamente como incompleto. Ele mostra o diff, roda o CI e aceita comentários como qualquer outro, mas não pode ser mergeado e não solicita revisão dos code owners enquanto estiver nesse estado (GITHUB, 2026f).
O uso mais comum é pedir opinião cedo, quando a decisão de arquitetura ainda dá para mudar. Abrir um rascunho com o esqueleto da solução e escrever na descrição "ainda falta X e Y; queria opinião sobre a abordagem antes de continuar" é muito mais barato do que descobrir, com o trabalho pronto, que o caminho era outro. No repositório de exemplo, o PR #6 está assim: a normalização do código do cupom funciona, mas falta o teste e falta decidir se a normalização pertence a essa camada.
O rascunho também serve para abrir o PR logo no começo da tarefa, apenas para que o time veja que aquilo está em andamento e o CI comece a rodar desde cedo — nesse caso ele funciona como um sinal de "estou trabalhando nisto", sem consumir a atenção de ninguém.
Dica
Rascunho não substitui descrição. Um draft sem explicação do que falta e do que você quer que a pessoa olhe recebe o mesmo tratamento de um PR sem descrição: ninguém entra. Diga o que já está pronto, o que falta e qual pergunta você quer responder.
Seção 19PR pequeno vs. PR gigante
Poucas variáveis afetam tanto a qualidade de uma revisão quanto o tamanho do diff. A razão é simples e não tem a ver com preguiça.
Atenção não escala linearmente.
O guia de code review do Google trata isso como número: cem linhas é um tamanho razoável para uma mudança e mil linhas já é grande demais, com a ressalva de que a contagem de arquivos pesa tanto quanto a de linhas — duzentas linhas em um arquivo podem estar de bom tamanho, as mesmas duzentas espalhadas por cinquenta arquivos normalmente não (GOOGLE, 2026b). O motivo que o guia dá é prático: é mais fácil achar cinco minutos várias vezes para revisar mudanças pequenas do que reservar meia hora seguida para uma grande. Quando esse tempo não aparece, o que sai é uma leitura superficial terminada em "LGTM".
PR A — focado
- 180 linhas alteradas
- uma responsabilidade: corrigir o cálculo de desconto
- 3 arquivos, sendo um de teste
- contexto claro na descrição
Revisável em uma sentada. Se algo quebrar depois do deploy, é óbvio o que reverter.
PR B — tudo junto
- 4.800 linhas alteradas
- refatoração + feature nova
- migração de banco
- reformatação automática do projeto inteiro
- atualização de dependências
A mudança de verdade está escondida em meio a milhares de linhas mecânicas. Reverter significa desfazer cinco coisas não relacionadas.
O problema do PR B não é o número em si — é a mistura. Um PR de 2.000 linhas que só renomeia um método em quarenta arquivos é fácil de revisar, porque o padrão se repete. O que mata a revisão é ter cinco tipos de mudança no mesmo diff, obrigando quem lê a trocar de modo mental a cada arquivo e a nunca saber se aquela linha diferente é parte da feature ou efeito colateral da formatação.
A regra prática é "uma responsabilidade por PR". Se a feature exige uma refatoração antes, faça a refatoração em um PR próprio, sem mudança de comportamento, e a feature em outro — é recomendação explícita do mesmo guia, que orienta separar refatoração de mudança de comportamento (GOOGLE, 2026b). Além de revisável, isso deixa o histórico honesto: um commit que só move código e um commit que só muda comportamento contam coisas diferentes para quem investigar um bug daqui a um ano.
Boa prática
Quando um PR grande for inevitável — uma migração, um gerador de código — separe os commits por tipo de mudança e diga isso na descrição: "commits 1 e 2 são reformatação automática, o commit 3 é a mudança de verdade". A aba Commits passa a ser um roteiro de leitura, e quem revisa consegue dedicar a atenção onde ela importa.
Seção 20Como PRs são usados no mercado
Não existe um processo universal. O que existe são configurações diferentes da mesma ideia, ajustadas ao tamanho do time, ao risco do produto e ao setor. Três recortes comuns:
Startup pequena
- feature
- PR
- 1 aprovação
- merge
Cinco ou seis pessoas, todas conhecendo o sistema inteiro. A revisão é rápida e
informal, muitas vezes acompanhada por uma conversa no chat. A proteção da
main costuma exigir só uma aprovação e os testes passando. O risco
aceito conscientemente é que decisões grandes passem com pouca discussão; a
contrapartida é velocidade.
Empresa maior
- ticket
- branch
- PR
- CI
- CODEOWNER
- 2 aprovações
- checks de segurança
- merge
O PR nasce de um ticket no Jira ou equivalente, e o número do ticket costuma estar
no nome da branch e no título. O CODEOWNERS direciona a revisão para quem mantém
cada área. Há mais checks: testes, lint, tipos, cobertura, análise de
dependências, às vezes uma verificação de licenças. Também aparecem regras que só
fazem sentido em escala, como exigir que a branch esteja atualizada com a
main antes do merge — para que o CI teste a combinação que realmente
vai para produção.
Projeto open source
- fork
- branch
- PR para o repositório original
- revisão do mantenedor
- alterações
- merge
Quem contribui normalmente não tem acesso de escrita, então o
caminho é o fork: uma cópia do repositório na sua conta, onde você cria a
branch e trabalha. O PR é aberto do seu fork para o repositório original — a tela
de criação chama isso de compare across forks. A revisão tende a ser mais
exigente com testes e documentação, porque o mantenedor vai conviver com aquele
código sem ter o seu contexto, e o tempo de resposta varia de horas a meses. Ler o
CONTRIBUTING.md antes de abrir o PR costuma ser
a diferença entre ser revisado e ser ignorado.
No mercado
Em qualquer um dos três cenários, o que se espera de quem está começando é o mesmo: PRs pequenos, descrição honesta, resposta rápida aos comentários e nenhuma surpresa. Ninguém espera que você acerte a arquitetura de primeira; esperam que você facilite a vida de quem vai revisar.
Seção 21Fluxo completo de uma tarefa
Juntando tudo, é assim que uma tarefa atravessa o processo — com os nomes que ela teria em uma empresa e o que está acontecendo por trás de cada etapa.
-
Ticket #431 — "Adicionar avatar do usuário no perfil"
A tarefa chega com o problema descrito e algum critério de aceite. Se estiver vaga, o momento de perguntar é agora, não no meio da implementação.
-
git switch -c feat/431-user-avatarBranch criada a partir de uma
mainatualizada. O número do ticket no nome liga o código à tarefa sem precisar de memória. -
Implementação
O código e os testes crescem juntos. Testes escritos depois do PR aberto costumam ser justificativas do que já foi feito, em vez de verificações do que deveria acontecer.
-
Commits
Pequenos e com mensagem no imperativo, cada um deixando o projeto em um estado coerente. Isso é o que permite revisar por partes e reverter com precisão.
-
git push -u origin feat/431-user-avatarA branch passa a existir no GitHub. Nada mudou para o resto do time ainda.
-
Abertura do Pull Request
Título explicando o efeito, descrição com contexto, o que mudou, como testar e riscos. Labels, reviewers e
Closes #431na descrição. -
CI executa
Testes, lint, build e checagens de segurança rodam sobre a branch. Enquanto estiver vermelho, pedir revisão é gastar o tempo de outra pessoa com algo que a máquina já apontou.
-
Revisão
Comentários em linha, dúvidas, sugestões. Quem revisa distingue o que bloqueia do que é opcional; quem escreveu lê tudo antes de responder qualquer coisa.
-
Ajustes e nova rodada
Commits novos entram na mesma branch e atualizam o PR automaticamente. Cada thread recebe resposta; as encerradas são resolvidas; a revisão é solicitada de novo.
-
Aprovação
Com as exigências do repositório satisfeitas — número de aprovações, code owners, checks obrigatórios, conversas resolvidas — o botão de merge libera.
-
Merge
Na estratégia adotada pelo time. Com squash, o título do PR vira a mensagem do commit na
maine a issue vinculada fecha sozinha. -
Branch removida
O histórico já está na
main. A branch pode ser restaurada pelo próprio PR se alguém precisar. -
Deploy
Em times com entrega contínua, o merge na
maindispara o pipeline de deploy. Em outros, a mudança entra na próxima release. Se algo der errado, o botão Revert do PR gera a correção em segundos.
Seção 22Boas práticas
A lista abaixo não é etiqueta: cada item resolve um problema concreto que aparece quando ele não é seguido.
- PRs pequenos, com uma responsabilidade
- Revisão superficial é consequência de diff grande, não de desleixo. Quanto menor o PR, mais específicos os comentários e mais fácil reverter se algo quebrar (GOOGLE, 2026b).
- Título que descreve o efeito
-
Com squash, ele vira a mensagem do commit na
main. É o que vai aparecer nogit log, no changelog e na busca de quem investigar um bug daqui a um ano. - Descrição com contexto, mudanças, teste e riscos
- Quem revisa não acompanhou sua semana. Cada pergunta que a descrição responde é uma ida e volta de horas que não acontece.
- Commits compreensíveis
-
Commits separados por intenção permitem revisar por etapas e usar
git bisectde verdade. "wip" e "ajustes" tornam o histórico inútil para quem investiga. - Revisar o próprio diff antes de pedir revisão
-
Boa parte dos comentários que você receberia — arquivo temporário,
console.log, trecho comentado — você encontra sozinho na aba Files changed. - Testes junto com a mudança
- Teste escrito depois tende a confirmar o que o código faz, e não o que deveria fazer. Além disso, é o teste que impede que a correção volte a quebrar seis meses depois.
- Não misturar refatoração não relacionada
- Renomear coisas no meio de uma feature esconde a mudança de verdade em meio a ruído e impede reverter uma sem desfazer a outra (GOOGLE, 2026b).
- Responder todos os comentários
- Silêncio é ambíguo: quem revisou não sabe se você concordou, discordou ou não viu — e thread sem resposta é PR parado sem motivo explícito.
- Manter a branch atualizada quando necessário
- Em PRs que vivem mais de um ou dois dias, trazer a base para dentro com frequência evita descobrir um conflito grande no pior momento — e faz o CI testar a combinação real.
- Não ignorar um check vermelho
- Reexecutar até passar transforma o CI em ruído. Se o teste é instável, isso é um problema do projeto e merece uma issue, não um clique em re-run.
Seção 23Erros comuns de quem está começando
- Trabalhar direto na
main - Funciona até o dia em que duas pessoas fazem isso ao mesmo tempo. Em repositórios protegidos, nem funciona: o push é recusado. Crie a branch antes do primeiro commit.
- Abrir um PR gigante
- Duas semanas de trabalho em um diff só garante revisão superficial e merge demorado. Quebre em etapas que façam sentido sozinhas.
- Título "update" e descrição vazia
- Empurra para quem revisa o trabalho de descobrir o que você fez. É a forma mais barata de garantir que seu PR fique por último na fila.
- Pedir revisão de código que você não testou
- Rodar os testes antes de abrir o PR é barato. Descobrir pelo reviewer que a suíte está vermelha custa o tempo de duas pessoas.
- Levar comentários para o lado pessoal
- Uma revisão com dez comentários geralmente significa que a pessoa leu com atenção. O objeto da conversa é o código, não você.
- Aproveitar o PR para arrumar outras coisas
- "Já que eu estava aqui" é como um PR de 200 linhas vira um de 900. Anote e abra outro PR.
- Resolver a conversa sem corrigir nem responder
- Fecha a thread e deixa o problema. Quem revisou percebe — e volta a abrir, com menos paciência.
- Dar Approve sem revisar
- Aprovar por cortesia esvazia o processo inteiro e transfere para você parte da responsabilidade pelo que entrar. Se não teve tempo, diga isso; se revisou só uma parte, use Comment e explique o que olhou.
Seção 24Checklist do autor
Uma passada rápida antes de clicar em Create pull request:
-
Estou na branch certa, criada a partir de uma
mainatualizada - O PR tem uma responsabilidade principal, não cinco
- Li o meu próprio diff, arquivo por arquivo
- O projeto compila e a suíte de testes passa localmente
- Adicionei ou atualizei testes para o comportamento novo
- O título explica o efeito da mudança, não o nome da branch
- A descrição tem contexto, o que mudou e por quê
- Escrevi como testar, em passos que outra pessoa consegue seguir
- Incluí screenshots ou exemplos quando a mudança é visível
- Não entrou nenhum arquivo acidental: log, configuração local, código comentado
- Marquei os reviewers certos e vinculei a issue com
Closes #
Seção 25Checklist do reviewer
E antes de clicar em Submit review:
- Entendi qual problema este PR resolve
- A solução resolve esse problema, e não um parecido
- Verifiquei os casos de borda: nulo, vazio, limite, erro
- Consigo entender o código sem o autor ao lado
- Pensei em regressões: o que mais usa esse trecho?
- Os testes cobrem o comportamento novo, não só o caminho feliz
- Olhei implicações de segurança quando o contexto pede
- Deixei claro o que bloqueia e o que é sugestão opcional
- Cada comentário meu explica o motivo, não só o que mudar
- Se aprovei, foi porque revisei de verdade
Seção 26Glossário
- Repository (repositório)
- O projeto com todo o seu histórico. Existe em duas cópias: a local, na sua máquina, e a remota, no GitHub.
- Branch
- Um ponteiro para um commit. Criar uma é barato e instantâneo, porque nada é copiado.
- Commit
- Uma mudança registrada no histórico, com autor, mensagem e identificador (SHA).
- Diff
-
A diferença entre duas versões do código, mostrada linha a linha com
+e-. - Pull Request
- Proposta de integrar os commits de uma branch em outra, com discussão, revisão e checks. Existe no GitHub, não no Git.
- Base / compare
- A branch de destino e a branch de origem de um PR.
- Reviewer
- Pessoa convidada a revisar um PR. Pode ser indicada manualmente ou automaticamente, via CODEOWNERS.
- Approval
- Revisão enviada com o estado Approve, indicando que a mudança está pronta para entrar.
- Merge
- A integração efetiva da branch de origem na de destino.
- Merge conflict
- Situação em que o Git não consegue combinar duas mudanças automaticamente e precisa de decisão humana.
- CI (integração contínua)
- Execução automática de testes e verificações a cada mudança proposta.
- Status check
- O resultado de uma verificação automatizada exibido no PR. Pode ser obrigatório ou apenas informativo.
- CODEOWNERS
- Arquivo que associa padrões de caminho a pessoas ou times, para solicitar revisão automaticamente.
- Branch protection
- Regras clássicas que restringem o que pode ser feito em uma branch: exigir PR, aprovações, checks.
- Ruleset
- Modelo mais recente de regras do GitHub, empilhável, com status próprio e visível para todo o time.
- Draft PR
- Pull Request marcado como trabalho em andamento: não pode ser mergeado e não solicita revisão dos code owners.
- Fork
- Cópia de um repositório na sua conta, usada para contribuir com projetos onde você não tem acesso de escrita.
- Squash
- Estratégia de merge que combina todos os commits do PR em um só na branch de destino.
FontesReferências
Documentação consultada para escrever este guia, toda ela verificada em 17 de setembro de 2026. As citações no texto seguem a NBR 10520 e a lista abaixo, a NBR 6023; como várias obras são do mesmo autor e do mesmo ano, elas aparecem diferenciadas por letra (2026a, 2026b, e assim por diante). Cada citação no corpo do artigo é um link para a entrada correspondente.
Vale separar dois tipos de afirmação. Como o GitHub se comporta — o que cada botão faz, o que uma regra exige, o que cada estratégia de merge produz — vem da documentação oficial e está citado no ponto em que aparece. Já as recomendações de prática — tamanho de PR, tom de comentário, o que responder, quando bloquear — são convenções de equipe: onde existe fonte pública que as sustente, ela está citada; no restante, o texto as apresenta como recomendação e não como dado. Os números de tamanho de mudança da seção 19, por exemplo, são do guia de code review do Google, não estimativas deste artigo.
- AFFONSO, Paulo. pr-and-code-review: projeto de exemplo do guia sobre Pull Requests e Code Review no GitHub. [S. l.], 2026. Disponível em: https://github.com/AffonsoPaulo/pr-and-code-review. Acesso em: 17 set. 2026.
- CHACON, Scott; STRAUB, Ben. Pro Git. 2. ed. Berkeley: Apress, 2014. Disponível em: https://git-scm.com/book/en/v2. Acesso em: 17 set. 2026.
- GIT. git-request-pull: generate a summary of pending changes. [S. l.], 2026. Disponível em: https://git-scm.com/docs/git-request-pull. Acesso em: 17 set. 2026.
- GITHUB. About code owners. [S. l.], 2026a. Disponível em: https://docs.github.com/en/repositories/managing-your-repositorys-settings-and-features/customizing-your-repository/about-code-owners. Acesso em: 17 set. 2026.
- GITHUB. About merge conflicts. [S. l.], 2026b. Disponível em: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/addressing-merge-conflicts/about-merge-conflicts. Acesso em: 17 set. 2026.
- GITHUB. About protected branches. [S. l.], 2026c. Disponível em: https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-protected-branches/about-protected-branches. Acesso em: 17 set. 2026.
- GITHUB. About pull request merges. [S. l.], 2026d. Disponível em: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/incorporating-changes-from-a-pull-request/about-pull-request-merges. Acesso em: 17 set. 2026.
- GITHUB. About pull request reviews. [S. l.], 2026e. Disponível em: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/about-pull-request-reviews. Acesso em: 17 set. 2026.
- GITHUB. About pull requests. [S. l.], 2026f. Disponível em: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/about-pull-requests. Acesso em: 17 set. 2026.
- GITHUB. About rulesets. [S. l.], 2026g. Disponível em: https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-rulesets/about-rulesets. Acesso em: 17 set. 2026.
- GITHUB. About status checks. [S. l.], 2026h. Disponível em: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/collaborating-on-repositories-with-code-quality-features/about-status-checks. Acesso em: 17 set. 2026.
- GITHUB. Available rules for rulesets. [S. l.], 2026i. Disponível em: https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/managing-rulesets/available-rules-for-rulesets. Acesso em: 17 set. 2026.
- GITHUB. Creating a pull request. [S. l.], 2026j. Disponível em: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/proposing-changes-to-your-work-with-pull-requests/creating-a-pull-request. Acesso em: 17 set. 2026.
- GITHUB. Creating a pull request template for your repository. [S. l.], 2026k. Disponível em: https://docs.github.com/en/communities/using-templates-to-encourage-useful-issues-and-pull-requests/creating-a-pull-request-template-for-your-repository. Acesso em: 17 set. 2026.
- GITHUB. GitHub Actions documentation. [S. l.], 2026l. Disponível em: https://docs.github.com/en/actions. Acesso em: 17 set. 2026.
- GITHUB. GitHub Skills. [S. l.], 2026m. Disponível em: https://skills.github.com/. Acesso em: 17 set. 2026.
- GITHUB. Incorporating feedback in your pull request. [S. l.], 2026n. Disponível em: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/incorporating-feedback-in-your-pull-request. Acesso em: 17 set. 2026.
- GITHUB. Linking a pull request to an issue. [S. l.], 2026o. Disponível em: https://docs.github.com/en/issues/tracking-your-work-with-issues/using-issues/linking-a-pull-request-to-an-issue. Acesso em: 17 set. 2026.
- GITHUB. Reviewing proposed changes in a pull request. [S. l.], 2026p. Disponível em: https://docs.github.com/en/pull-requests/collaborating-with-pull-requests/reviewing-changes-in-pull-requests/reviewing-proposed-changes-in-a-pull-request. Acesso em: 17 set. 2026.
- GOOGLE. How to handle reviewer comments. [S. l.], 2026a. Disponível em: https://google.github.io/eng-practices/review/developer/handling-comments.html. Acesso em: 17 set. 2026.
- GOOGLE. Small CLs. [S. l.], 2026b. Disponível em: https://google.github.io/eng-practices/review/developer/small-cls.html. Acesso em: 17 set. 2026.