Como o git armazena arquivos?

Eu acabei de começar a aprender git e para isso comecei a ler o Git Community Book , e neste livro eles dizem que o SVN e o CVS armazenam a diferença entre os arquivos e que o git armazena um instantâneo de todos os arquivos.

Mas eu realmente não entendi o que eles querem dizer com o instantâneo. O git realmente faz uma cópia de todos os arquivos em cada commit porque foi o que eu entendi da explicação deles.

PS: Se alguém tiver alguma fonte melhor para aprender git eu agradeceria.

O Git inclui para cada commit uma cópia completa de todos os arquivos, exceto que, para o conteúdo já presente no repository do Git, o instantâneo simplesmente apontará para o dito conteúdo em vez de duplicá-lo.
Isso também significa que vários arquivos com o mesmo conteúdo são armazenados apenas uma vez.

Portanto, um instantâneo é basicamente um commit, referindo-se ao conteúdo de uma estrutura de diretórios.

Algumas boas referências são:

  • gitref.org

Você diz ao Git que quer salvar um snapshot do seu projeto com o comando git commit e basicamente registra um manifesto de como todos os arquivos no seu projeto se parecem naquele momento

  • git imersão

O laboratório 12 ilustra como obter instantâneos anteriores

  • ” Você poderia ter inventado o git (e talvez você já tenha!) ”

  • O que é um git “Snapshot”?

  • Aprenda GitHub


O livro de programação tem a descrição mais abrangente de um instantâneo:

A principal diferença entre o Git e qualquer outro VCS (Subversion e amigos incluídos) é a forma como o Git pensa sobre seus dados.
Conceitualmente, a maioria dos outros sistemas armazena informações como uma lista de alterações baseadas em arquivos. Esses sistemas (CVS, Subversion, Perforce, Bazaar e assim por diante) pensam nas informações que mantêm como um conjunto de arquivos e as alterações feitas em cada arquivo ao longo do tempo.

VCS baseado em delta

O Git não pensa ou armazena seus dados dessa maneira. Em vez disso, o Git pensa em seus dados mais como um conjunto de instantâneos de um mini sistema de arquivos.
Toda vez que você confirma, ou salva o estado do seu projeto no Git, ele basicamente tira uma foto de como todos os seus arquivos se parecem naquele momento e armazena uma referência àquele instantâneo.
Para ser eficiente, se os arquivos não forem alterados, o Git não armazenará o arquivo novamente – apenas um link para o arquivo idêntico anterior que ele já armazenou.
Git pensa em seus dados mais como abaixo:

VCS baseado em instantâneo

Essa é uma distinção importante entre o Git e quase todos os outros VCSs. Ele faz o Git reconsiderar quase todos os aspectos do version control que a maioria dos outros sistemas copiou da geração anterior. Isso torna o Git mais parecido com um mini sistema de arquivos com algumas ferramentas incrivelmente poderosas construídas sobre ele, em vez de simplesmente um VCS.


Jan Hudec acrescenta este comentário importante :

Embora isso seja verdade e importante no nível conceitual, NÃO é verdade no nível de armazenamento.
O Git usa deltas para armazenamento .
Não só isso, mas é mais eficiente do que qualquer outro sistema. Como ele não mantém o histórico por arquivo, quando ele quer fazer a compactação delta , ele pega cada blob, seleciona alguns blobs que provavelmente são semelhantes (usando heurística que inclui a aproximação mais próxima da versão anterior e de alguns outros), tenta Gere os deltas e escolhe o menor. Desta forma, pode (muitas vezes, depende da heurística) tirar proveito de outros arquivos semelhantes ou versões mais antigas que são mais semelhantes do que o anterior. O parâmetro “pack window” permite o desempenho de negociação para a qualidade de compression delta. O padrão (10) geralmente dá resultados decentes, mas quando o espaço é limitado ou para acelerar transferências de rede, o git gc --aggressive usa o valor 250, o que o faz rodar muito devagar, mas fornece compression extra para os dados do histórico.

O Git armazena logicamente cada arquivo sob seu SHA1. Isso significa que, se você tiver dois arquivos com exatamente o mesmo conteúdo em um repository (ou se você renomear um arquivo), apenas uma cópia será armazenada.

Mas isso também significa que quando você modifica uma pequena parte de um arquivo e confirma, outra cópia do arquivo é armazenada. A maneira como o git resolve isso é usando arquivos de pacote. De vez em quando, todos os arquivos “soltos” (na verdade, não apenas arquivos, mas objects contendo informações de confirmação e diretório também) de um repository são reunidos e compactados em um arquivo de pacote. O arquivo do pacote é compactado usando zlib. E arquivos semelhantes também são comprimidos em delta.

O mesmo formato também é usado ao puxar ou empurrar (pelo menos com alguns protocolos), então esses arquivos não precisam ser recompactados novamente.

O resultado disso é que um repository git, contendo toda a cópia de trabalho não compactada, arquivos recentes descomprimidos e arquivos antigos compactados é geralmente relativamente pequeno, menor que o dobro do tamanho da cópia de trabalho. E isso significa que é menor que o repository SVN com os mesmos arquivos, mesmo que o SVN não armazene o histórico localmente.

As respostas acima são bem interessantes, mas eu gostaria de adicionar mais um pequeno conceito conhecido como codificação delta. A eficiência é salva até que o arquivo do pacote seja gravado. Os objects soltos são gravados no formato compactado, mas não delta, no momento de cada consolidação.