Objetos, blobs, trees y commits
La base de datos de Git se entiende mejor si bajas un nivel y miras los objetos. No hace falta usar estos comandos todos los dias, pero conocerlos ayuda a entender por que Git puede recuperar tanto.
Los cuatro tipos de objeto
flowchart LR
B["blob\ncontenido de archivo"]
T["tree\ndirectorio"]
C["commit\nsnapshot + metadata"]
G["tag\nnombre firmado o anotado"]
C --> T
T --> B
T --> T
G --> CBlob
Un blob guarda el contenido de un archivo, no su nombre.
Puedes crear un objeto manualmente:
echo "hola" | git hash-object --stdinPara guardarlo en la base de datos:
echo "hola" | git hash-object -w --stdinGit calcula un hash a partir del tipo, tamano y contenido. Si dos archivos tienen el mismo contenido, pueden compartir el mismo blob.
Tree
Un tree guarda nombres, permisos y enlaces a blobs u otros trees.
Ver el tree de un commit:
git ls-tree HEAD
git ls-tree -r HEADEjemplo conceptual:
tree HEAD
100644 blob a1b2c3 readme.md
040000 tree d4e5f6 srcCommit
Un commit apunta a:
- Un tree.
- Cero, uno o varios commits padre.
- Autor.
- Committer.
- Fecha.
- Mensaje.
Inspeccion:
git cat-file -p HEADSalida conceptual:
tree 9f1a...
parent 3b2c...
author Iago PL <email@example.com> 1710000000 +0100
committer Iago PL <email@example.com> 1710000000 +0100
Anade autenticacionCommit inicial
El primer commit no tiene padre.
git rev-list --max-parents=0 HEADMerge commit
Un merge commit tiene dos o mas padres.
git cat-file -p HEADPuedes ver la forma:
git log --oneline --graph --decorate --allflowchart BT
A["A"] --> B["B"]
B --> C["C"]
B --> D["D"]
C --> M["merge"]
D --> MDiff entre commits
Git no necesita guardar un diff como pieza principal. Puede calcularlo comparando trees.
git diff HEAD~1 HEAD
git diff main feature/loginIdentificadores
Los hashes largos son identificadores completos. Normalmente puedes usar abreviados:
git show a1b2c3Si el repositorio crece y hay ambiguedad, Git pedira mas caracteres.
Objetos alcanzables
Un objeto es alcanzable si existe alguna referencia que permite llegar a el.
flowchart LR
R["main"] --> C3["commit C"]
C3 --> C2["commit B"]
C2 --> C1["commit A"]
X["commit perdido"]:::lost
classDef lost fill:#f8d7da,stroke:#b42318,color:#111;Los objetos no alcanzables no desaparecen inmediatamente. Por eso reflog y fsck pueden rescatar cambios.
Buscar objetos sueltos
git fsck --lost-foundNo es una herramienta de uso diario, pero puede ayudar en recuperaciones avanzadas.
Relacion con git add
Cuando haces:
git add src/app.jsGit prepara en el index la version exacta de ese archivo. Si despues editas otra vez src/app.js, tendras:
- Una version en el index.
- Otra version en el working tree.
Compruebalo:
git diff
git diff --stagedBuenas practicas
- Usa commits pequenos para que cada snapshot tenga sentido.
- Revisa
git diff --stagedantes de confirmar. - No confundas nombre de archivo con blob: Git guarda contenido y estructura por separado.
- Aprende a leer
git log --graphpara entender padres y merges.
