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.

Os comandos desta página foram executados com o Git 2.43, em repositórios de teste.

O fluxo do dia a dia

# Atualizar a main e começar uma branch curta
git switch main
git pull --rebase
git switch -c corrige-frete-interior

# Trabalhar em commits pequenos, escolhendo o que entra em cada um
git add -p                       # revisa e escolhe trecho por trecho
git commit -m "Corrige frete para o interior quando o CEP tem traço"

# Trazer as mudanças da main antes de abrir o PR
git fetch origin
git rebase origin/main           # commits ainda não compartilhados: rebase é seguro

# Enviar
git push -u origin corrige-frete-interior
# depois de um rebase numa branch já enviada:
git push --force-with-lease

git add -p é a forma mais simples de manter commits coesos: o Git mostra cada trecho alterado e pergunta se ele entra no commit. Com código gerado por IA, que costuma mexer em vários assuntos de uma vez, ele ajuda a separar a mudança em partes que fazem sentido sozinhas.

Resolver um conflito

Um conflito acontece quando duas mudanças alteram as mesmas linhas. O Git marca o trecho no arquivo:

<<<<<<< HEAD
const FRETE_INTERIOR = 25;
=======
const FRETE_INTERIOR = 30;
>>>>>>> corrige-frete-interior
PassoComando
Ver quais arquivos têm conflitogit status
Editar o arquivo e decidir o conteúdo finalEditor; remover os marcadores
Marcar como resolvidogit add arquivo
Continuar o rebase ou o mergegit rebase --continue ou git commit
Desistir e voltar ao estado anteriorgit rebase --abort ou git merge --abort

Resolver um conflito não é escolher um dos lados: é entender as duas intenções e escrever o resultado que atende ambas. Depois de resolver, rode os testes antes de continuar.

Encontrar o commit que introduziu um defeito

git bisect faz uma busca binária no histórico: você informa um commit bom e um ruim, e o Git testa o commit do meio, depois o meio da metade restante, e assim por diante. Com git bisect run, um script faz o teste sozinho.

No teste, um repositório com 20 commits tinha um defeito introduzido no commit 14, na função de soma:

# teste_soma.py: sai com erro se o defeito estiver presente
from calc import soma

assert soma(2, 3) == 5
git bisect start HEAD HEAD~19        # ruim: agora; bom: 19 commits atrás
git bisect run python3 -B teste_soma.py
# ...
# Commit 14 is the first bad commit
git bisect reset                     # volta para onde estava

O Git encontrou o commit 14 rodando o teste cinco vezes, e não vinte. Com mil commits, seriam cerca de dez.

LinguagemComando de teste seguro para o bisect
Nodenpm ci && npx vitest run caminho/do/teste (dependências podem mudar entre commits)
Pythonpython3 -B -m pytest caminho/do/teste
Gogo test ./pacote/ -run NomeDoTeste -count=1 (-count=1 ignora o cache de testes)
Javamvn -q clean test -Dtest=NomeDoTeste
C#dotnet test --no-incremental --filter NomeDoTeste

Ligar cada deploy ao commit

Quando algo quebra em produção, a primeira pergunta é "qual versão está rodando?". Expor o commit numa rota responde na hora e permite usar git log e git bisect a partir dali.

O commit entra na imagem no momento do build:

ARG GIT_COMMIT=desconhecido
ENV GIT_COMMIT=$GIT_COMMIT
docker build --build-arg GIT_COMMIT=$(git rev-parse --short HEAD) -t loja/api:$(git rev-parse --short HEAD) .

E a aplicação o expõe:

import http from "node:http";

const versao = JSON.stringify({ commit: process.env.GIT_COMMIT ?? "desconhecido" });

http
  .createServer((req, res) => {
    if (req.url === "/versao") {
      res.setHeader("Content-Type", "application/json");
      return res.end(versao);
    }
    // ... rotas da aplicação
  })
  .listen(3000);

O que muda de uma linguagem para outra

Onde o commit entraAlternativa comum
NodeVariável de ambiente definida no build da imagemGravar num arquivo versao.json durante o build
PythonVariável de ambienteIdem
GoGravado no próprio binário com -ldflags -XO Go 1.18+ grava a revisão do Git sozinho, lida com debug.ReadBuildInfo(), quando compilado dentro do repositório
JavaVariável de ambienteO plugin git-commit-id do Maven, exposto pelo Actuator do Spring Boot em /actuator/info
C#Variável de ambienteA propriedade SourceRevisionId do MSBuild, que entra na versão informativa do assembly

No Go, o commit fica no binário e não depende da configuração do container: conferimos que o mesmo programa imprime "desconhecido" sem a opção e o hash informado com -ldflags "-X main.commit=3f9c2e1".

Com o commit em cada resposta de /versao, nos logs e nas métricas, investigar um incidente começa por git log <commit-anterior>..<commit-atual>, e não por uma adivinhação.

O mínimo do .gitignore de um backend

# Segredos e configuração local
.env
.env.*
!.env.example
*.pem
*.key

# Dependências e artefatos de build
node_modules/
__pycache__/
.venv/
bin/
obj/
target/
dist/

# Editor e sistema
.idea/
.vscode/
.DS_Store

O !.env.example mantém no repositório um arquivo de exemplo, com os nomes das variáveis e valores fictícios, que documenta a configuração sem expor nada. E um .gitignore não remove arquivos que já foram commitados: para esses, git rm --cached arquivo e, se forem segredos, troque-os.

Lista de revisão

Branches e PRs

  • As branches duram poucos dias e são integradas com frequência?
  • Os PRs são pequenos e focados num assunto?
  • A forma de juntar (squash, rebase ou merge) é sempre a mesma?
  • A main é protegida contra push forçado, com revisão e testes obrigatórios?

Commits

  • Cada commit trata de um assunto e passa nos testes?
  • As mensagens explicam o motivo da mudança?
  • Commits já compartilhados são desfeitos com revert, e não reescritos?

Segredos e rastreabilidade

  • .env e arquivos de credenciais estão no .gitignore?
  • Há verificação automática de segredos antes do commit e na integração contínua?
  • Existe um procedimento para trocar segredos que tenham sido commitados?
  • Cada deploy expõe o commit de origem?

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.

  • Praticar merge, rebase e conflitos

    Quero praticar as operações do Git num repositório de teste, sem medo de estragar nada.
    
    Vamos em etapas, com os comandos para eu rodar:
    1. Criar um repositório e uma branch feature com dois commits, e um commit novo na main.
    2. Juntar com merge e ver o grafo com git log --graph.
    3. Recriar o cenário e juntar com rebase, e ver o grafo.
    4. Recriar e juntar com squash.
    5. Provocar um conflito, resolvê-lo e continuar.
    6. Fazer um reset --hard, perder um commit e recuperá-lo pelo reflog.
    7. Reverter um commit com git revert.
    
    Em cada etapa, peça que eu preveja o grafo antes de rodar o comando.
  • Encontrar um defeito com git bisect

    Quero aprender a usar o git bisect para encontrar o commit que introduziu um defeito.
    
    Pergunte qual linguagem e ferramenta de testes eu uso.
    
    Explique:
    1. Como a busca binária funciona e quantos passos ela leva para 100 e para 1.000 commits.
    2. O bisect manual, com git bisect good e bad.
    3. O git bisect run com um script de teste que sai com erro quando o defeito aparece.
    4. Como escrever esse script na minha linguagem sem ser enganado por caches de compilação, de dependências ou de testes.
    5. O que fazer com commits que não compilam (git bisect skip).
    
    Depois me ajude a montar um repositório de teste com o defeito em um commit no meio do histórico e a encontrá-lo.
  • Revisar a configuração do repositório

    Quero revisar a configuração do meu repositório Git e do servidor (GitHub, GitLab ou outro).
    
    Pergunte qual servidor eu uso e me peça para colar o .gitignore e descrever as regras da branch principal.
    
    Verifique:
    1. O .gitignore exclui segredos, dependências e artefatos de build da minha linguagem?
    2. A branch principal está protegida contra push forçado e exclusão?
    3. PRs exigem revisão e testes passando antes de integrar?
    4. A forma de juntar PRs está definida?
    5. Há verificação automática de segredos?
    6. Cada deploy está ligado a um commit, com a versão exposta pela aplicação?
    
    Para cada item faltando, mostre como configurar.