DevGuideTK
← Trilha Backend

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égiaComo funcionaQuando usar
Trunk-basedTodos integram na main com frequência, pelo menos uma vez por dia; branches duram horas; funcionalidades incompletas ficam escondidas por feature flagsEquipes com integração e deploy contínuos e boa cobertura de testes
GitHub flowUma branch curta por mudança, revisada num pull request e integrada na main, que está sempre pronta para deployO padrão para a maioria das equipes
Git flowBranches develop, release, hotfix e feature, com cerimônias de versãoProdutos 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

MergeRebase e avanço rápidoSquash
HistóricoMostra o trabalho em paralelo, com commits de junçãoLinear, como se o trabalho fosse sequencialUm commit por mudança
Commits da branchPreservadosPreservados, com hashes novosViram um só
Reescreve commitsNãoSimSim
Desfazer a mudança inteiraReverter o commit de junção (com -m 1)Reverter vários commitsReverter um commit
git bisectFunciona, com ramificaçõesSimplesSimples, 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çãoComandoReescreve o histórico
Descartar edições ainda não commitadas num arquivogit restore arquivoNão
Tirar um arquivo da área de preparaçãogit restore --staged arquivoNão
Corrigir o último commit, ainda não enviadogit commit --amendSim, só local
Desfazer commits locais, ainda não enviadosgit resetSim, só local
Desfazer um commit já enviadogit revert <commit>Não: cria um commit novo que desfaz o anterior
Recuperar um commit "perdido" depois de um resetgit 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.

RegraPor quê
Nunca force na main ou em branches compartilhadasApaga trabalho de outras pessoas
Nas suas branches, prefira --force-with-leaseSó substitui se o remoto ainda estiver como você o viu por último
Proteja a main no servidorBloqueie push forçado e exija PR com revisão e testes passando

Commits e mensagens

PráticaPor quê
Um assunto por commitFica 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 testesO git bisect depende de cada commit poder ser testado
PRs pequenosSã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

MomentoO 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 enviadoPrimeiro, 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 enviadoRemova 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

  1. Branches curtas, integradas pelo menos a cada poucos dias; GitHub flow como padrão.
  2. Uma forma de juntar, configurada no servidor; squash para PRs pequenos.
  3. Revert para desfazer o que já está compartilhado; reset só no que é local.
  4. Commits pequenos, que passam nos testes, com mensagens que explicam o motivo.
  5. Segredos fora do repositório, com verificação automática; se vazar, troque primeiro.
  6. main protegida: 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.