Acelere o Git: Técnicas Essenciais de Otimização de Desempenho

Acelere o Git reduzindo o custo de clonagem, usando Git LFS com sabedoria, podando referências obsoletas, ignorando arquivos gerados e aplicando checkout esparso.

Acelere o Git: Técnicas Essenciais de Otimização de Desempenho

Git lento geralmente tem uma causa concreta: muito histórico, muitos arquivos não rastreados, objetos binários grandes, varreduras caras do sistema de arquivos ou latência de rede. Antes de culpar o próprio Git, verifique qual operação está lenta e o que ela está tentando ler ou baixar.

A otimização de desempenho do Git funciona melhor quando você combina a correção com o sintoma. Um clone lento em CI precisa de uma resposta diferente de um git status lento em uma árvore de trabalho enorme.

Entendendo as Causas do Desempenho Lento do Git

Comece com as causas comuns:

  • Um histórico longo com muitos arquivos e referências.
  • Arquivos binários grandes commitados diretamente no Git.
  • Saída de build, pastas de dependências ou logs não ignorados na árvore de trabalho.
  • Muitos ramos e tags de rastreamento remoto obsoletos.
  • Links de rede lentos para o remoto.
  • Versões antigas do Git sem as melhorias mais recentes de manutenção e checkout esparso.

Execute o comando lento com intenção. Se git clone é lento, observe o tamanho do histórico e a transferência de rede. Se git status é lento, observe o tamanho da árvore de trabalho, arquivos ignorados e o comportamento do sistema de arquivos. Se git fetch é lento, observe as referências remotas, tags e objetos alterados.

Reduza o Custo de Clone e Fetch

Para CI, jobs de implantação e inspeção somente leitura, muitas vezes você não precisa do histórico completo.

Use um clone raso:

git clone --depth <número> <url_do_repositório>

Por exemplo, para clonar apenas os últimos 10 commits:

git clone --depth 10 https://github.com/exemplo/repo.git

Para jobs de CI que constroem apenas o commit atual, --depth 1 geralmente é suficiente. Para trabalho de desenvolvedor, um clone completo costuma ser menos surpreendente porque comandos como git log profundo, checkout de tags antigas e alguns rebases precisam de mais histórico.

Se você já tem um clone raso e precisa de mais histórico, aprofunde-o:

git fetch --deepen=50 origin

Ou converta-o para um clone completo:

git fetch --unshallow origin

Para necessidades de dados parciais, versões mais recentes do Git também suportam filtros de clone parcial como --filter=blob:none, mas use-os apenas quando seu host Git e fluxo de trabalho os suportarem bem:

git clone --filter=blob:none https://github.com/exemplo/repo-grande.git

Mantenha Arquivos Grandes Fora do Histórico Normal do Git

Binários grandes são uma das maneiras mais rápidas de tornar o Git lento. Imagens, vídeos, arquivos, arquivos de design e arquivos de modelo geralmente não comprimem ou diferenciam bem.

Use Git LFS para ativos grandes que realmente pertencem ao repositório:

git lfs install
git lfs track "*.psd"
git lfs track "assets/*.mp4"
git add .gitattributes
git commit -m "Rastrear ativos grandes com Git LFS"

O Git LFS afeta commits futuros após as regras de rastreamento estarem em vigor. Se alguém já commitou arquivos grandes no histórico normal do Git, removê-los da árvore atual não é suficiente. Você pode precisar de uma reescrita de histórico coordenada com uma ferramenta como git lfs migrate import ou git filter-repo.

Para artefatos de build gerados, a melhor resposta geralmente não é LFS. Não os comite. Adicione-os ao .gitignore:

node_modules/
dist/
coverage/
*.log

Limpe Referências e Objetos Locais

Ramos de rastreamento remoto obsoletos adicionam bagunça e podem tornar comandos que listam ou inspecionam referências mais lentos. Pode-os durante o fetch:

git fetch --prune

Exclua ramos locais que já foram mesclados e não são mais necessários:

git branch --merged
git branch -d ramo-recurso-antigo

Deixe o Git executar a manutenção:

git maintenance run

Em fluxos de trabalho mais antigos, git gc ainda é útil:

git gc

Evite comandos de limpeza agressivos a menos que você saiba por que precisa deles. Por exemplo, expirar reflogs pode dificultar a recuperação de um reset ruim.

Torne git status Mais Barato

git status tem que inspecionar a árvore de trabalho. Se o diretório do seu projeto contém milhares de arquivos gerados ou de dependência, o status pode se tornar ruidoso e lento.

Use .gitignore para arquivos que o Git não deve considerar. Se um arquivo já é rastreado, .gitignore não impedirá o Git de rastreá-lo; você deve removê-lo do índice primeiro:

git rm --cached caminho/para/arquivo-gerado

Para repositórios muito grandes onde você precisa apenas de parte da árvore, o checkout esparso pode ajudar:

git sparse-checkout init --cone
git sparse-checkout set services/api docs

Isso mantém apenas os caminhos selecionados em sua árvore de trabalho. É útil em monorepos, mas sua equipe deve documentar os caminhos esparsos esperados para que os desenvolvedores não percam arquivos de que precisam.

Separe Fetch da Integração

git pull busca e então integra as alterações com merge ou rebase, dependendo da configuração. Quando um repositório é grande ou um ramo divergiu, geralmente é mais claro buscar primeiro:

git fetch origin
git log --oneline HEAD..origin/main
git merge origin/main

Isso não torna a transferência de rede menor por si só. Dá a você controle antes de alterar seu ramo de trabalho.

Conclusão Prática

Use clones rasos para jobs de curta duração, Git LFS para ativos grandes, .gitignore para arquivos gerados, poda para referências obsoletas e checkout esparso para árvores grandes onde você precisa apenas de um subconjunto. Mantenha o Git atualizado, mas não use ferramentas de integridade como git fsck como uma correção de desempenho, a menos que suspeite de corrupção no repositório.

Quando o Git estiver lento, anote o comando exato e onde o tempo é gasto: transferência de rede, processamento de objetos ou varredura da árvore de trabalho. Esse único detalhe geralmente aponta para a otimização correta.