Git
Git é a base do software moderno. Em 2025, recursos como Sparse Checkout e Scalar (para monorepos) estão se tornando convencionais.
Quando Usar
- Branching e Colaboração: Gerenciamento de isolamento de funcionalidades, pull requests, desenvolvimento trunk-based e revisões de código em equipes distribuídas.
- Reescrita e Limpeza de Histórico: Linearização de grafos de commits, squash de commits WIP e edição de mensagens via
git rebase -iantes de mesclar em branches principais. - Caça Automatizada a Bugs: Isolamento de commits que introduziram regressões em milhares de revisões por meio de busca binária usando
git bisect. - Contextos de Espaço de Trabalho Concorrentes: Trabalho em hotfixes urgentes sem a necessidade de stash ou troca de contexto de branch usando
git worktree. - Escalonamento de Repositórios Grandes: Otimização de desempenho em monorepos massivos usando Git Sparse Checkout, Scalar e clones rasos.
Início Rápido
# Clonar repositório e criar uma nova branch de funcionalidade
git clone https://github.com/minhaorg/projeto.git
cd projeto
# Criar e mudar para nova branch usando comando moderno
git switch -c feature/fluxo-autorizacao
# Stage, commit e push com rastreamento upstream
git add .
git commit -m "feat(auth): implementar fluxo de código de autorização oauth2"
git push -u origin feature/fluxo-autorizacao
Conceitos Principais
A Arquitetura de 3 Árvores (Working Tree, Index, HEAD)
O Git gerencia arquivos em três estados distintos, em vez de simplesmente rastrear alterações entre revisões:
# 1. Working Tree: Arquivos modificados não comprometidos em seu editor
echo "export const API_URL = 'https://api.v2.internal';" >> config.ts
# 2. Index (Área de Staging): Conteúdo preparado para o próximo commit
git add config.ts
# 3. HEAD: O snapshot do último commit na branch ativa
git diff --staged # Inspeciona diferença entre Staging e HEAD
git commit -m "chore(config): atualizar endpoint interno da API"
Grafo Acíclico Dirigido (DAG) e Objetos Imutáveis
Cada commit no Git é um nó imutável que aponta para hashes dos pais e uma árvore raiz de snapshots de blob.
# Inspecionar o objeto bruto por trás de qualquer hash de commit ou HEAD
git cat-file -p HEAD
# Saída:
# tree 4b825dc642cb6eb9a060e54bf8d69288fbee4904
# parent 8f3d1e1c3a628a58a98b47cf7d12a9e32049e712
# author Alice <[email protected]> 1727420400 +0000
# committer Alice <[email protected]> 1727420400 +0000
#
# feat(auth): implementar fluxo de código de autorização oauth2
Navegação Moderna em Branches (git switch vs git restore)
O Git moderno desambigua o comando sobrecarregado git checkout em operações dedicadas:
# Troca de Branch (substitui git checkout <branch>)
git switch main
git switch -c feature/pagamentos # Criar e trocar
# Restauração de Arquivos (substitui git checkout -- <arquivo>)
git restore src/app.ts # Descartar alterações não comprometidas no diretório de trabalho
git restore --staged src/app.ts # Remover arquivo do index de volta para a working tree
Estratégias de Rebase vs Merge
- Merge (
git merge <branch>): Preserva o contexto histórico completo com um commit de merge de dois pais. Ideal para integrar branches de lançamento de longa duração. - Rebase (
git rebase <upstream>): Reaplica commits do tópico linearmente no topo do HEAD upstream, evitando grafos emaranhados ("trilhos de trem"). Ideal para limpar branches de funcionalidade antes da revisão de PR.
# Rebase da branch de funcionalidade sobre a main mais recente de forma limpa
git switch feature/fluxo-autorizacao
git fetch origin main
git rebase origin/main
Padrões Comuns
Desenvolvimento Multi-Branch com Git Worktrees
Problema: Fazer stash de trabalho não comprometido para trocar de branches e corrigir um bug urgente em produção.
Solução: Faça checkout de múltiplas branches em diretórios separados simultaneamente:
# Criar pasta de worktree paralela para branch de hotfix
git worktree add ../hotfix-branch main
# Trabalhar no hotfix em diretório separado sem tocar no espaço de trabalho atual
cd ../hotfix-branch
git commit -am "fix: corrigir vulnerabilidade crítica de autenticação"
git push origin hotfix-branch
# Limpar worktree quando terminar
cd ../projeto
git worktree remove ../hotfix-branch
Rebase Interativo para Histórico Limpo de Pull Request
Problema: A branch de funcionalidade contém dezenas de commits bagunçados como "WIP", "corrigir typo" ou "ponto de verificação".
Solução: Faça squash e limpe o histórico interativamente antes de abrir um pull request.
# Rebase interativo dos últimos 4 commits
git rebase -i HEAD~4
# No editor interativo:
# pick 8f3d1e1 feat(auth): adicionar geração de token
# squash 4b825dc corrigir typo no payload do token
# squash a1c94e2 adicionar import ausente
# reword 91f7a02 feat(auth): adicionar endpoint de refresh token
Caça Automatizada a Regressões com Git Bisect
Problema: Um bug foi introduzido em algum lugar entre 500 commits, mas o commit exato é desconhecido.
Solução: Execute uma busca binária com script de execução de teste automatizado.
# Iniciar sessão bisect
git bisect start
git bisect bad HEAD # HEAD atual está quebrado
git bisect good v2.1.0 # v2.1.0 estava funcionando
# Executar script de teste automaticamente em cada etapa do bisect
git bisect run npm test -- --runInBand
# O Git termina no primeiro commit exato que quebrou a suíte de testes
git bisect reset
Melhores Práticas (2026)
Faça:
- Use
git switchegit restore: Evite ogit checkoutsobrecarregado para prevenir trocas acidentais de branch ou sobrescrita de arquivos. - Faça push com
--force-with-lease: Proteja-se contra sobrescrita de commits de colegas em branches remotos. - Ative a Manutenção em Segundo Plano: Execute
git maintenance startpara otimizar packfiles, grafos de commit e desempenho de fetch. - Assine Commits com SSH / GPG: Garanta a autenticidade da autoria do commit em pipelines de produção.
- Escreva Commits Convencionais: Use prefixos padronizados (
feat:,fix:,chore:,refactor:) para automatizar versionamento semântico e changelogs.
Não Faça:
- Não faça force push em branches protegidas: Nunca reescreva o histórico em
main,masterou branches de lançamento compartilhadas. - Não cometa segredos ou credenciais: Use
.gitignoree git-secrets/trufflehog; uma vez cometidos, as credenciais persistem em blobs de packfile mesmo se excluídas posteriormente. - Não use arquivos binários grandes diretamente: Armazene pesos de modelos grandes ou mídia em Git LFS (Large File Storage) ou S3.
- Não mescle working trees sujas: Faça stash ou commit das alterações antes de puxar ou fazer rebase para evitar conflitos de arquivo acidentais.
Solução de Problemas
| Erro | Causa | Solução |
|---|---|---|
fatal: refusing to merge unrelated histories | Puxar de um repositório inicializado independentemente sem commit raiz compartilhado. | Execute git pull origin main --allow-unrelated-histories. |
HEAD detached at ... | Checkout de um hash de commit específico em vez de um nome de branch. | Crie uma branch a partir da posição atual: git switch -c branch-recuperacao. |
Merge conflict in file.txt | Commits concorrentes modificaram linhas idênticas em branches opostas. | Resolva os marcadores de conflito (<<<<<<<), faça stage do arquivo (git add), e execute git commit. |