tag - ¿Cuánto de un git sha*se considera*generalmente*necesario para identificar de manera única un cambio en una base de código dada?
git push tag (5)
Esta pregunta ha sido respondida, pero para cualquiera que esté buscando la matemática detrás, se llama " Problema de cumpleaños" ( Wikipedia ).
Se trata de la probabilidad de tener 2 (o más) personas del grupo de N personas para tener cumpleaños en el mismo día del año. Lo cual es analógico a la probabilidad de 2 (o más) commits de git del repositorio que tiene N commits en total con el mismo prefijo hash de longitud X.
Mire la tabla de probabilidad . Por ejemplo, para la cadena hexadecimal de hash de longitud 8, la probabilidad de tener una colisión alcanza el 1% cuando el repositorio tiene aproximadamente 9300 elementos (se compromete git). Para 110 000 confirmaciones, la probabilidad es del 75%. Pero si tiene cadena hexadecimal hash de longitud 12, la probabilidad de colisión en 100 000 confirmaciones es inferior al 0,1%.
Si vas a construir, digamos, una estructura de directorio donde un directorio se llama para una confirmación en un repositorio de Git, y quieres que sea lo suficientemente corto para que tus ojos no sangren, pero lo suficientemente largo como para que la posibilidad de colisionar sería insignificante, ¿qué parte de la subcadena SHA generalmente se requiere?
Digamos que quiero identificar de manera única este cambio: https://github.com/wycats/handlebars.js/commit/e62999f9ece7d9218b9768a908f8df9c11d7e920
Puedo usar tan poco como los primeros cuatro caracteres: https://github.com/wycats/handlebars.js/commit/e629
Pero siento que eso sería arriesgado. Pero al sustentar una base de código que, en un par de años, podría tener, digamos, 30k cambios, ¿cuáles son las posibilidades de colisión si uso 8 caracteres? 12? ¿Hay algún número que generalmente se considere aceptable para este tipo de cosas?
Esta pregunta se responde en realidad en el Capítulo 7 del libro de Pro Git :
Generalmente, de ocho a diez caracteres son más que suficientes para ser únicos dentro de un proyecto. Uno de los mayores proyectos de Git, el kernel de Linux, está empezando a necesitar 12 caracteres de los 40 posibles para mantenerse únicos.
7 dígitos es el valor predeterminado de Git para un SHA corto, por lo que está bien para la mayoría de los proyectos. El equipo de Kernel ha aumentado el suyo varias veces, como se mencionó, porque tienen varios cientos de miles de compromisos. Entonces, para tus ~ 30k commits, 8 o 10 dígitos deberían estar perfectamente bien.
Esto se conoce como el problema del cumpleaños.
Para probabilidades inferiores a 1/2, la probabilidad de una colisión puede aproximarse a
p ~ = (n 2 ) / (2m)
Donde n es el número de elementos ym es el número de posibilidades para cada artículo.
El número de posibilidades para una cadena hex es 16 c donde c es la cantidad de caracteres.
Entonces para 8 caracteres y 30,000 confirmaciones
30K ~ = 2 15
p ~ = (n 2 ) / (2 m) ~ = ((2 15 ) 2 ) / (2 * 16 8 ) = 2 30/2 33 = ⅛
Incrementándolo a 12 caracteres
p ~ = (n 2 ) / (2 m) ~ = ((2 15 ) 2 ) / (2 * 16 12 ) = 2 30/2 49 = 2 -19
La versión 2.11 de Git (o quizás 2.12?) Contendrá una función que adapta el número de caracteres utilizados en los identificadores cortos (por ejemplo, git log --oneline
) al tamaño del proyecto. Una vez que utilice esa versión de Git, la respuesta a su pregunta puede ser "elegir la longitud que Git le proporcione con git log --oneline
, es lo suficientemente seguro".
Para obtener más detalles, consulte ¿ Cambiar el valor predeterminado para "core.abbrev"? discusión en la edición 20 de Git Rev News y commit bb188d00f7 .
Nota: puede solicitar git rev-parse --short
para el SHA1 más corto y único.
Consulte " git get short hash from hash regular "
git rev-parse --short=4 921103db8259eb9de72f42db8b939895f5651489
92110
Como puede ver en mi ejemplo, el SHA1 tiene una longitud de 5 incluso si especifiqué una longitud de 4.
Para grandes repos, 7 no es suficiente desde 2010, y cometer dce9648 por el mismo Linus Torvalds (git 1.7.4.4, octubre de 2010):
El valor predeterminado de 7 proviene bastante temprano en el desarrollo de git, cuando siete dígitos hexadecimales eran muchos (cubre alrededor de 250+ millones de valores de hash).
En aquel entonces, pensé que 65k revisiones eran muchas (era lo que estábamos a punto de alcanzar en BK), y cada revisión tiende a ser de unos 5-10 objetos nuevos más o menos, por lo que un millón de objetos era un gran número.
(BK = BitKeeper)
En estos días, el kernel ni siquiera es el proyecto de git más grande, e incluso el kernel tiene unas 220k revisiones ( mucho más grande que el árbol BK) y nos acercamos a dos millones de objetos.
En ese punto, siete dígitos hexadecimales siguen siendo únicos para muchos de ellos, pero cuando hablamos de solo dos órdenes de diferencia de magnitud entre el número de objetos y el tamaño del hash, habrá colisiones en valores hash truncados.
Ya no está ni cerca de ser poco realista, sucede todo el tiempo.Ambos deberíamos aumentar la abreviatura predeterminada que era irrealmente pequeña, y agregar una forma para que las personas establezcan su propio proyecto por defecto en el archivo de configuración de git .
core.abbrev
Establecer la longitud de los nombres de los objetos se abrevia a.
Si no se especifica, muchos comandos abrevian a 7 hexadecimales, lo que puede no ser suficiente para que los nombres abreviados de los objetos permanezcan únicos durante un tiempo suficientemente largo.
int minimum_abbrev = 4, default_abbrev = 7;
Nota: Tal como se comenta a continuación por marco.m , se renombró core.abbrev
en core.abbrev
en ese mismo Git 1.7.4.4 en commit a71f09f
Cambie el nombre de
core.abbrevlength
acore.abbrev
Corresponde a
--abbrev=$n
opción de línea de comando después de todo.
Más recientemente, Linus agregó en commit e6c587c (para Git 2.11, Q4 2016):
(como se menciona en la answer Matthieu Moy )
En una época bastante temprana, de alguna manera decidimos abreviar los nombres de los objetos hasta 7-hexdígitos, pero a medida que los proyectos crecen, cada vez es más probable ver nombres de objetos cortos hechos en días anteriores y grabados en los mensajes de registro que ya no son únicos.
Actualmente, el proyecto del kernel de Linux necesita de 11 a 12 hexdígitos, mientras que Git necesita 10 hexdígitos para identificar de manera única los objetos que tienen, mientras que muchos proyectos más pequeños aún pueden estar bien con el valor predeterminado original de 7 hexágonos. Un tamaño no se ajusta a todos los proyectos.
Introduzca un mecanismo, donde estimamos el número de objetos en el repositorio en la primera solicitud para abreviar un nombre de objeto con la configuración predeterminada y obtener un valor de estado en el repositorio. En función de la expectativa de que veríamos una colisión en un repositorio con
2^(2N)
objetos al usar nombres de objetos acortados a los primeros N bits, utilice una cantidad suficiente de dígitos hexadecimales para cubrir el número de objetos en el repositorio.
Cada dígito hexadecimal (4 bits) que agregamos al nombre abreviado nos permite tener cuatro veces (2 bits) tantos objetos en el repositorio.
Ver commit e6c587c (01 Oct 2016) por Linus Torvalds ( torvalds
) .
Ver commit 7b5b772 , commit 65acfea (01 Oct 2016) por Junio C Hamano ( gitster
) .
(Fusionado por Junio C Hamano - gitster
- in commit bb188d0 , 03 de octubre de 2016)
Esa nueva propiedad (adivinar un valor predeterminado razonable para el valor de abreviatura SHA1) tiene un efecto directo sobre cómo Git calcula su propio número de versión para su lanzamiento .