Introducción
"Alcanzabilidad" es la propiedad más importante de un objeto Git. Un objeto es alcanzable si alguna ref lleva a él vía enlaces de padre o tree. Los objetos inalcanzables son elegibles para recolección de basura.
Reglas de alcanzabilidad
Empezando desde cualquier ref:
- Un commit alcanza su tree raíz, todos los padres y (transitivamente) los trees y padres de esos padres.
- Un tree alcanza todas las entradas (blobs y subtrees).
- Un tag anotado alcanza el objeto etiquetado.
Las refs incluyen branches locales, branches de seguimiento remoto, tags, stash, notes y el reflog (hasta la expiración).
Listando objetos alcanzables
git rev-list --objects --all | head
git rev-list --objects HEAD
git rev-list --count HEAD
Pruebas de ascendencia
git merge-base --is-ancestor X Y && echo "X is ancestor of Y"
git rev-list X..Y --count # cuántos commits hay entre
git log --ancestry-path A..B --oneline # solo commits en el camino A a B
--ancestry-path es invaluable para encontrar la cadena de commits que llevó un fix de un tag a otro.
Operadores de rango
A..B: alcanzables desde B, no desde A.A...B: diferencia simétrica (cualquier lado, no ambos).^A B C: alcanzables desde B o C pero no A.
git log main..feature # commits añadidos por feature
git log main...feature --left-right # ambos lados etiquetados
Objetos inalcanzables
git fsck --unreachable
git fsck --dangling
git fsck --lost-found # los escribe en .git/lost-found
Los objetos inalcanzables sobreviven hasta que git gc --prune los elimina; el período de gracia predeterminado es dos semanas (gc.pruneExpire).
El papel del archivo commit-graph
Las consultas de alcanzabilidad y ascendencia son el cuello de botella de muchas operaciones Git. El archivo commit-graph precalcula los números de generación y listas de padres, haciendo estas consultas O(log n) en lugar de O(n):
git commit-graph write --reachable
git config --global core.commitGraph true
Alcanzabilidad por bitmaps
Del lado del servidor, los bitmaps de alcanzabilidad permiten a Git responder "¿qué objetos son alcanzables desde este commit?" en microsegundos, almacenando un bit precalculado por objeto. Se escriben con:
git repack -adb
Recorridos limitados por fecha o ruta
La maquinaria de alcanzabilidad acepta muchos limitadores que se combinan con la sintaxis de rango:
git rev-list --since=2024-01-01 main
git rev-list main -- path/to/file
git rev-list --no-merges main..feature
git rev-list --first-parent main
git rev-list HEAD --count
Combina estos para responder preguntas específicas como "¿cuántos commits no-merge aterrizó Ada en main el último trimestre?" sin recurrir a pipelines de shell. La salida estable del plumbing hace trivial alimentar el resultado a herramientas de reporte.
Errores comunes
Creer que un branch eliminado borra sus commits; permanecen alcanzables a través del reflog durante 90 días, e inalcanzables pero no podados durante dos semanas más. Confundir A..B con A...B; uno es asimétrico, el otro simétrico. Usar HEAD~3 para navegar a través de merges y confundirse por el recorrido de primer padre; usa HEAD^2 para cambiar al segundo padre. Finalmente, esperar que git fsck encuentre commits perdidos tras un clon nuevo; el reflog y los objetos colgantes solo existen localmente donde se hizo el trabajo.