Pull Requests: boas práticas de revisão

1. Fundamentos de um Pull Request Eficiente

1.1. O que é um Pull Request e seu ciclo de vida no Git

Um Pull Request (PR) é um mecanismo de colaboração que permite solicitar que alterações de um branch sejam integradas a outro branch (geralmente o branch principal). No Git, o ciclo de vida de um PR envolve: criação do branch de feature, desenvolvimento com commits, abertura do PR, revisão, ajustes e, finalmente, o merge.

1.2. Tamanho ideal do PR: como dividir mudanças complexas

PRs muito grandes são difíceis de revisar e aumentam a chance de bugs passarem despercebidos. O ideal é que cada PR contenha uma única mudança lógica e coesa.

Exemplo de divisão inadequada:

PR #42: "Implementar sistema de login completo"
- 40 arquivos alterados
- 2000 linhas adicionadas
- Mistura de frontend, backend e banco de dados

Exemplo de divisão adequada:

PR #42: "Adicionar modelo de usuário no banco de dados"
- 3 arquivos alterados
- 50 linhas adicionadas

PR #43: "Criar endpoint de registro de usuário"
- 5 arquivos alterados
- 120 linhas adicionadas

PR #44: "Implementar tela de login no frontend"
- 8 arquivos alterados
- 200 linhas adicionadas

1.3. Relação entre commits, branches e o PR

Cada commit deve representar uma unidade lógica de mudança. O branch do PR deve ser criado a partir de um ponto estável do branch base.

# Criando branch para nova feature
git checkout -b feature/autenticacao-jwt main

# Commits atômicos
git commit -m "feat: adicionar dependência jsonwebtoken"
git commit -m "feat: criar middleware de verificação JWT"
git commit -m "feat: proteger rotas de usuário com JWT"

2. Preparação do PR para Revisão

2.1. Escrevendo títulos e descrições claras e objetivas

O título deve resumir a mudança em poucas palavras. A descrição deve explicar o "porquê" e "como" da mudança.

Exemplo de descrição eficiente:

## Título: "Corrigir vazamento de memória no processamento de imagens"

## Descrição:
### Problema
O processamento de imagens de alta resolução estava causando
vazamento de memória, levando ao crash do servidor após
aproximadamente 100 requisições.

### Causa
O buffer de imagem não estava sendo liberado após o
redimensionamento, acumulando memória a cada requisição.

### Solução
Adicionar chamada explícita para `buffer.free()` após o
processamento. Testado com imagens de até 50MB.

### Testes
- Teste unitário para liberação de buffer
- Teste de carga com 500 requisições simultâneas

2.2. Como referenciar issues e tarefas no corpo do PR

Plataformas como GitHub e GitLab permitem referenciar issues automaticamente.

Closes #123
Related to #456

## Checklist
- [x] Código segue o guia de estilo
- [x] Testes unitários adicionados
- [x] Documentação atualizada
- [x] Sem warnings do linter

2.3. Checklist de auto-revisão antes de abrir o PR

## Auto-revisão
- [ ] O código compila sem erros?
- [ ] Testes passam localmente?
- [ ] Não há código comentado ou debug statements?
- [ ] Variáveis e funções têm nomes significativos?
- [ ] O histórico de commits está limpo?
- [ ] A branch está atualizada com o branch base?

3. Boas Práticas de Commits Dentro do PR

3.1. Commits atômicos e mensagens descritivas

Cada commit deve representar uma única mudança lógica, facilitando o entendimento e possível reversão.

# Mensagens descritivas seguindo Conventional Commits
git commit -m "feat(api): adicionar endpoint GET /users/:id"
git commit -m "fix(auth): corrigir validação de token expirado"
git commit -m "refactor(database): extrair conexão para módulo separado"

3.2. Uso de git rebase -i para limpar o histórico antes do merge

Antes do merge, reorganize os commits para manter um histórico limpo.

# Interativamente reorganizar últimos 5 commits
git rebase -i HEAD~5

# Comandos comuns no rebase interativo:
# pick - manter o commit
# squash - combinar com o commit anterior
# reword - alterar mensagem do commit
# fixup - combinar com anterior descartando mensagem

3.3. Evitando commits de "merge" e "fixup" desnecessários

Commits de merge poluem o histórico. Prefira rebase para atualizar o branch.

# Em vez de:
git merge main  # cria commit de merge desnecessário

# Faça:
git rebase main  # mantém histórico linear

4. O Papel do Revisor: O que Analisar

4.1. Lógica e corretude do código vs. estilo e formatação

Priorize a revisão da lógica de negócio. Use ferramentas automáticas (linters, formatters) para estilo.

# O que revisar manualmente:
- Lógica de validação está correta?
- Tratamento de erros é adequado?
- Casos de borda foram considerados?

# O que automatizar:
- Formatação (Prettier, Black)
- Estilo (ESLint, Pylint)
- Tipos (TypeScript, mypy)

4.2. Verificação de segurança, performance e testes

# Checklist de segurança
- [ ] Dados de entrada são sanitizados?
- [ ] Autenticação e autorização estão corretas?
- [ ] Não há exposição de informações sensíveis?

# Checklist de performance
- [ ] Consultas ao banco estão otimizadas?
- [ ] Há N+1 queries?
- [ ] Recursos são liberados corretamente?

# Checklist de testes
- [ ] Testes cobrem o cenário feliz?
- [ ] Testes cobram casos de erro?
- [ ] Testes de integração foram adicionados?

4.3. Como usar git diff e git log para entender o PR

# Ver alterações completas do PR
git diff main...feature-branch

# Ver apenas arquivos alterados
git diff --stat main...feature-branch

# Ver histórico de commits do PR
git log main..feature-branch --oneline

# Ver alterações de um commit específico
git show <commit-hash>

5. Comunicação e Feedback na Revisão

5.1. Como dar feedback construtivo e específico

# Feedback construtivo
"Na linha 42, a validação de email pode ser simplificada
usando a biblioteca `email-validator`. Isso reduziria o
código e melhoraria a cobertura de casos de borda."

# Feedback vago (evitar)
"Isso está errado."

5.2. Diferença entre "must fix", "nice to have" e "suggestion"

# Must fix (bloqueante)
"**Must fix**: A função `deleteUser` não verifica se o
usuário existe antes de tentar deletar. Isso pode causar
um erro 500. Adicione verificação de existência."

# Nice to have (não bloqueante)
"**Nice to have**: Considere adicionar logging para
facilitar debug em produção."

# Suggestion (apenas sugestão)
"**Suggestion**: Poderíamos extrair a lógica de
validação para um módulo separado no futuro."

5.3. Lidando com discordâncias e revisões iterativas

Quando houver discordância, foque em dados e evidências, não em opiniões pessoais. Ciclos de revisão são normais e esperados.

# Abordagem produtiva
"Entendo seu ponto sobre performance, mas os benchmarks
mostram que a versão atual é 30% mais lenta. Podemos
discutir alternativas na daily de hoje?"

6. Ferramentas e Fluxos de Revisão com Git

6.1. Uso de git request-pull e patches em projetos sem plataforma

Para projetos sem GitHub/GitLab, é possível usar patches.

# Gerar patch das alterações
git format-patch main --stdout > feature.patch

# Aplicar patch
git am feature.patch

# Ou usar request-pull para notificar mantenedores
git request-pull main origin feature-branch

6.2. Integração com CI/CD: testes automáticos no PR

Configure CI para executar automaticamente ao abrir/atualizar PR.

# Exemplo de workflow GitHub Actions
name: PR Checks
on: [pull_request]
jobs:
  test:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v3
      - run: npm install
      - run: npm test
      - run: npm run lint

6.3. Estratégias de merge: squash, rebase ou merge commit

# Squash - combina todos os commits em um
# Ideal para: features pequenas, histórico limpo
git merge --squash feature-branch

# Rebase - mantém commits individuais sem merge commit
# Ideal para: features com commits atômicos significativos
git rebase main feature-branch
git checkout main
git merge feature-branch

# Merge commit - preserva histórico completo
# Ideal para: colaboração em equipe, features complexas
git checkout main
git merge --no-ff feature-branch

7. Finalização e Merge do PR

7.1. Critérios para aprovação: quantos revisores?

Projetos críticos geralmente exigem 2 revisores. Projetos menores podem exigir 1.

# Critérios de aprovação
- [ ] Pelo menos 1 revisor aprovou (projetos pequenos)
- [ ] Pelo menos 2 revisores aprovaram (projetos críticos)
- [ ] Todos os "must fix" foram resolvidos
- [ ] CI/CD passou com sucesso
- [ ] Branch está atualizada com o branch base

7.2. Boas práticas ao fazer merge (evitar conflitos futuros)

# Antes do merge, atualizar branch
git checkout feature-branch
git rebase main

# Verificar se não há conflitos
git diff --check

# Fazer merge apenas quando todos os checks passarem
git checkout main
git merge --no-ff feature-branch

7.3. Atualização do branch base e limpeza pós-merge

# Após merge, deletar branch remoto e local
git push origin --delete feature-branch
git branch -d feature-branch

# Atualizar branch base
git checkout main
git pull origin main

Referências