modulo 01 / lezione 01
Fondamenti e modello mentale
Cosa è Git: snapshot, non diff
Sostituire l'idea di 'Git che salva differenze' con il modello reale: ogni commit è uno snapshot completo dell'albero di file.
Cosa è Git: snapshot, non diff
La prima idea da correggere è questa: Git non salva una sequenza di differenze testuali come se fosse un documento con revisioni. Git salva snapshot. Ogni commit punta a una fotografia completa dell’albero dei file in quel momento.
Questo non significa che Git sprechi spazio copiando tutto ogni volta. Internamente deduplica oggetti identici, comprime e ottimizza. Ma il modello mentale corretto resta: quando fai commit, Git registra “com’era il progetto”, non solo “cosa è cambiato”.
Perché questa lezione conta
Se pensi a Git come a una lista di patch, molti comandi sembrano magia: branch, merge, reset, rebase, checkout. Se lo pensi come un grafo di snapshot collegati da puntatori, i comandi diventano più prevedibili.
Questa lezione serve a togliere superstizione. Git è difficile quando lo usi a memoria. Diventa molto più maneggevole quando sai che stai manipolando oggetti immutabili e riferimenti mobili.
Obiettivo operativo
Alla fine della lezione devi saper spiegare cosa contiene un commit, quali oggetti lo compongono e perché un branch può spostarsi senza “contenere” davvero codice.
Snapshot, non patch
Immagina tre commit:
A -- B -- C
Ogni commit punta a un tree, cioè a una struttura che rappresenta cartelle e file. Se tra A e B cambia solo un file, Git non deve duplicare ogni contenuto: può riusare gli oggetti dei file invariati. Ma il commit B descrive comunque lo stato completo del progetto.
Questo spiega perché puoi fare checkout di un commit vecchio e vedere tutto il progetto com’era allora. Git non ricostruisce solo applicando patch una dopo l’altra nel tuo editor: legge lo snapshot puntato dal commit.
Gli oggetti principali
Git lavora con pochi tipi di oggetti:
Blob. Contenuto di un file. Non contiene il nome del file, solo i byte.
Tree. Directory: associa nomi, permessi e riferimenti a blob o altri tree.
Commit. Punta a un tree, ha zero o più parent, autore, committer, data e messaggio.
Tag. Riferimento, spesso annotato, a un commit o a un oggetto.
Il nome file vive nel tree, non nel blob. Questo dettaglio è utile: se rinomini un file senza cambiarne contenuto, Git può riconoscere che il contenuto è lo stesso anche se il percorso cambia.
Hash come identità
Ogni oggetto Git ha un hash. L’hash dipende dal contenuto e dal tipo dell’oggetto. Se cambi un byte, cambia l’identità.
Questo dà tre proprietà operative:
- integrità: Git sa se un oggetto è stato corrotto;
- deduplicazione: contenuti identici hanno lo stesso oggetto;
- immutabilità pratica: riscrivere un commit significa creare un nuovo commit con nuovo hash.
Quando fai rebase, amend o squash, non stai “modificando” commit esistenti. Stai creando nuovi commit simili, con hash diversi, e poi sposti un branch a puntare lì.
Comandi essenziali
git init demo-git-snapshot
cd demo-git-snapshot
git config user.name "Demo"
git config user.email "demo@example.com"
echo "prima versione" > app.txt
git add app.txt
git commit -m "Aggiungi app iniziale"
echo "seconda versione" > app.txt
git add app.txt
git commit -m "Aggiorna testo app"
git cat-file -p HEAD
git cat-file -p HEAD^{tree}
git ls-tree -r HEAD
git cat-file -p HEAD mostra il commit: vedrai il tree, il parent, autore e messaggio. git ls-tree -r HEAD mostra la fotografia dei file puntata da quel commit.
Laboratorio guidato
Crea un repo demo con due file e tre commit:
- primo commit con
README.md; - secondo commit che aggiunge
app.txt; - terzo commit che modifica solo
app.txt.
Per ogni commit annota:
- hash del commit;
- hash del tree;
- blob associati ai file;
- cosa resta uguale tra commit consecutivi.
Poi disegna il grafo:
commit C -> tree C -> blob README
-> blob app v2
commit B -> tree B -> blob README
-> blob app v1
Non serve essere perfetti nel disegno. Serve vedere che il commit punta a una fotografia.
Output atteso
Produci una nota tecnica breve:
Git salva snapshot.
Un commit punta a un tree.
Un tree collega nomi file a blob.
Un branch punta a un commit.
Riscrivere storia crea nuovi commit, non cambia quelli vecchi.
Questa nota diventa la base mentale del resto del corso.
Errori comuni
Pensare che un branch sia una cartella. Un branch è un puntatore mobile a un commit.
Pensare che amend modifichi davvero il commit. Crea un nuovo commit e sposta il branch.
Confondere diff e storia. Il diff è una vista calcolata tra due snapshot, non l’unità primaria salvata da Git.
Checklist di verifica
- so distinguere blob, tree e commit;
- so leggere
git cat-file -p HEAD; - so spiegare perché due commit simili hanno hash diversi;
- so dire perché Git può recuperare un progetto com’era in un commit vecchio.
Collegamenti
- Modulo: Fondamenti e modello mentale — lezione 1 del corso.
- La prossima lezione porta questo modello dentro working tree, index e repository.