ver tipos tag subir oneline modificados log etiquetas crear archivos git hash sha1 checksum git-hash

tipos - ¿Cómo calcula git hashes de archivos?



subir archivos git (5)

Git prefija el objeto con "blob", seguido de la longitud (como un entero legible por el ser humano), seguido de un carácter NUL

$ echo -e ''blob 14/0Hello, World!'' | shasum 8ab686eafeb1f44702738c8b0f24f2567c36da6d

Fuente: http://alblue.bandlem.com/2011/08/git-tip-of-week-objects.html

Los valores hash SHA1 almacenados en los objetos del árbol (como los devuelve git ls-tree ) no coinciden con los valores hash SHA1 del contenido del archivo (tal como lo devuelve sha1sum )

$ git cat-file blob 4716ca912495c805b94a88ef6dc3fb4aff46bf3c | sha1sum de20247992af0f949ae8df4fa9a37e4a03d7063e -

¿Cómo calcula git hashes de archivos? ¿Comprime el contenido antes de calcular el hash?


Lo necesitaba para algunas pruebas unitarias en Python 3, así que pensé que lo dejaría aquí.

def git_blob_hash(data): if isinstance(data, str): data = data.encode() data = b''blob '' + str(len(data)).encode() + b''/0'' + data h = hashlib.sha1() h.update(data) return h.hexdigest()

Me adhiero a /n terminaciones de línea en todas partes, pero en algunas circunstancias Git también podría estar cambiando las terminaciones de línea antes de calcular este hash, así que es posible que necesites un .replace(''/r/n'', ''/n'') allí también.


Según la respuesta de , aquí hay una función de shell que sustituye a git hash-object :

git-hash-object () { # substitute when the `git` command is not available local type=blob [ "$1" = "-t" ] && shift && type=$1 && shift # depending on eol/autocrlf settings, you may want to substitute CRLFs by LFs # by using `perl -pe ''s//r$//g''` instead of `cat` in the next 2 commands local size=$(cat $1 | wc -c | sed ''s/ .*$//'') ( echo -en "$type $size/0"; cat "$1" ) | sha1sum | sed ''s/ .*$//'' }

Prueba:

$ echo ''Hello, World!'' > test.txt $ git hash-object test.txt 8ab686eafeb1f44702738c8b0f24f2567c36da6d $ git-hash-object test.txt 8ab686eafeb1f44702738c8b0f24f2567c36da6d


Solo estoy ampliando la respuesta de @Leif Gruenwoldt y detallando lo que está en la http://alblue.bandlem.com/2011/08/git-tip-of-week-objects.html proporcionada por @Leif Gruenwoldt

Hazlo tu mismo..

  • Paso 1. Crea un documento de texto vacío (el nombre no importa) en tu repositorio
  • Paso 2. Etapa y compromiso del documento
  • Paso 3. Identifica el hash del blob ejecutando git ls-tree HEAD
  • Paso 4. Encuentra el hash del blob para ser e69de29bb2d1d6434b8b29ae775ad8c2e48c5391
  • Paso 5. Salga de su sorpresa y lea a continuación

¿Cómo calcula GIT sus hashes de confirmación?

Commit Hash (SHA1) = SHA1("blob " + <size_of_file> + "/0" + <contents_of_file>)

El texto blob⎵ es un prefijo constante y /0 también es constante y es el carácter NULL . El <size_of_file> y <contents_of_file> varían según el archivo.

¡Y eso es todo amigos!

¡Pero espera! , ¿notó que el <filename> no es un parámetro utilizado para el cálculo hash? Dos archivos podrían tener el mismo hash si sus contenidos son indiferentes a la fecha y hora en que fueron creados y su nombre. Esta es una de las razones por las que Git maneja movimientos y cambia el nombre mejor que otros sistemas de control de versiones.

Hágalo usted mismo (Ext)

  • Paso 6. Crea otro archivo vacío con un filename de filename diferente en el mismo directorio
  • Paso 7. Compara los hashes de tus dos archivos.

Nota:

El enlace no menciona cómo se codifica el objeto del tree . Sin embargo, no estoy seguro del algoritmo y los parámetros de mi observación. Probablemente computa un hash basado en todos los blobs y trees (probablemente sus hashes) que contiene


git hash-object es una forma rápida de verificar tu método de prueba:

s=''abc'' printf "$s" | git hash-object --stdin printf "blob $(printf "$s" | wc -c)/0$s" | sha1sum

Salida:

f2ba8f84ab5c1bce84a7b441cb1959cfc7093b7f f2ba8f84ab5c1bce84a7b441cb1959cfc7093b7f -

donde sha1sum está en GNU Coreutils.