¿Cómo crea Git hash de commit únicos, principalmente los primeros caracteres?

Me resulta difícil entender cómo Git crea hashes totalmente únicos que no están permitidos ni siquiera en los primeros 4 caracteres. Puedo invocar compromisos en Git Bash usando solo los primeros cuatro caracteres. ¿Se decide específicamente en el algorithm que los primeros caracteres son "ultra" -unique y que nunca entrarán en conflicto con otros hashes similares, o el algorithm genera cada parte del hash de la misma manera?

Git usa la siguiente información para generar el sha-1:

  • El tree fuente de la confirmación (que se desennetworkinga a todos los subtreees y blobs)
  • El padre comete sha1
  • La información del autor
  • La información del committer (¡correcto, esos son diferentes!)
  • El post de confirmación

(en la explicación completa, mira aquí ).

Git NO garantiza que los primeros 4 caracteres sean únicos. En el capítulo 7 del Pro Git Book está escrito:

Git puede encontrar una abreviatura corta y única para sus valores de SHA-1. Si pasa –abbrev-commit al command git log, la salida usará valores más cortos pero los mantendrá únicos; de forma pnetworkingeterminada utiliza siete caracteres, pero los hace más largos si es necesario para mantener el SHA-1 inequívoco:

Así que Git solo hace la abreviatura todo el time que sea necesario para seguir siendo único. Incluso notan que:

Generalmente, de ocho a diez caracteres son más que suficientes para ser únicos dentro de un proyecto.

Como ejemplo, el kernel de Linux, que es un proyecto bastante grande con más de 450k commits y 3.6 millones de objects, no tiene dos objects cuyos SHA-1 se superpongan más que los primeros 11 caracteres.

Así que de hecho solo dependen de la gran improbabilidad de tener exactamente el mismo (X primeros caracteres de a) sha.

Tenga en count que después del episodio all shattenetworking.io (donde Google logró una colisión SHA1), el formatting de 20 bytes no estará allí para siempre.

Un primer paso para eso es replace el unsigned char sha1[20] que es un código en toda la base de código Git por un object genérico cuya definición podría cambiar en el futuro (SHA2 ?, Blake2 , …)

Ver commit e86ab2c (21 de febrero de 2017) por brian m. carlson ( bk2204 ) .

Convierta los usos restantes de unsigned char [20] a struct object_id .

Ese es un ejemplo de un esfuerzo continuo iniciado con commit 5f7817c (13 Mar 2015) por Brian m. carlson ( bk2204 ) , para v2.5.0-rc0, en 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]; }; 

Y no olvide que, incluso con SHA1, los 4 primeros caracteres ya no son suficientes para garantizar la singularidad, como explico en " ¿Qué cantidad de git sha se considera generalmente necesaria para identificar de manera única un cambio en una base de código dada? ".