Pelo que entendi, quando o Git atribui um hash SHA1 a um arquivo, esse SHA1 é exclusivo do arquivo com base em seu conteúdo.
Como resultado, se um arquivo for movido de um repositório para outro, o SHA1 do arquivo permanecerá o mesmo, pois seu conteúdo não foi alterado.
Como o Git calcula o resumo SHA1? Faz isso no conteúdo completo do arquivo descompactado?
Eu gostaria de emular a atribuição de SHA1 fora do Git.
Respostas:
É assim que o Git calcula o SHA1 para um arquivo (ou, em termos do Git, um "blob"):
Assim, você pode computar facilmente sem ter o Git instalado. Observe que "\ 0" é o byte nulo, não uma seqüência de dois caracteres.
Por exemplo, o hash de um arquivo vazio:
Outro exemplo:
Aqui está uma implementação do Python:
fonte
TypeError: Unicode-objects must be encoded before hashing
exceção na primeiras.update()
linha.s.update(("blob %u\0" % filesize).encode('utf-8'))
para evitar oTypeError
.Um pouco de guloseima: com casca
fonte
echo -en "blob ${#CONTENTS}\0$CONTENTS" | sha1sum
com a saída degit hash-object path-to-file
e eles produzem resultados diferentes. No entanto,echo -e ...
produz os resultados corretos, exceto que há um final-
( nãogit hash-object
produz caracteres finais). É com isso que eu deveria me preocupar?-
é usadosha1sum
se ele computou o hash do stdin e não de um arquivo. Nada para se preocupar. Porém-n
, o estranho é que isso deve suprimir a nova linha normalmente anexada por eco. Por acaso, seu arquivo tem uma última linha vazia, que você esqueceu de adicionar à suaCONTENTS
variável?cat file | sha1sum
em vez desha1sum file
(mais processos e tubulações embora)Você pode criar uma função bash shell para calculá-la facilmente se não tiver o git instalado.
fonte
(stat --printf="blob %s\0" "$1"; cat "$1") | sha1sum -b | cut -d" " -f1
.Dê uma olhada na página de manual do git-hash-object . Você pode usá-lo para calcular o hash git de qualquer arquivo em particular. Eu acho que o git alimenta mais do que apenas o conteúdo do arquivo no algoritmo de hash, mas não sei ao certo, e se ele alimenta dados extras, não sei o que é.
fonte
Esta é uma solução em F #.
fonte
Implementação completa do Python3:
fonte
Em Perl:
Como um comando shell:
fonte
E no Perl (veja também Git :: PurePerl em http://search.cpan.org/dist/Git-PurePerl/ )
fonte
Usando Ruby, você poderia fazer algo assim:
fonte
Um pequeno script Bash que deve produzir uma saída idêntica a
git hash-object
:fonte
Em JavaScript
fonte
É interessante notar que, obviamente, o Git adiciona um caractere de nova linha ao final dos dados antes de serem hash. Um arquivo contendo nada além de "Hello World!" obtém um hash de blob de 980a0d5 ..., o mesmo que este:
fonte
git hash-object
. Observe que fazerecho "Hello World!" | git hash-object --stdin
give980a0d5...
, enquanto estiver usando,echo -n
dá um hashc57eff5...
.