Introducción
Git almacena objetos en dos formatos: sueltos (un archivo por objeto bajo .git/objects/xx/yyyy...) y empaquetados (muchos objetos en un solo archivo .pack con un compañero .idx). Los packs son mucho más eficientes en disco y en la red.
Disposición
.git/objects/
00/ ... objetos sueltos, nombrados por sha menos los primeros dos chars
pack/
pack-<hash>.pack # los datos
pack-<hash>.idx # índice de offsets
pack-<hash>.rev # índice inverso (Git 2.31+)
Por qué packs
- Un archivo por objeto es brutal en sistemas de archivos con millones de archivos.
- Los packs aplican compresión delta: almacenan blobs similares como una base más un diff.
- Los packs usan zlib además de los deltas.
- Los fetch/push smart transfieren datos pack directamente.
Disparando empaquetamiento
git gc # mantenimiento rutinario
git gc --aggressive # búsqueda de delta más pesada
git repack -a -d -f # recrear un pack desde todos los objetos
git fetch # también puede producir packs
Auto-gc se dispara cuando el repo acumula demasiados objetos sueltos; ajusta con gc.auto.
Inspeccionando packs
ls .git/objects/pack
git verify-pack -v .git/objects/pack/pack-<hash>.idx | head
git count-objects -v
verify-pack -v muestra el tipo, tamaño, tamaño empaquetado de cada objeto, y si es un delta contra otro objeto.
Multi-pack indexes
Para repos muy grandes, múltiples packs pueden unificarse mediante un solo índice:
git multi-pack-index write
git config core.multiPackIndex true
Bitmaps de alcanzabilidad
Los bitmaps aceleran las consultas de alcanzabilidad (usadas por clone y fetch en servidores de hosting):
git repack -adb # construir bitmap
git config repack.writeBitmaps true
Los bitmaps son más útiles cuando se sirven muchos clones o cuando se ejecutan grandes consultas git rev-list.
Detalles de compresión de objetos
Un delta en un pack almacena una referencia de objeto base y un flujo de instrucciones. La base puede ser ella misma un delta. Git limita las cadenas de delta vía pack.depth (predeterminado 50). La base elegida es normalmente un blob similar, a menudo una versión previa del mismo archivo.
Repacking geométrico
Mantener un solo pack enorme es caro; reescribirlo en cada gc es derrochador. Git moderno soporta repacking geométrico, que mantiene una cadena de packs de tamaño geométricamente creciente y solo reempaqueta los pequeños:
git repack --geometric=2 -d --write-bitmap-index
git config maintenance.incremental-repack.enabled true
git maintenance run --task incremental-repack
Esto hace el mantenimiento rutinario acotado: cada gc solo toca los packs más pequeños. Combinado con multi-pack indexes y bitmaps de alcanzabilidad, el repack geométrico es la configuración recomendada para repositorios grandes o ocupados.
Errores comunes
Eliminar manualmente un archivo .pack para reclamar espacio, rompiendo el repo. El pack contiene muchos objetos alcanzables; usa git gc --prune en su lugar. Ejecutar git gc --aggressive en un horario; es caro y rara vez mejora sobre un gc normal. Mantener millones de objetos sueltos (después de una recuperación fallida) y luego hacer git status en un sistema de archivos lento; empaqueta primero. Finalmente, transferir packs copiando archivos en lugar de usar git clone --bare; podrías perderte el .idx o saltarte características más nuevas como el multi-pack index.