13 pontos por GN⁺ 2025-08-16 | 1 comentários | Compartilhar no WhatsApp
  • O projeto Git começou recentemente, de forma oficial, a resolver diretamente o problema de gerenciamento de arquivos grandes
  • O Git LFS é uma solução paliativa que impõe vários custos e dependência de fornecedor aos usuários
  • Com o recurso recente de partial clone, o próprio Git já consegue substituir a maior parte do papel do LFS
  • No futuro, uma nova solução chamada large object promisor também está sendo preparada para integração ao Git oficial
  • Com essas mudanças, a solução definitiva para o gerenciamento de arquivos grandes tende a convergir não para extensões externas, mas para o próprio Git

O problema dos arquivos grandes no Git e as mudanças em curso

  • Se existe uma grande nêmesis do Git, ela é justamente os arquivos grandes
  • Arquivos grandes incham os repositórios Git, reduzem a velocidade do git clone e também afetam negativamente a maioria dos ambientes de hospedagem

O surgimento do Git LFS e suas limitações

  • Em 2015, o GitHub lançou o Git LFS para contornar o problema dos arquivos grandes
  • Mas o próprio Git LFS adiciona nova complexidade e custos de armazenamento
  • A comunidade Git vinha refletindo discretamente sobre a causa raiz do problema dos arquivos grandes e, nas releases oficiais mais recentes do Git, começou a surgir uma nova direção para gerenciar arquivos grandes sem LFS

O que já dá para fazer hoje: substituir o Git LFS por partial clone

  • Como funciona o partial clone

    • Git LFS: os arquivos grandes ficam fora do repositório, e o trabalho acontece baixando apenas os arquivos necessários
    • Git partial clone (introduzido em 2017):
      • clona excluindo blobs acima de um tamanho desejado com a opção --filter
      • baixa do servidor apenas o arquivo grande necessário, somente quando preciso

      Ao usar partial clone, não é necessário baixar previamente [ativos binários grandes] durante o clone e o fetch, o que reduz o tempo de download e o uso de disco

  • Semelhanças entre partial clone e LFS

    • 1. Capacidade mínima no checkout: recebe apenas a versão mais recente e omite todo o histórico do arquivo
    • 2. Clonagem rápida: como não há transferência de arquivos grandes, o clone é mais veloz
    • 3. Configuração rápida: ao contrário do shallow clone, permite acesso ao histórico completo do projeto
  • Exemplo de uso do partial clone

    • Caso real de velocidade de clonagem e uso de disco em um repositório com muito histórico de arquivos PNG grandes:
      • com clone normal, quase 4 minutos e 1,3 GB ocupados
      • com partial clone e limite de blob de 100 KB, clonagem em 6 segundos e 49 MB ocupados
      • em relação ao original, melhora de 97% na velocidade de clonagem e redução de 96% no tamanho do checkout
  • Limitações do partial clone

    • Quando os dados filtrados são necessários (por exemplo, git diff, git blame, git checkout), o Git solicita os arquivos ao servidor
    • Essa é a mesma característica do Git LFS
    • Na prática, é raro haver necessidade de usar blame em arquivos binários

Os problemas do Git LFS

  • Alta dependência de fornecedor: a implementação do GitHub suporta apenas seus próprios servidores, gerando cobrança e dependência
  • Questão de custo: para armazenar 50 GB, o GitHub LFS custa US$ 40 por ano, enquanto o Amazon S3 custa US$ 13
  • Difícil de reverter: depois de migrar para LFS, não é possível voltar ao estado anterior sem reescrever o histórico
  • Custo contínuo de configuração: todos os colaboradores precisam instalar o LFS; se não instalarem, verão arquivos de metadados no lugar dos arquivos reais, o que gera confusão

Perspectivas futuras: Large Object Promisor

  • Arquivos grandes também geram problemas de custo para plataformas de hospedagem como GitHub e GitLab
  • O Git LFS reduz custos do servidor ao descarregar arquivos grandes para uma CDN
  • O que é Large Object Promisor?

    • No início deste ano, o Git fez merge oficial de um recurso chamado large object promisor
    • Esse recurso reduz a carga de armazenamento do lado do servidor de forma semelhante ao LFS, mas reduz bastante a complexidade para o usuário

      Esse esforço tem como objetivo melhorar o trabalho no lado do servidor, especialmente com blobs grandes que já estão compactados em formato binário
      É uma solução alternativa ao Git LFS
      Large Object Promisors, git-scm.com

  • Como funciona

    • 1. O usuário faz push de arquivos grandes para o host Git
    • 2. O host descarrega esses arquivos grandes para um promisor de backend
    • 3. No clone, o host Git fornece ao cliente as informações do promisor
    • 4. Quando necessário, o cliente baixa automaticamente os arquivos grandes a partir desse promisor
  • Situação atual de adoção e desafios

    • O promisor para objetos grandes ainda está em desenvolvimento, e parte do código foi integrada ao Git em março de 2025
    • Implementações adicionais e discussões sobre issues em aberto estão em andamento no GitLab e em outros lugares
    • Ainda será preciso tempo até a adoção em massa
    • Por enquanto, a dependência do Git LFS para armazenar arquivos grandes continua inevitável
    • Quando o promisor se popularizar, a expectativa é que até o GitHub passe a permitir upload de arquivos acima de 100 MB

Conclusão: o futuro dos arquivos grandes no Git é o próprio Git

  • O projeto Git continua pensando sem parar no problema dos arquivos grandes por você
  • No momento, ainda é necessário usar o Git LFS
  • Porém, com a evolução de partial clone e large object promisors, o Git LFS tende a se tornar gradualmente desnecessário, e em breve deve chegar a era em que será fácil gerenciar arquivos grandes apenas com Git
  • No futuro, a última barreira para usar arquivos grandes talvez seja apenas a ideia de colocar uma biblioteca de MP3 dentro do Git

1 comentários

 
GN⁺ 2025-08-16
Comentários do Hacker News
  • Até o antigo svn funcionava sem grandes problemas com um diretório de trabalho de 150 GB cheio de arquivos binários grandes, enquanto o git não. Fico curioso sobre por que o svn adota uma abordagem diferente do git para arquivos binários grandes, e se o git não poderia fazer o mesmo. Além disso, um recurso essencial ao lidar com dados binários é o bloqueio de arquivos: só uma pessoa deveria poder editar um arquivo específico, enquanto os demais ficam em modo somente leitura, para evitar merges confusos. Também não entendo bem se descarregar arquivos grandes para fora realmente melhora os problemas de desempenho ou confiabilidade. No fim, continua sendo apenas outro repositório; repositório é repositório. Esse offload parece mais uma forma de forjas públicas de git evitarem o custo de armazenar arquivos grandes

    • git e svn têm projetos completamente diferentes. O git é totalmente distribuído, então todo repositório precisa ter o histórico completo de todos os arquivos, e a ideia de bloqueio perde o sentido. Basta escolher o sistema de controle de versão adequado ao projeto; não significa que o git precise servir para tudo
  • Gostei do conceito de large object promisors. Se desse para conectar facilmente algo como S3, eu provavelmente migraria do LFS atual na hora. O S3 tem uma boa sinergia com versionamento de arquivos binários grandes. Com intelligent tiering, há a vantagem de mover automaticamente dados antigos para camadas de armazenamento mais baratas conforme envelhecem. Não me importo se levar meio dia para restaurar dados de 10 anos atrás

    • Penso o mesmo. Não entendo por que isso não foi o padrão desde o começo. Eu rodo meu próprio servidor pequeno de git LFS, e se o git desse suporte nativo a S3 eu já estaria pronto para trocar

    • No meu trabalho atual, fazemos cache dos objetos LFS em um bucket para reduzir custos. Em cada execução de PR, pegamos a lista de arquivos com git lfs ls-files, buscamos no gcp, salvamos os objetos localmente com git lfs checkout e depois usamos pull para baixar só o que faltou. Os arquivos ainda não cacheados são enviados de volta ao bucket com gcloud storage rsync. Do ponto de vista do desenvolvedor, não é preciso configuração extra: basta dar pull nos objetos novos, e a UI do GitHub também não fica confusa sobre o estado do repositório. Antes eu pensava em subir nosso próprio backend de LFS, mas esse método resolve o maior problema imediato. O GitHub cobrava tráfego demais toda vez que o CI baixava arquivos LFS, e por causa do limite de cache de 10 GB e da falta de compartilhamento entre branches, era preciso baixar tudo de novo sempre. Eu até queria pagar para aumentar o cache, mas nem essa opção existia. Para aplicar isso aos desenvolvedores, basta adicionar um git hook; é bem simples

    • S3 é algum serviço relacionado à Amazon?

  • O texto menciona vários pontos ruins do Git LFS, mas não concordo com a ideia de que haja vendor lock-in. Como o GitHub fornece cliente e servidor abertos, essa alegação me parece injusta. Ainda assim, o LFS não funciona em cenários offline/sneakernet, e embora isso não seja comum, vale mencionar. O large object promisor parece mover a complexidade do lado cliente do LFS para o servidor, então no fim parece só mudar onde a complexidade fica. Se a estrutura for um servidor git fazendo upload dos arquivos para um servidor LFS e um armazenamento de objetos, isso traz outros trade-offs. Fico curioso sobre o que aconteceria ao esconder remotos promisor em servidores git públicos e fazer uploads

    • Acho que LFS realmente deixa bastante a desejar. A implementação do servidor é ruim, e mistura o conteúdo do objeto com a forma de armazená-lo. O mecanismo de opt-in também é péssimo, então, se você usar sem pensar, acaba com um pequeno arquivo de texto em vez do arquivo real que queria. Não sei se a nova solução é melhor, mas que o LFS não é bom, isso é claro

    • Outro problema do Git LFS que descobri recentemente é que a migração contamina até o .gitattributes dos commits anteriores. Ou seja, numa sequência A→B→C, se um arquivo grande só foi adicionado ao LFS em C, então A e B também acabam contendo um .gitattributes apontando para arquivos LFS que nem existem. Isso acontece porque, no processo de migração, o .gitattributes é propagado para trás ao longo do histórico, sem verificar se a entidade de fato existe no commit atual

    • Antigamente o Git LFS não tinha suporte a SSH, então era obrigatório obter um certificado SSL, o que aumentava a barreira de entrada para quem fazia self-hosting em casa. Parece que o GitLab adicionou um patch com suporte a SSH recentemente

  • Em uma disciplina de engenharia de software, recomendaram não colocar arquivos grandes (mídia etc.) no Git, e sim em um repositório de artefatos, como o Artifactory. Aí você pode distribuí-los no formato de dependências snapshot, e deixar o sistema de build controlar automaticamente para baixar só a versão mais recente. Os arquivos antigos acumulados localmente pelos colegas também podem ser limpos na hora, só esvaziando o cache do sistema de build

    • Isso parece meio parecido com um submodule do git. Se submodules resolvessem o problema, imagino que as pessoas já usariam isso. Submodules do git também suportam shallow clone (link relacionado: https://stackoverflow.com/questions/2144406/how-to-make-shallow-git-submodules). Nunca enfrentei problema com arquivos grandes, então fico curioso sobre por que esse método não funcionaria. As desvantagens apontadas no SO não parecem tão sérias

    • Fico curioso se nessa disciplina também ensinam arquitetura de sistemas de CI/CD. Hoje em dia muitos engenheiros iniciantes não estão familiarizados com a arquitetura completa integrada a GitLab, Artifactory, CodeSonar, Anchore etc.

    • Essa abordagem também tem desvantagens. Ela exige credenciais extras no sistema de CI/CD ou para os desenvolvedores. Os commits também passam a envolver mais etapas: primeiro é preciso saber o ID do artefato, e, se você tentar automatizar isso com git hooks, no fim acaba chegando a uma complexidade parecida com a do git-lfs

  • Este texto está sendo injusto com o LFS. O LFS não é dependente do GitHub, e o protocolo também é aberto. As desvantagens do LFS são, em parte, inevitáveis por ser uma extensão do git, e os promisors na prática também são basicamente o mesmo conceito. A diferença é que, ao embutir isso no git, a UX melhora um pouco

    • Um repositório que já usou LFS fica permanentemente preso a ele. Para reduzir o espaço usado, é preciso apagar o repositório inteiro, e isso nem é claramente informado de forma oficial. Passei por esse problema na prática quando coloquei um grande arquivo compactado de banco de dados no LFS ao pesquisar estatísticas de GitHub na empresa
  • Isso não é a solução de verdade. O git LFS também é só uma gambiarra temporária, e mesmo colocar um filtro no clone não resolve o problema de forma fundamental. git clone é um dos primeiros comandos que todo mundo aprende, então ter de lembrar um filtro toda vez é ruim: se a pessoa errar, perde tempo, e mesmo se der certo, o repositório clonado pode não funcionar direito. No fim, a solução real exigiria mudar para algo mais parecido com o rsync, que busca os arquivos mais recentes de forma eficiente primeiro. O git não costuma fazer esse tipo de mudança fundamental

    • Concordo bastante. O git sempre “resolve” os problemas adicionando mais uma flag, mas a maioria dos usuários nem conhece esses recursos. Melhorar o padrão em si permitiria resolver isso sem quebrar compatibilidade

    • o repositório clonado pode não funcionar direito
      Na prática, o que fica faltando é só o histórico dos blobs

    • Você diz que isso é algo que o rsync resolveu, mas como isso seria na prática? Não o algoritmo, e sim o que realmente apareceria no sistema de arquivos local quando o usuário rodasse git clone

    • Se a maior parte do volume do repositório estiver nas revisões antigas, então uma abordagem estilo rsync, que prioriza a versão mais recente, é a solução mais adequada para a maioria dos usuários

  • Fico muito feliz em ver suporte a arquivos grandes chegando ao core do Git. Mesmo sendo uma solução externa, no fim a estrutura de opt-in é parecida. Como eu queria reduzir ao máximo o número de comandos e tornar tudo mais seamless, desenhei a API limitada aos filtros smudge/clean no arquivo .gitattributes. Também trabalhei diretamente com a Atlassian e a Microsoft para evitar vendor lock-in, e a Atlassian ajudou bastante com a API de bloqueio de arquivos. O LFS é fornecido como open source com suporte compatível em três hosts

  • Estamos desenvolvendo o oxen para resolver problemas que tivemos com git e git-lfs. Ele mantém a interface do git, mas funciona muito mais rápido em ambientes com arquivos grandes e monorepos com milhões de arquivos. Oferecemos CLI e servidor open source; se tiver interesse, agradeço feedback
    https://github.com/Oxen-AI/Oxen

  • O próprio formato de armazenamento do git também precisaria de uma reformulação, mais parecida com ferramentas modernas de backup como restic ou borg, usando content-defined chunking para arquivos e diretórios

  • Entre os pontos fracos do GitLFS, faltou mencionar a questão da autenticação: se você não usar SSH-agent, pode precisar autenticar várias vezes até para um único push. Pela minha experiência, já aconteceu de precisar fazer isso duas ou três vezes ou mais