Git em time: branches, Pull Requests e code review na prática
Saber usar Git sozinho é diferente de usar em time. Branches, Pull Requests e code review do jeito que o mercado usa na prática.

Antes do Framework — Ep. 05
Você tem o ambiente configurado. O código roda. Agora vem o que separa quem trabalha sozinho de quem trabalha em time.
Quando eu estava aprendendo Python com Django, desenvolvi um sistema de ordem de serviço do zero, era meu projeto de estudo, meu portfólio, minha prova de que conseguia construir algo real.
E eu "já sabia" Git, repositórios, commits, push, tranquilo.
Tinha duas branches: dev e main, tudo ia pra dev e quando estava funcionando mergeava na main, muita fé.
Funcionou por um tempo, até o dia que precisei adicionar uma nova funcionalidade enquanto corrigia um bug urgente, as duas coisas misturadas na dev, uma bagunça. Ou eu subia tudo junto (e às vezes subia coisa quebrada), ou ficava parado esperando uma coisa terminar para começar a outra.
Não tava errado de um jeito absurdo, mas também não era o jeito mais certo do mundo.
O jeito certo custa literalmente 30 segundos a mais por tarefa e faz toda a diferença quando o projeto cresce, quando entra outra pessoa, ou quando você precisa voltar e entender o que você mesmo fez três semanas atrás.
Você já sabe commitar, criar branch e dar push, ótimo.
Mas chega o primeiro dia no trabalho, ou o primeiro projeto em grupo, e alguém fala:
"Abre um PR pra eu revisar antes de mergear na main."
E aí? Se você nunca trabalhou assim, o fluxo parece burocrático, mas não é, é o que separa um projeto que escala de um repositório onde ninguém sabe o que o outro está fazendo.
Por que trabalhar em time é diferente de trabalhar sozinho
Quando você é o único dev, a main é sua, você commita direto, dá push, acabou.
Em time, a main é sagrada, é o que está em produção e ninguém commita direto nela.
O motivo é simples: se dois devs alterarem o mesmo arquivo ao mesmo tempo na main, você vai ter conflito, código perdido e muito estresse. O fluxo com branches resolve isso de forma organizada.
O fluxo completo: do issue ao merge
Na prática, um ciclo de trabalho funciona assim:
1. Existe uma tarefa (issue, card, ticket)
2. Você cria uma branch para essa tarefa
3. Desenvolve na sua branch
4. Abre um Pull Request
5. Alguém revisa (code review)
6. Ajustes se necessário
7. Aprovado → merge na main
8. Branch deletada
Parece muito passo, mas com o tempo leva menos de 2 minutos do passo 2 ao 4.
Criando branches do jeito certo (não o jeito que eu fiz)
O problema do modelo dev + main é que tudo se mistura. Você nunca sabe o que está estável e o que está pela metade.
A solução é simples: uma branch por tarefa. O nome precisa comunicar o que ela faz:
git checkout -b feat/autenticacao-jwt
git checkout -b fix/bug-login-email-invalido
git checkout -b chore/atualiza-dependencias
git checkout -b docs/adiciona-readme
Os prefixos mais comuns:
| Prefixo | Quando usar |
|---|---|
feat/ | Nova funcionalidade |
fix/ | Correção de bug |
chore/ | Tarefa técnica sem impacto no usuário |
docs/ | Documentação |
refactor/ | Refatoração sem mudança de comportamento |
Isso não é só organização visual. Ferramentas de CI/CD e changelogs automáticos dependem desses padrões para funcionar.
Conventional Commits: mensagens que comunicam
Uma mensagem de commit ruim:
git commit -m "ajustes"
git commit -m "corrigindo coisa"
git commit -m "funciona agora"
Uma mensagem de commit que comunica:
git commit -m "feat: adiciona autenticação JWT com refresh token"
git commit -m "fix: corrige validação de email no formulário de login"
git commit -m "chore: atualiza dependências para versões LTS"
O formato é tipo: descrição curta no imperativo. O padrão se chama Conventional Commits e é amplamente adotado no mercado.
Por que isso importa: três meses depois, quando você precisar entender o que mudou em uma semana, git log se torna legível. E quando a empresa usa ferramentas de release automático, elas leem os commits para gerar o changelog.
Abrindo um Pull Request que as pessoas vão querer revisar
Um PR ruim chega sem contexto:
"Implementei a feature"
Um PR bom explica o que foi feito, por quê e como testar:
## O que foi feito
Implementa autenticação JWT com refresh token automático.
## Por que
Precisávamos de sessões persistentes sem expor credenciais no localStorage.
## Como testar
1. Rodar `docker compose up`
2. POST /auth/login com { email, password }
3. Verificar que o token expira em 15min e renova automaticamente
## Screenshots
[print do endpoint funcionando no Insomnia]
Isso não é formalidade. É respeito pelo tempo de quem vai revisar. E quando você for revisar o PR de outra pessoa, vai agradecer por quem escreveu assim.
Code review: como dar e receber feedback
Como revisar
Não é só procurar bug. É entender o que foi feito e pensar em casos que o autor pode ter esquecido:
- O código está legível?
- Tem algum caso de borda não tratado?
- Faz sentido com o restante do projeto?
- Tem algo que poderia ser simplificado?
Comente com contexto, não só com crítica:
❌ "Isso tá errado"
✅ "Essa validação não cobre o caso de email com subdomínio.
Exemplo: usuario@mail.empresa.com vai passar mas não deveria."
Como receber
Todo comentário é uma oportunidade de aprender, se você discorda argumente com razão técnica, se fizer sentido ajuste e marque como resolvido, o objetivo não é ganhar a discussão, é entregar código melhor.
Conflitos de merge: sem entrar em pânico
Conflito acontece quando duas branches alteram a mesma linha do mesmo arquivo, o Git não sabe qual versão manter e pede pra você decidir.
Parece assustador, mas não é.
<<<<<<< HEAD (sua branch)
const timeout = 5000
=======
const timeout = 3000
>>>>>>> main
Você escolhe qual fica, remove as marcações e commita:
git add arquivo-com-conflito.ts
git commit -m "fix: resolve conflito de merge no timeout de requisição"
IDEs como VSCode mostram isso visualmente com botões "Accept Current" / "Accept Incoming" / "Accept Both". Na prática, você raramente vai editar conflito no terminal puro.
Como evitar conflitos grandes: branches pequenas e de vida curta. Uma branch que fica aberta por duas semanas vai ter muito mais conflito do que uma que vive 2 dias.
GitHub Projects e Issues: organizando o trabalho
Antes de codar, a tarefa precisa existir em algum lugar. O GitHub tem ferramentas nativas para isso:
Issues: registram bugs, features e discussões. Cada issue tem um número (#42) que você referencia nos commits e PRs.
git commit -m "feat: adiciona paginação na listagem de produtos (closes #42)"
O closes #42 fecha a issue automaticamente quando o PR for mergeado.
GitHub Projects: quadro Kanban integrado com as issues. Colunas como "A fazer", "Em progresso", "Em review", "Concluído". Simples e suficiente para a maioria dos times.
Por que isso importa desde o primeiro projeto
Você pode estar pensando: "Isso é para time grande. Eu trabalho sozinho."
Mas não é. Mesmo sozinho, esse fluxo traz clareza:
- O histórico de commits conta a história do projeto
- As branches isolam experimentos sem afetar o que está funcionando
- Os PRs forçam você a descrever o que fez, o que melhora seu raciocínio
- Quando entrar no primeiro time, você já vai falar a língua
E tem mais: o app do GitHub no celular te notifica quando alguém comenta no seu PR, quando o CI passa ou falha, quando sua branch tem conflito. Você acompanha o projeto de qualquer lugar — sem precisar ficar preso no computador.
→ Próximo episódio
Você já sabe versionar código, trabalhar em time e automatizar o ambiente. Agora é hora de tratar a própria infraestrutura como código. Com Terraform, você para de clicar no console da AWS ou do GCP e começa a versionar servidores, bancos e redes da mesma forma que versiona sua aplicação.
Antes do Framework — Ep. 06: O que é Infrastructure as Code e como usar Terraform do zero
Newsletter
Em breveEm breve você poderá receber novos artigos direto no seu email.