O projeto de código aberto Git lançou a versão Git 2.49, com diversas novidades e correções de bugs de mais de 89 colaboradores, sendo 24 deles novos. Esta versão traz melhorias significativas e novas funcionalidades que prometem otimizar o trabalho de desenvolvedores. Vamos explorar os destaques desta atualização.
Empacotamento Acelerado com Name-Hash v2
O Git utiliza um modelo de armazenamento de objetos onde estes podem ser escritos individualmente (objetos “soltos”) ou agrupados em packfiles. Os packfiles são usados em diversas funções, como armazenamento local e transferência de dados entre repositórios Git.
Armazenar objetos em packfiles oferece vantagens sobre armazená-los individualmente. A busca por objetos é mais rápida no armazenamento em packfiles, pois o Git precisa fazer várias chamadas de sistema para encontrar, abrir, ler e fechar um objeto solto. Essas chamadas podem ser agilizadas com o cache de bloco do sistema operacional, mas o acesso pseudoaleatório dificulta o uso eficiente do cache.
Objetos soltos são comprimidos isoladamente, impedindo o armazenamento de objetos como deltas de outros objetos semelhantes. Por exemplo, pequenas mudanças em um blob grande resultam em objetos armazenados individualmente e comprimidos com zlib. No entanto, se grande parte do conteúdo permanecer inalterada, o Git pode comprimir ainda mais esses objetos, armazenando versões sucessivas como deltas de versões anteriores.
Para identificar bons candidatos para pares delta-base, o Git compara objetos que aparecem em paths similares, utilizando um “name hash”. Esse hash numérico e classificável pondera os 16 caracteres finais não-espaço em um filepath. Essa função, criada por Linus em 2006, agrupa funções com extensões semelhantes (.c
, .h
) ou arquivos movidos de um diretório para outro (a/foo.txt
para b/foo.txt
).
Aprimoramentos no Name-Hash v2 do Git 2.49
A implementação existente do name-hash pode gerar compressão inadequada quando muitos arquivos têm o mesmo nome base, mas conteúdos diferentes, como vários arquivos CHANGELOG.md
. Para resolver isso, o Git 2.49 introduz uma nova variante da função hash que considera mais da estrutura de diretórios.
Cada camada da hierarquia de diretórios recebe seu próprio hash, que é deslocado para baixo e combinado via XOR no hash geral. Isso cria uma função hash mais sensível ao path completo, não apenas aos 16 caracteres finais.
Essa melhoria pode otimizar o desempenho do empacotamento e reduzir o tamanho dos packs. Por exemplo, a nova função hash reduziu o tempo de reempacotamento de microsoft/fluentui de aproximadamente 96 segundos para 34 segundos, e o tamanho do pack resultante de 439 MiB para 160 MiB.
Embora essa funcionalidade ainda não seja compatível com os reachability bitmaps do Git, você pode experimentá-la com a flag --name-hash-version
nos comandos git repack
ou git pack-objects
.
Preenchimento de Blobs Históricos em Clones Parciais
Ao trabalhar em um clone parcial, você pode se deparar com uma saída inesperada ao executar o comando git blame.
Em um clone parcial criado com --filter=blob:none
, o repositório terá todas as árvores, commits e objetos de tag anotados, mas apenas o conjunto de blobs diretamente acessíveis a partir de HEAD. Isso significa que o clone local terá apenas os blobs necessários para um checkout completo na revisão mais recente, e qualquer blob histórico ausente será carregado do repositório original.
No exemplo acima, o comando blame
no arquivo README.md
exige todas as versões históricas do arquivo para calcular o diff em cada camada e determinar se uma revisão modificou uma linha. O Git carrega cada versão histórica individualmente, resultando em inchaço do armazenamento e desempenho insatisfatório.
O Novo Comando Git Backfill no Git 2.49
O Git 2.49 introduz o comando git backfill
, que pode preencher blobs históricos ausentes de um clone com --filter=blob:none
em pequenos lotes. Essas requisições utilizam a nova API path-walk (também introduzida no Git 2.49) para agrupar objetos que aparecem no mesmo path, resultando em melhor compressão delta nos packfiles enviados pelo servidor.
Como as requisições são enviadas em lotes, podemos preencher todos os blobs ausentes em poucos packs, em vez de um pack por blob. Após executar git backfill
, a experiência melhora significativamente.
Executar git backfill
logo após clonar um repositório com --filter=blob:none
não traz muitos benefícios, pois seria mais simples clonar o repositório sem o filtro de objeto. Ao usar a opção --sparse
do comando backfill (o padrão quando o recurso de sparse checkout está habilitado), o Git baixará apenas os blobs que aparecem dentro do sparse checkout, evitando objetos que não seriam extraídos de qualquer maneira.
Para experimentar, execute git backfill
em qualquer clone de um repositório com --filter=blob:none
usando o Git 2.49.
Outras melhorias notáveis incluem:
* Otimização zlib-ng: Git usa compressão zlib ao escrever objetos soltos ou dentro de packs. zlib-ng é um fork que otimiza o desempenho, incorporando conjuntos de instruções SIMD (como SSE2 e AVX2). No Git 2.49, você pode compilar o Git com zlib-ng, resultando em ganhos de velocidade de cerca de 25% ao imprimir o conteúdo de todos os objetos no repositório.
* Integração com Rust: Esta versão marca um marco importante com a inclusão de código Rust no projeto Git. Duas crates Rust, libgit-sys e libgit, fornecem wrappers de baixo e alto nível para uma pequena parte do código da biblioteca Git.
* Esforços de “libificação“: Esta versão continua o esforço de tornar o código do Git mais orientado a bibliotecas, substituindo funções que encerram o programa por funções que retornam um inteiro e permitindo que o chamador decida se deve sair ou não. Além disso, foram feitos esforços para eliminar avisos -Wsign-compare
, que ocorrem quando um valor assinado é comparado com um não assinado.
* Opção –expire-to no git gc: A opção --expire-to
no git repack
controla o comportamento de objetos inacessíveis que foram removidos do repositório. No Git 2.49, o comando git gc
agora expõe sua própria opção de linha de comando para usar --expire-to
, permitindo mover objetos removidos para o lado para fins de backup.
* Melhorias no help.autocorrect: O recurso de correção automática do Git agora interpreta o valor “1” para a configuração help.autocorrect
como outros comandos booleanos, e números positivos maiores que 1 como antes.
* Opção –revision no git clone: O Git 2.49 introduz a opção --revision
no comando git clone
, que permite buscar o histórico até a revisão especificada, independentemente de haver ou não um branch ou tag apontando para ela.
* Remoção de mecanismos de remote obsoletos: Os mecanismos antigos de configuração de remotes via arquivos em $GIT_DIR/branches
e $GIT_DIR/remote
foram removidos em favor do mecanismo baseado em configuração.
* Estagiários Outreachy: O projeto Git teve dois estagiários Outreachy que concluíram seus projetos: Usman Akinyemi adicionou suporte para incluir informações uname no user agent do Git ao fazer requisições HTTP, e Seyi Kuforiji converteu mais testes de unidade para usar o Clar testing framework.
O Restante do Iceberg
Esta é apenas uma amostra das mudanças na versão mais recente. Para mais informações, consulte as notas de lançamento da versão 2.49 ou qualquer versão anterior no repositório Git. Você pode aprender a criar listas suspensas no Excel e otimizar suas tarefas.
Este conteúdo foi auxiliado por Inteligência Artificiado, mas escrito e revisado por um humano.
Via The GitHub Blog