Como o git armazena arquivos?

225

Comecei a aprender o 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 arquivos e que o git armazena uma captura instantânea de todos os arquivos.

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

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

mteffaha
fonte
20
Aqui está um post brilhante que explica em detalhes como o git funciona. O que você está procurando é provavelmente o § sobre o banco de dados de objetos.
greg0ire
Excelente artigo que contém links para outros ótimos recursos. Eu me divirto com isso por algumas horas.
Mihai
2
Achei isso muito bom artigo descrevendo git de fora para dentro: maryrosecook.com/blog/post/git-from-the-inside-out
Sumudu

Respostas:

275

O Git inclui para cada confirmação uma cópia completa de todos os arquivos, exceto que, para o conteúdo já presente no repositório Git, o instantâneo simplesmente apontará para o 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 uma confirmação, referindo-se ao conteúdo de uma estrutura de diretórios.

Algumas boas referências são:

Você diz ao Git que deseja salvar um instantâneo do seu projeto com o comando git commit e, basicamente, registra um manifesto da aparência de todos os arquivos do seu projeto naquele momento

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


O livro progit possui 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 maneira 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 etc.) pensam nas informações que eles mantêm como um conjunto de arquivos e nas alterações feitas em cada arquivo ao longo do tempo.

VCS baseados 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, basicamente tira uma foto da aparência de todos os seus arquivos naquele momento e armazena uma referência a esse instantâneo.
Para ser eficiente, se os arquivos não foram alterados, o Git não armazena o arquivo novamente - apenas um link para o arquivo idêntico anterior que ele já armazenou.
O Git pensa em seus dados mais como abaixo:

VCS baseados em instantâneo

Essa é uma distinção importante entre o Git e quase todos os outros VCSs. Isso faz com que o Git reconsidere quase todos os aspectos do controle de versão 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 importante comentário :

Embora isso seja verdadeiro e importante no nível conceitual, NÃO é verdadeiro no nível de armazenamento.
O Git usa deltas para armazenamento .
Não apenas isso, mas é mais eficiente do que qualquer outro sistema. Como ele não mantém o histórico por arquivo, quando deseja fazer a compactação delta, pega cada blob, seleciona alguns blobs que provavelmente são semelhantes (usando heurísticas que incluem a aproximação mais próxima da versão anterior e outras), tenta gerar os deltas e escolhe o menor. Dessa forma, ele pode (muitas vezes, depende da heurística) tirar proveito de outros arquivos semelhantes ou versões mais antigas que são mais parecidas que as anteriores. O parâmetro "pack window" permite desempenho de negociação para qualidade de compactação delta. O padrão (10) geralmente fornece resultados decentes, mas quando o espaço é limitado ou para acelerar as transferências de rede, o git gc --aggressivevalor 250 é usado, o que o torna muito lento, mas fornece compactação extra para os dados do histórico.

VonC
fonte
4
@JanHudec good point. Incluímos seu comentário na resposta para obter mais visibilidade.
VonC
1
Alguém conhece o termo de ciência da computação para o padrão de armazenamento semelhante ao Git, também conhecido como armazenamento de valor baseado em hash? (ou algo similar)
Joannes Vermorel
34
No contexto da pergunta real do PO, o primeiro parágrafo parece realmente enganador. Não é até chegar ao último parágrafo que nós aprendemos que, oh sim, fato Git faz "store [...] diferenças entre os arquivos. Realmente desejo que a informação foi marcado em cima e não enterrado tão profundamente. Dito isto, graças à menos incluindo a algum lugar história real em sua resposta;)
Josh O'Brien
1
@NickVolynkin Great! Fico feliz que essas respostas estejam encontrando um público maior.
VonC 21/08/2015
1
Outro bom livro: Git From The Bottom Up: ftp.newartisans.com/pub/git.from.bottom.up.pdf
Jonas Berlin
46

O Git armazena logicamente cada arquivo em seu SHA1. O que isso significa é que se você tiver dois arquivos com exatamente o mesmo conteúdo em um repositório (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 "frouxos" (na verdade, não apenas arquivos, mas objetos que também contêm informações de confirmação e diretório) de um repositório são reunidos e compactados em um arquivo de pacote. O arquivo do pacote é compactado usando zlib. E arquivos semelhantes também são compactados em delta.

O mesmo formato também é usado ao puxar ou empurrar (pelo menos com alguns protocolos), para que esses arquivos não precisem ser recomprimidos novamente.

O resultado disso é que um repositório git, contendo toda a cópia de trabalho descompactada, arquivos recentes não compactados e arquivos antigos compactados, é geralmente relativamente pequeno, duas vezes menor que o tamanho da cópia de trabalho. E isso significa que é menor que o repositório SVN com os mesmos arquivos, embora o SVN não armazene o histórico localmente.

svick
fonte
1
ah, tão mercurial é mais eficiente em termos de espaço #
Ben