Introducción
Git nombra cada objeto por el hash criptográfico de su contenido. Esto es almacenamiento direccionado por contenido: el nombre es la huella digital del contenido. El hash predeterminado es SHA-1 (160 bits, 40 caracteres hex). El soporte SHA-256 existe experimentalmente desde Git 2.29.
Cómo se calcula un hash
Git antepone una cabecera de la forma <type> <size>\0 al contenido crudo, luego hashea:
printf 'blob 6\0hello\n' | sha1sum
# ce013625030ba8dba906f756967f9e9ca394464a -
El mismo valor sale de git hash-object:
printf 'hello\n' | git hash-object --stdin
# ce013625030ba8dba906f756967f9e9ca394464a
Por qué direccionar por contenido
- Deduplicación: contenido idéntico almacenado una vez.
- Integridad: cualquier corrupción cambia el hash, instantáneamente detectable.
- Reproducibilidad: el mismo tree siempre tiene el mismo nombre.
- Sincronización distribuida: Git puede preguntar "¿tienes
abc123?" sin explicar qué es.
Hashes abreviados
Git acepta el prefijo no ambiguo más corto, normalmente 7 caracteres. A medida que un repo crece, pueden necesitarse más dígitos:
git rev-parse --short HEAD
git rev-parse --short=12 HEAD
git config --global core.abbrev 12
SHA-1 versus SHA-256
SHA-1 tiene ataques de colisión conocidos (SHAttered, 2017). El proyecto Git respondió con SHA-256 como formato de objeto alternativo. Para crear un repo SHA-256:
git init --object-format=sha256
Nota: los repos SHA-1 y SHA-256 aún no pueden interoperar; el soporte de herramientas y hosting aún está madurando a fecha de Git 2.45+. Por ahora, la mayoría de proyectos continúan con SHA-1, aumentado con la implementación SHA-1 endurecida con detección de colisiones de Git.
Verificando integridad
git fsck --full
git fsck --strict
git fsck recalcula hashes para cada objeto y reporta cualquier discrepancia.
Inspeccionando un objeto
git cat-file -t <sha> # tipo
git cat-file -s <sha> # tamaño
git cat-file -p <sha> # contenido formateado
SHA-1 endurecido
Desde 2017 Git se distribuye con una implementación SHA-1 "detectora de colisiones" (sha1dc) que reconoce el patrón SHAttered publicado y se rehúsa a hashear tales entradas. Esto hace los ataques prácticos contra repositorios Git esencialmente imposibles sin descubrir una nueva técnica de colisión. El costo es una pequeña ralentización al hashear; puedes optar por el SHA-1 estándar de OpenSSL con ./configure --with-openssl-sha1 al compilar desde el código fuente, pero pocos usuarios tienen razón para hacerlo.
git --version --build-options 2>&1 | grep -i sha
Errores comunes
Preocuparse de que las colisiones SHA-1 comprometan tu repo. Los ataques conocidos requieren entradas elaboradas; Git adicionalmente detecta el patrón de colisión publicado. El riesgo pragmático para un proyecto normal es esencialmente cero. Truncar hashes muy agresivamente en scripts; en un repo con un millón de objetos, 7 caracteres pueden colisionar. Usa git rev-parse --short para que Git elija. Editar archivos de objeto directamente bajo .git/objects; eso rompe la invariante de direccionamiento por contenido y corrompe el repo. Todas las escrituras deben ir a través del plumbing de Git.