Git e fluxo de trabalho
O modelo de commits e branches, e as estratégias de integração que as equipes usam.
As decisões de fluxo de trabalho com Git são cinco: como a equipe organiza as branches, como junta o trabalho, como desfaz mudanças, como escreve o histórico e como protege segredos.
Estratégias de branches
| Estratégia | Como funciona | Quando usar |
|---|---|---|
| Trunk-based | Todos integram na main com frequência, pelo menos uma vez por dia; branches duram horas; funcionalidades incompletas ficam escondidas por feature flags | Equipes com integração e deploy contínuos e boa cobertura de testes |
| GitHub flow | Uma branch curta por mudança, revisada num pull request e integrada na main, que está sempre pronta para deploy | O padrão para a maioria das equipes |
| Git flow | Branches develop, release, hotfix e feature, com cerimônias de versão | Produtos com várias versões mantidas ao mesmo tempo, como bibliotecas e software instalado pelo cliente |
O ponto comum das estratégias que funcionam bem é branches curtas. Uma branch que vive três semanas acumula conflitos com o trabalho de todos os outros, e a integração vira um projeto à parte. Uma branch de um dia raramente conflita.
O Git flow resolve um problema real, o de manter várias versões, mas traz uma cerimônia desnecessária para serviços com um único ambiente de produção, que é o caso da maioria dos backends.
Merge, rebase ou squash
| Merge | Rebase e avanço rápido | Squash | |
|---|---|---|---|
| Histórico | Mostra o trabalho em paralelo, com commits de junção | Linear, como se o trabalho fosse sequencial | Um commit por mudança |
| Commits da branch | Preservados | Preservados, com hashes novos | Viram um só |
| Reescreve commits | Não | Sim | Sim |
| Desfazer a mudança inteira | Reverter o commit de junção (com -m 1) | Reverter vários commits | Reverter um commit |
git bisect | Funciona, com ramificações | Simples | Simples, mas aponta para a mudança inteira |
Na prática, a escolha costuma ser configurada no servidor, para os pull requests:
- Squash é a escolha mais comum para equipes com PRs pequenos: cada PR vira um commit na
main, com a descrição do PR como mensagem, fácil de reverter. - Rebase quando os commits da branch são cuidadosos e contam uma história que vale preservar.
- Merge quando é importante registrar quando e como o trabalho paralelo foi integrado.
Escolha uma e use sempre. Um histórico que mistura os três estilos é o mais difícil de ler.
Desfazer mudanças
| Situação | Comando | Reescreve o histórico |
|---|---|---|
| Descartar edições ainda não commitadas num arquivo | git restore arquivo | Não |
| Tirar um arquivo da área de preparação | git restore --staged arquivo | Não |
| Corrigir o último commit, ainda não enviado | git commit --amend | Sim, só local |
| Desfazer commits locais, ainda não enviados | git reset | Sim, só local |
| Desfazer um commit já enviado | git revert <commit> | Não: cria um commit novo que desfaz o anterior |
Recuperar um commit "perdido" depois de um reset | git reflog e git reset --hard <hash> | Sim, só local |
A linha em destaque é a mais importante. Num commit que já está na main compartilhada, use revert. No teste, o revert criou um commit novo chamado Revert "Muda app (com defeito)", e o arquivo voltou ao conteúdo anterior, sem apagar nada do histórico nem afetar quem já tinha baixado os commits.
Push forçado
git push --force substitui o histórico do remoto pelo seu. Se alguém tiver enviado commits nesse meio-tempo, eles desaparecem da branch remota.
| Regra | Por quê |
|---|---|
Nunca force na main ou em branches compartilhadas | Apaga trabalho de outras pessoas |
Nas suas branches, prefira --force-with-lease | Só substitui se o remoto ainda estiver como você o viu por último |
Proteja a main no servidor | Bloqueie push forçado e exija PR com revisão e testes passando |
Commits e mensagens
| Prática | Por quê |
|---|---|
| Um assunto por commit | Fica possível reverter, revisar e entender cada mudança separadamente |
| Mensagem no imperativo, com o motivo | "Corrige frete para o interior quando o CEP tem traço" explica; "fix" não |
| Commits que compilam e passam nos testes | O git bisect depende de cada commit poder ser testado |
| PRs pequenos | São revisados com atenção, integrados rápido e revertidos sem drama |
Algumas equipes adotam um padrão de mensagem, como os Conventional Commits (feat:, fix:, docs:), que permite gerar notas de versão automaticamente. O padrão ajuda; o que mais importa é a mensagem explicar o motivo.
Segredos
| Momento | O que fazer |
|---|---|
| Antes | .gitignore com .env e arquivos de credenciais; um verificador de segredos antes do commit (gitleaks, detect-secrets) e na integração contínua; a varredura de segredos do próprio servidor |
| Se um segredo for commitado e enviado | Primeiro, troque o segredo: considere-o vazado. Depois, se for necessário, remova-o do histórico com git filter-repo e force a atualização, avisando a equipe |
| Se ainda não foi enviado | Remova do commit com --amend ou reset antes do push |
A ordem importa. Reescrever o histórico não apaga as cópias que já existem: os clones da equipe, os forks, os caches do servidor e qualquer ferramenta que tenha lido o repositório. Só trocar a credencial torna o vazamento inofensivo.
Resumo da decisão
- Branches curtas, integradas pelo menos a cada poucos dias; GitHub flow como padrão.
- Uma forma de juntar, configurada no servidor; squash para PRs pequenos.
- Revert para desfazer o que já está compartilhado;
resetsó no que é local. - Commits pequenos, que passam nos testes, com mensagens que explicam o motivo.
- Segredos fora do repositório, com verificação automática; se vazar, troque primeiro.
mainprotegida: sem push forçado, com revisão e testes obrigatórios.
O próximo nível mostra os comandos do dia a dia, o git bisect encontrando um defeito automaticamente e como ligar cada deploy ao commit de origem nas cinco linguagens.
Prompts para aprofundar
Ao abrir no ChatGPT ou no Claude, o prompt é enviado ao serviço escolhido pela URL e também fica copiado na sua área de transferência.
Escolher o fluxo de trabalho da equipe
Quero escolher o fluxo de trabalho com Git da minha equipe. Faça estas perguntas, uma por vez: - Quantas pessoas trabalham no repositório? - Com que frequência fazemos deploy, e existe mais de uma versão em produção ao mesmo tempo? - Quanto tempo uma branch costuma durar hoje? - Temos integração contínua com testes confiáveis? - Usamos feature flags? Com as respostas, compare trunk-based, GitHub flow e Git flow para o meu caso, e recomende uma estratégia, a forma de juntar os PRs e as proteções da branch principal. Termine com as regras que eu deveria escrever no guia de contribuição do projeto.
Um segredo foi commitado
Um segredo (senha, chave de API ou token) foi commitado no repositório. Quero agir do jeito certo. Pergunte se o commit já foi enviado ao remoto, se o repositório é público ou privado e se há forks. Explique, em ordem: 1. Por que remover o arquivo num commit novo não resolve. 2. Por que a primeira ação é trocar o segredo, e como fazer isso sem derrubar o sistema. 3. Se e como remover o segredo do histórico com git filter-repo, e o que isso não resolve (clones, forks, caches). 4. Como avisar a equipe e o que cada pessoa precisa fazer com o clone local. 5. Como impedir que aconteça de novo: .gitignore, verificação antes do commit, varredura na integração contínua e no servidor.
Commits e PRs que ajudam a equipe
Quero melhorar a qualidade dos commits e PRs da minha equipe, especialmente agora que boa parte do código é gerada por IA. Explique: 1. Por que commits pequenos e coesos importam para revisão, revert, bisect e blame. 2. Como escrever mensagens que explicam o motivo, com exemplos bons e ruins. 3. Como separar uma mudança grande gerada numa sessão com IA em commits menores, usando git add -p. 4. Qual é um tamanho razoável de PR e como dividir funcionalidades grandes. 5. Se vale a pena adotar Conventional Commits e o que ele traz. Peça que eu cole as mensagens dos últimos commits do meu repositório e sugira melhorias.