Da Anonimo (non verificato) , 29 Aprile 2026

Introduzione

Il repository di Git è, nel cuore, un object store indirizzato per contenuto. Ci sono esattamente quattro tipi di oggetti: blob, tree, commit e tag. Ogni operazione alla fine tocca uno di essi. Capire questi quattro tipi demistifica la maggior parte di Git.

Blob

Un blob memorizza il contenuto di un file, niente di più. Nessun nome di file, nessun permesso, nessuna storia. Due file con contenuto identico condividono un solo blob, indipendentemente da dove vivono nell'albero.

echo "hello" | git hash-object --stdin
# ce013625030ba8dba906f756967f9e9ca394464a

Tree

Un tree è un elenco di directory: un set ordinato di entry (mode, type, sha, name). Le sottodirectory sono a loro volta tree, ricorsivamente. Ogni commit punta a esattamente un tree radice.

git ls-tree HEAD
# 100644 blob a1b2... README.md
# 040000 tree c3d4... src

Commit

Un oggetto commit contiene:

  • Un puntatore a un tree radice.
  • Zero o più commit parent (zero per il root, due o più per i merge).
  • Author e committer con timestamp.
  • Un messaggio.
  • Firma GPG/SSH opzionale.
git cat-file -p HEAD
# tree 9f1a...
# parent b2c3...
# author Ada <[email protected]> 1714300000 +0000
# committer Ada <[email protected]> 1714300000 +0000
#
# Add greeting

Tag

Un tag annotated è un proprio oggetto che punta a un altro oggetto (quasi sempre un commit), con info del tagger e un messaggio. I tag lightweight sono solo ref e non hanno oggetto.

git cat-file -t v1.0.0
# tag
git cat-file -p v1.0.0

Mettere tutto insieme

Percorri manualmente il tree di un commit:

git cat-file -p HEAD^{tree}
git cat-file -p HEAD^{tree}:src
git cat-file -p HEAD:README.md

Il peel ^{tree} e la sintassi commit:path sono come tutti gli strumenti Git navigano.

Storage

Ogni oggetto è compresso con zlib e indirizzato dallo SHA-1 (o SHA-256) del suo contenuto non compresso più un header. Contenuti identici, ovunque nella storia, vengono deduplicati automaticamente.

Mode delle entry tree

Il campo mode in un'entry tree è un piccolo set di mode file simili a POSIX:

  • 100644: file regolare non eseguibile (blob).
  • 100755: file eseguibile (blob).
  • 120000: link simbolico (blob il cui contenuto è il target).
  • 040000: sottodirectory (tree).
  • 160000: gitlink (riferimento submodule a uno SHA di commit).
git ls-tree HEAD
git update-index --chmod=+x scripts/run.sh
git ls-tree HEAD scripts/

Git è intenzionalmente limitato; permessi e proprietà arbitrarie non vengono memorizzati.

Errori comuni

Credere che Git memorizzi i diff. Non lo fa; memorizza snapshot completi, deduplicati per hash e successivamente compressi in delta nei pack file. Confondere i tree con le directory su disco; i tree sono oggetti immutabili. Confondere i tag lightweight con quelli annotated; solo i tag annotated portano metadati e firme. Infine, aspettarsi che rinominare un file cambi il blob; il blob è lo stesso, solo l'entry name del tree cambia. Spendi dieci minuti con git cat-file -p su un repository reale e il modello diventa naturale.