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.