Introducción
Un clon shallow descarga solo los N commits más recientes de un branch en lugar del historial completo. El resultado es mucho más pequeño y rápido de descargar, al costo de un historial incompleto.
Creando
git clone --depth 1 https://github.com/example/widget.git
git clone --depth 50 https://github.com/example/widget.git
git clone --depth 1 --branch v1.2.3 --single-branch <url>
El directorio .git contiene un archivo shallow que lista los commits cuyos padres se han omitido.
Por qué shallow
- Builds de CI: solo necesitan el código fuente para HEAD.
- Contenedores y Dockerfiles: imágenes más pequeñas.
- Herramientas one-shot que no necesitan historial.
Limitaciones
- No puedes hacer push desde un clon shallow si tu push depende de commits que el servidor no tiene (raro, pero posible).
git logse detiene en el límite shallow.- Algunas operaciones (rebase a través del límite, blame en líneas viejas) no pueden funcionar.
- Hasta Git 2.11 clonar shallow sobre HTTP no estaba soportado; Git moderno lo maneja.
Profundizando y desclonando shallow
git fetch --depth 100 # extender profundidad
git fetch --deepen 50 # añadir 50 commits más
git fetch --shallow-since=2024-01-01
git fetch --unshallow # descargar historial completo
Después de --unshallow el repo se comporta como un clon normal.
Single-branch y shallow
--single-branch + --depth 1 es el clon útil más pequeño posible. Para rastrear otros branches después:
git remote set-branches --add origin main feature
git fetch origin
Clones parciales (una optimización diferente)
Si necesitas historial completo pero no todos los blobs, usa un clon parcial en su lugar:
git clone --filter=blob:none <url>
git clone --filter=tree:0 <url>
Los clones parciales descargan historial pero aplazan blobs (o trees) hasta necesitarlos. Suelen ser una mejor elección que shallow cuando el servidor los soporta.
Detectando estado shallow
git rev-parse --is-shallow-repository
cat .git/shallow
Patrones de CI
Muchos proveedores de CI usan clones shallow por defecto (depth 1 o 50). Si tu build ejecuta git describe o necesita blame entre versiones, solicita un clon completo:
# GitHub Actions
- uses: actions/checkout@v4
with:
fetch-depth: 0
Archivos shallow y grafts
El archivo shallow en .git/ lista SHAs de commits cuyos padres están intencionalmente faltantes. Git los trata como raíces durante el recorrido del grafo. El mecanismo relacionado pero deprecado info/grafts te permitía falsificar relaciones de padre; usa git replace --graft en su lugar, que es más seguro y se replica sobre fetch:
cat .git/shallow
git replace --graft <commit> <new-parent>
git replace -l
git replace -d <commit>
Esto es ocasionalmente útil para coser historiales importados sin reescribir commits.
Errores comunes
Ejecutar git describe en un clon depth-1 y obtener un error porque ningún tag anotado es alcanzable; o bien descarga tags (--tags) o usa un clon más profundo. Intentar rebasear un branch feature en un clon shallow donde la merge base está más allá del límite shallow; profundiza primero. Pushear desde un clon shallow y sorprenderte por "remote rejected"; el servidor puede necesitar objetos padre faltantes. Finalmente, tratar los clones shallow como sustituto de los clones parciales; resuelven problemas diferentes y los parciales suelen ser más amigables.