Os hashes SHA1 armazenados nos objetos da árvore (retornados por git ls-tree
) não correspondem aos hashes SHA1 do conteúdo do arquivo (retornados por sha1sum
)
$ git cat-file blob 4716ca912495c805b94a88ef6dc3fb4aff46bf3c | sha1sum
de20247992af0f949ae8df4fa9a37e4a03d7063e -
Como o git calcula hashes de arquivos? Comprime o conteúdo antes de calcular o hash?
Respostas:
$ echo -e 'blob 14\0Hello, World!' | shasum 8ab686eafeb1f44702738c8b0f24f2567c36da6d
Fonte: http://alblue.bandlem.com/2011/08/git-tip-of-week-objects.html
fonte
echo 'Hello, World!' | git hash-object --stdin
. Opcionalmente, você pode especificar--no-filters
para garantir que nenhuma conversão crlf aconteça ou especificar--path=somethi.ng
para permitir que o git use o filtro especificado viagitattributes
(também @ user420667). E-w
para realmente enviar o blob para.git/objects
(se você estiver em um repositório git).echo -e 'blob 16\0Hello, \r\nWorld!' | shasum
==echo -e 'Hello, \r\nWorld!' | git hash-object --stdin --no-filters
e será também equivalente com\n
e 15.echo
anexa uma nova linha à saída, que também é passada para o git. É por isso que seus 14 caracteres. Para usar o eco sem uma nova linha, escrevaecho -n 'Hello, World!'
Estou apenas expandindo a resposta
@Leif Gruenwoldt
e detalhando o que está na referência fornecida por@Leif Gruenwoldt
Faça Você Mesmo..
Como o GIT calcula seus hashes de confirmação
O texto
blob⎵
é um prefixo constante e\0
também é constante e é oNULL
caractere. O<size_of_file>
e<contents_of_file>
varia dependendo do arquivo.Consulte: Qual é o formato do arquivo de um objeto de confirmação git?
E isso é tudo!
Mas espere! , você percebeu que
<filename>
não é um parâmetro usado para o cálculo de hash? Dois arquivos podem ter o mesmo hash se o conteúdo for indiferente à data e hora em que foram criados e ao nome. Essa é uma das razões pelas quais o Git manipula movimentos e renomeia melhor do que outros sistemas de controle de versão.Faça Você Mesmo (Ext)
Nota:
O link não menciona como o
tree
objeto está em hash. Eu não tenho certeza do algoritmo e dos parâmetros, no entanto, pela minha observação, provavelmente calcula um hash com base em todos osblobs
etrees
(provavelmente seus hashes) que ele contémfonte
SHA1("blob" + <size_of_file>
- existe um caractere de espaço adicional entre blob e tamanho? O tamanho é decimal? É o prefixo zero?git hash-object
Esta é uma maneira rápida de verificar seu método de teste:
Resultado:
onde
sha1sum
está no GNU Coreutils.Então, tudo se resume a entender o formato de cada tipo de objeto. Já cobrimos o trivial
blob
, aqui estão os outros:fonte
$(printf "\0$s" | wc -c)
. Observe o caractere vazio adicionado. Ou seja, se a string for 'abc' com o caractere vazio adicionado na frente, o comprimento renderá 4, não 3. Em seguida, os resultados com sha1sum corresponderão ao objeto hash git.Com base na resposta de Leif Gruenwoldt , aqui está um substituto da função shell para
git hash-object
:Teste:
fonte
Eu precisava disso para alguns testes de unidade no Python 3, então pensei em deixá-lo aqui.
Eu mantenho
\n
finais de linha em todos os lugares, mas em algumas circunstâncias o Git também pode estar alterando seus finais de linha antes de calcular esse hash, para que você possa precisar de um.replace('\r\n', '\n')
também.fonte