web-dev-qa-db-fra.com

Comment Git crée-t-il des hachages de validation uniques, principalement les premiers caractères?

J'ai du mal à comprendre comment Git crée des hachages entièrement uniques qui ne sont pas autorisés à être les mêmes, même dans les 4 premiers caractères. Je peux appeler des commits dans Git Bash en utilisant uniquement les quatre premiers caractères. Est-il spécifiquement décidé dans l'algorithme que les premiers caractères sont "ultra" -uniques et n'entreront jamais en conflit avec d'autres hachages similaires, ou l'algorithme génère-t-il chaque partie du hachage de la même manière?

22
Ben

Git utilise les informations suivantes pour générer le sha-1:

  • L'arbre source du commit (qui se dévoile à tous les sous-arbres et blobs)
  • Le parent valide sha1
  • Informations sur l'auteur (avec horodatage)
  • Les informations sur le committer (à droite, elles sont différentes !, également avec horodatage)
  • Le message de validation

(sur l'explication complète; regardez ici ).

Git NE garantit PAS que les 4 premiers caractères seront uniques. En chapitre 7 du livre Pro Git il est écrit:

Git peut trouver une abréviation courte et unique pour vos valeurs SHA-1. Si vous passez --abbrev-commit à la commande git log, la sortie utilisera des valeurs plus courtes mais les gardera uniques; il utilise par défaut sept caractères mais les rallonge si nécessaire pour garder le SHA-1 sans ambiguïté:

Donc Git fait juste l'abréviation aussi longtemps que nécessaire pour rester unique. Ils notent même que:

En règle générale, huit à dix caractères sont plus que suffisants pour être uniques dans un projet.

Par exemple, le noyau Linux, qui est un projet assez important avec plus de 450 000 validations et 3,6 millions d'objets, n'a pas deux objets dont les SHA-1 chevauchent plus que les 11 premiers caractères.

Donc, en fait, ils dépendent simplement de la grande improbabilité d'avoir exactement les mêmes (X premiers caractères de a) sha.

36
Chris Maes

Avril 2017: Attention, après le tout épisode shattered.io (où une collision SHA1 a été réalisée par Google), le format 20 octets ne sera plus là pour toujours.

Une première étape pour cela consiste à remplacer unsigned char sha1[20] Qui est du code dur partout dans la base de code Git par un objet générique dont la définition pourrait changer à l'avenir (SHA2 ?, Blake2 , .. .)

Voir commit e86ab2c (21 février 2017) par brian m. Carlson (bk2204) .

Convertissez les utilisations restantes de unsigned char [20] En struct object_id.

C'est un exemple d'un effort continu commencé avec commit 5f7817c (13 mars 2015) par brian m. Carlson (bk2204) , pour v2.5.0- rc0, dans cache.h :

/* The length in bytes and in hex digits of an object name (SHA-1 value). */
#define GIT_SHA1_RAWSZ 20
#define GIT_SHA1_HEXSZ (2 * GIT_SHA1_RAWSZ)

struct object_id {
    unsigned char hash[GIT_SHA1_RAWSZ];
};

Et n'oubliez pas que, même avec SHA1, les 4 premiers caractères ne suffisent plus pour garantir l'unicité, comme je l'explique dans " Quelle est la taille d'un git sha en général considéré nécessaire pour identifier de manière unique un changement dans une base de code donnée? ".


Mise à jour décembre 2017 avec Git 2.16 (T1 2018): cet effort pour prendre en charge une alternative SHA est en cours: voir " Pourquoi Git n'utilise-t-il pas un SHA plus moderne? ".

Vous pourrez utiliser un autre hachage: SHA1 n'est plus le seul pour Git.

Mise à jour 2018-2019 : le choix a été fait dans Git 2.19+: SHA-256.
Voir " transition de fonction de hachage ".

Ce n'est pas encore actif (ce qui signifie que git 2.21 utilise toujours SHA1), mais le code est en cours de prise en charge dans le futur SHA-256.


Avec Git 2.26 (T1 2020), le travail continue et utilise "struct object_id" Pour remplacer l'utilisation de" char *sha1 "

Voir commit 2fecc48 , commit 6ac976 , commit b99b6bc , commit 63f4a7f , commit e31c71 , commit 500e4f2 , commit f66d4e , commit a93c141 , commit 3f83fd5 , commit 0763671 (24 février 2020) par Jeff King (peff) .
(Fusionné par Junio ​​C Hamano - gitster - in commit e8e7184 , 05 mars 2020)

packfile : drop nth_packed_object_sha1()

Signé par: Jeff King

Il était une fois, nth_packed_object_sha1() était le principal moyen d'obtenir le oid de la position d'index d'un packfile.
Mais ces jours-ci, nous avons le wrapper nth_packed_object_id() plus sûr pour tous les types, et tous les appelants ont été convertis.

Laissons tomber la version "sha1" (Transformant le wrapper plus sûr en une seule fonction) afin que personne ne soit tenté d'introduire de nouveaux appelants.

4
VonC