J'essaie de comprendre comment git calcule le hachage des références.
$ git ls-remote https://github.com/git/git
....
29932f3915935d773dc8d52c292cadd81c81071d refs/tags/v2.4.2
9eabf5b536662000f79978c4d1b6e4eff5c8d785 refs/tags/v2.4.2^{}
....
Clonez le référentiel localement. Vérifier la refs/tags/v2.4.2^{}
ref par sha
$ git cat-file -p 9eabf5b536662000f79978c4d1b6e4eff5c8d785
tree 655a20f99af32926cbf6d8fab092506ddd70e49c
parent df08eb357dd7f432c3dcbe0ef4b3212a38b4aeff
author Junio C Hamano <[email protected]> 1432673399 -0700
committer Junio C Hamano <[email protected]> 1432673399 -0700
Git 2.4.2
Signed-off-by: Junio C Hamano <[email protected]>
Copiez le contenu décompressé afin que nous puissions le hacher (AFAIK git utilise la version non compressée lors du hachage)
git cat-file -p 9eabf5b536662000f79978c4d1b6e4eff5c8d785 > fi
Disons SHA-1 le contenu en utilisant la propre commande de hachage de git
git hash-object fi
3cf741bbdbcdeed65e5371912742e854a035e665
Pourquoi la sortie n'est pas [9e]abf5b536662000f79978c4d1b6e4eff5c8d785
? Je comprends les deux premiers caractères (9e
) est la longueur en hexadécimal. Comment dois-je hacher le contenu de fi
pour obtenir la référence git abf5b536662000f79978c4d1b6e4eff5c8d785
?
Comme décrit dans " Comment est formé git commit sha1 ", la formule est:
(printf "<type> %s\0" $(git cat-file <type> <ref> | wc -c); git cat-file <type> <ref>)|sha1sum
Dans le cas de la validation 9eabf5b536662000f79978c4d1b6e4eff5c8d785 (qui est v2.4.2^{}
, et qui faisait référence à un arbre):
(printf "commit %s\0" $(git cat-file commit 9eabf5b536662000f79978c4d1b6e4eff5c8d785 | wc -c); git cat-file commit 9eabf5b536662000f79978c4d1b6e4eff5c8d785 )|sha1sum
Cela donnera 9eabf5b536662000f79978c4d1b6e4eff5c8d785.
Comme le ferait:
(printf "commit %s\0" $(git cat-file commit v2.4.2{} | wc -c); git cat-file commit v2.4.2{})|sha1sum
(toujours 9eabf5b536662000f79978c4d1b6e4eff5c8d785)
De même, le calcul du SHA1 de la balise v2.4.2 serait:
(printf "tag %s\0" $(git cat-file tag v2.4.2 | wc -c); git cat-file tag v2.4.2)|sha1sum
Cela donnerait 29932f3915935d773dc8d52c292cadd81c81071d.
Il y a un peu de confusion ici. Git utilise différents types d'objets: blobs, arbres et commits. La commande suivante:
git cat-file -t <hash>
Vous indique le type d'objet pour un hachage donné. Ainsi, dans votre exemple, le hachage 9eabf5b536662000f79978c4d1b6e4eff5c8d785 correspond à un objet commit.
Maintenant, comme vous vous en êtes rendu compte, exécutez ceci:
git cat-file -p 9eabf5b536662000f79978c4d1b6e4eff5c8d785
Vous donne le contenu de l'objet en fonction de son type (dans ce cas, un commit).
Mais ça:
git hash-object fi
... calcule le hachage pour un blob dont le contenu est la sortie de la commande précédente (dans votre exemple), mais cela pourrait être autre chose (comme "bonjour le monde!"). Ici, essayez ceci:
echo "blob 277\0$(cat fi)" | shasum
La sortie est la même que la commande précédente. C'est essentiellement ainsi que Git hache un blob. Donc en hachant fi, vous générez un objet blob. Mais comme nous l'avons vu, 9eabf5b536662000f79978c4d1b6e4eff5c8d785 est un commit, pas un blob. Donc, vous ne pouvez pas hacher fi tel quel pour obtenir le même hachage.
Le hachage d'un commit est basé sur plusieurs autres informations qui le rendent unique (comme le committer, l'auteur, la date, etc.). L'article suivant vous indique exactement de quoi est composé un hachage de validation:
Vous pouvez donc obtenir le même hachage en fournissant toutes les données spécifiées dans l'article avec les mêmes valeurs exactes que celles utilisées dans le commit d'origine.
Cela pourrait également être utile: