Lezione 5 di 35

Git 05

🔀 Git & GitHub · Modulo 1 · Lezione 05

Leggere la storia 🔍

git log (formati e filtri) · git diff (confrontare versioni) · git show · Navigare la storia come un detective

⏱️ Durata stimata: 60–75 min 📊 Livello: Base (Modulo 1) 🔧 Strumenti: Terminale · Repository con almeno 4-5 commit 📋 Prerequisiti: Lezioni 01–04

🕵️ Un repository senza la capacità di leggerne la storia è come un diario scritto in un cassetto chiuso a chiave. In questa lezione impari a esplorare la storia dei commit con git log, a confrontare versioni diverse con git diff e a ispezionare un singolo commit con git show. Questi tre comandi trasformano Git da “sistema di backup” a strumento investigativo potente.

🎯 Obiettivi della lezione

  • Usare git log con diversi formati: standard, oneline, graph, personalizzato
  • Filtrare la storia per autore, data, file, parola chiave nel messaggio
  • Usare git diff per confrontare: working vs staging, staging vs commit, commit vs commit
  • Ispezionare un singolo commit con git show
  • Capire come Git identifica i commit: hash, HEAD, HEAD~n
  • Leggere l’output di un diff: righe aggiunte, rimosse, contesto

📖 1. Teoria

1.1 — git log: la storia del progetto

git log mostra la lista dei commit in ordine cronologico inverso (il più recente in cima). Ogni voce contiene: hash, autore, data e messaggio. È il comando che usi per rispondere alla domanda: “Cosa è successo in questo progetto?”

$ git log
commit e5f2a1b9c3d7a45b8c2f6e3d1a9b7c5e4f8d2a1b (HEAD -> main)
Author: Mario Rossi <mario.rossi@email.it>
Date: Tue Mar 10 11:30:00 2026 +0100

Aggiunto foglio di stile e collegato alla home

commit c8d3f4a2e1b5c7d9f3a6e8b0d4c2f1a5e7b9d3c6
Author: Mario Rossi <mario.rossi@email.it>
Date: Tue Mar 10 10:45:00 2026 +0100

Aggiunta pagina contatti con form base

commit a3b8f2c9e1d7a45b8c2f6e3d1a9b7c5e4f8d2a1
Author: Mario Rossi <mario.rossi@email.it>
Date: Tue Mar 10 09:15:00 2026 +0100

Primo commit: inizializzato progetto con README

📌 Per uscire da git log: se la lista è lunga, Git la mostra in un “pager” (programma di scorrimento). Premi q per uscire, Spazio per scorrere avanti, b per tornare indietro, /parola per cercare.

1.2 — Formati di git log

L’output standard di git log è dettagliato. Esistono molte opzioni per renderlo più compatto o più informativo a seconda di cosa cerchi.

Comando Cosa mostra Quando usarlo
git log –oneline Una riga per commit: hash abbreviato + messaggio Panoramica rapida della storia
git log –oneline –graph Come sopra + linee ASCII che mostrano i branch Visualizzare la struttura dei branch (dal Modulo 2)
git log –oneline –graph –all Grafo di tutti i branch, non solo quello attuale Vista completa del repository (è l’alias git lg della Lezione 02)
git log –stat Dettagli standard + lista dei file modificati con statistiche (+/-) Capire quali file sono stati toccati in ogni commit
git log -p Dettagli standard + diff completo di ogni commit Vedere esattamente cosa è cambiato riga per riga
git log -n 5 Solo gli ultimi 5 commit Limitare l’output su repository con molti commit
# Esempio: –oneline
$ git log –oneline
e5f2a1b (HEAD -> main) Aggiunto foglio di stile e collegato alla home
c8d3f4a Aggiunta pagina contatti con form base
a3b8f2c Primo commit: inizializzato progetto con README

# Esempio: –stat (mostra quali file e quante righe)
$ git log –oneline –stat -n 2
e5f2a1b Aggiunto foglio di stile e collegato alla home
index.html | 1 +
style.css | 5 +++++
2 files changed, 6 insertions(+)
c8d3f4a Aggiunta pagina contatti con form base
contatti.html | 12 ++++++++++++
1 file changed, 12 insertions(+)

1.3 — Filtrare la storia

Su un repository con centinaia di commit, serve poter cercare. git log ha filtri potenti:

Filtro Comando Esempio
Per autore –author=”nome” git log –author=”Mario”
Per messaggio –grep=”parola” git log –grep=”fix” –oneline
Per data (dopo) –after=”data” git log –after=”2026-03-01″
Per data (prima) –before=”data” git log –before=”2026-03-15″
Per file — nomefile git log –oneline — style.css
Per contenuto -S “stringa” git log -S “background” –oneline
I filtri si possono combinare: git log --author="Mario" --after="2026-03-01" --oneline mostra solo i commit di Mario dal 1° marzo in poi.
# Tutti i commit che hanno toccato style.css
$ git log –oneline — style.css
e5f2a1b Aggiunto foglio di stile e collegato alla home

# Tutti i commit che contengono “background” nel codice aggiunto/rimosso
$ git log -S “background” –oneline
e5f2a1b Aggiunto foglio di stile e collegato alla home
Il filtro -S (detto “pickaxe”) è potentissimo: cerca i commit in cui una stringa è stata aggiunta o rimossa dal codice. Perfetto per trovare quando una funzione è stata introdotta o cancellata.

1.4 — Riferimenti ai commit: hash, HEAD, HEAD~n

Per usare git diff e git show, devi saper indicare quale commit vuoi esaminare. Git offre diversi modi per riferirsi a un commit:

Riferimento Significato Esempio
e5f2a1b Hash abbreviato (7 caratteri, di solito sufficienti) git show e5f2a1b
HEAD Il commit più recente sul branch corrente (dove sei “adesso”) git show HEAD
HEAD~1 Il commit precedente a HEAD (il “genitore”) git show HEAD~1
HEAD~3 Tre commit fa git diff HEAD~3 HEAD
main L’ultimo commit sul branch “main” git log main –oneline
Visualizzazione di HEAD e HEAD~n
a3b8f2c
HEAD~3
→
c8d3f4a
HEAD~2
→
d4e5f6a
HEAD~1
→
e5f2a1b
HEAD (main)
HEAD punta sempre al commit corrente. HEAD~1 è il genitore, HEAD~2 il nonno, ecc. I numeri contano all’indietro nella storia.

1.5 — git diff: confrontare versioni

git diff mostra le differenze tra due stati del progetto. È il microscopio di Git: dove git log ti dice “è successo qualcosa”, git diff ti dice “ecco esattamente cosa è cambiato, riga per riga”.

Comando Confronta Risponde alla domanda
git diff Working directory vs Staging area “Cosa ho cambiato ma non ancora aggiunto alla staging?”
git diff –staged Staging area vs Ultimo commit “Cosa andrà nel prossimo commit se faccio commit adesso?”
git diff HEAD Working directory vs Ultimo commit “Tutto ciò che è cambiato dall’ultimo commit, staged o no?”
git diff hash1 hash2 Commit vs Commit “Cosa è cambiato tra questi due punti nella storia?”
git diff HEAD~2 HEAD Due commit fa vs adesso “Cosa è successo negli ultimi 2 commit?”
Mappa visuale dei tre git diff
Working Dir
Staging Area
Ultimo Commit
← git diff →
← git diff –staged →
←————— git diff HEAD —————→

1.6 — Leggere l’output di git diff

L’output di un diff può sembrare criptico all’inizio. Ecco come leggerlo:

$ git diff
diff –git a/style.css b/style.css ← quale file è cambiato
index 3a4f5c2..8b7e6d1 100644
— a/style.css ← versione “vecchia” (a/)
+++ b/style.css ← versione “nuova” (b/)
@@ -1,4 +1,6 @@ ← posizione: riga 1, 4 righe vecchie → riga 1, 6 righe nuove
body { ← riga invariata (contesto)
font-family: Arial; ← riga invariata
+ background: #f0f0f0; ← riga AGGIUNTA (verde con +)
+ color: #333; ← riga AGGIUNTA
}
-/* vecchio commento */ ← riga RIMOSSA (rosso con -)
Guida rapida alla lettura del diff
+ riga Riga aggiunta nella nuova versione (verde)
– riga Riga rimossa dalla vecchia versione (rosso)
  riga Riga invariata (contesto — mostra le righe intorno alla modifica)
@@…@@ Intestazione del blocco: indica la posizione nel file (riga di partenza e numero di righe)
Una riga “modificata” appare come una riga rimossa e una riga aggiunta — perché Git ragiona per righe intere, non per singoli caratteri.

1.7 — git show: ispezionare un singolo commit

git show combina le informazioni di git log e git diff per un singolo commit: mostra autore, data, messaggio e il diff completo delle modifiche.

# Mostra i dettagli dell’ultimo commit
$ git show HEAD

# Mostra un commit specifico
$ git show c8d3f4a

# Mostra solo la lista dei file toccati (senza il diff)
$ git show –stat HEAD

# Mostra il contenuto di un file specifico in un commit specifico
$ git show HEAD~2:README.md ← mostra il README com’era 2 commit fa

📌 Trucco potente — git show COMMIT:file: puoi vedere il contenuto esatto di qualsiasi file in qualsiasi momento della storia. git show HEAD~5:index.html mostra come era index.html cinque commit fa. Utilissimo per recuperare codice cancellato senza dover fare checkout.

1.8 — Riepilogo: quale comando per quale domanda

Domanda Comando
Cosa è successo nel progetto? git log –oneline
Quali file ha toccato ogni commit? git log –stat
Chi ha scritto questo commit? git show HASH
Cosa ho cambiato ma non ancora aggiunto? git diff
Cosa andrà nel prossimo commit? git diff –staged
Cosa è cambiato tra due commit? git diff HEAD~3 HEAD
Com’era un file 5 commit fa? git show HEAD~5:nomefile
In quale commit è stata aggiunta la parola “login”? git log -S “login” –oneline

💻 2. Esempi guidati

Per questi esempi, usa il repository mini-sito dell’Esercizio 4 della Lezione 04 (o creane uno nuovo con almeno 4-5 commit).

Esempio A — Preparare un repository di test

# Se non hai già un repo con più commit, creane uno velocemente:
$ mkdir lab-storia && cd lab-storia && git init

$ echo “# Progetto Lab” > README.md
$ git add . && git commit -m “Inizializzato progetto”

$ echo “body { margin: 0; }” > style.css
$ git add . && git commit -m “Aggiunto foglio di stile base”

$ echo “<h1>Home</h1>” > index.html
$ git add . && git commit -m “Aggiunta pagina home”

$ echo “body { margin: 0; background: #fff; }” > style.css
$ git add . && git commit -m “Aggiunto background bianco al body”

$ echo “## Istruzioni” >> README.md
$ echo “<p>Benvenuto</p>” >> index.html
$ git add . && git commit -m “Aggiornati README e home con contenuto”

Esempio B — Esplorare la storia con git log

# Panoramica compatta
$ git log –oneline
f1a2b3c Aggiornati README e home con contenuto
d4e5f6a Aggiunto background bianco al body
b7c8d9e Aggiunta pagina home
a1b2c3d Aggiunto foglio di stile base
e4f5a6b Inizializzato progetto

# Quali file ha toccato ogni commit?
$ git log –oneline –stat

# Solo i commit che hanno toccato style.css
$ git log –oneline — style.css
d4e5f6a Aggiunto background bianco al body
a1b2c3d Aggiunto foglio di stile base

# Dove è stata introdotta la parola “background”?
$ git log -S “background” –oneline
d4e5f6a Aggiunto background bianco al body

Esempio C — Confrontare versioni con git diff

# Cosa è cambiato tra il primo e l’ultimo commit?
$ git diff HEAD~4 HEAD –stat
README.md | 2 ++
index.html | 2 ++
style.css | 1 +
3 files changed, 5 insertions(+)

# Com’è cambiato style.css negli ultimi 2 commit?
$ git diff HEAD~2 HEAD — style.css

# Adesso modifichiamo qualcosa senza fare add/commit
$ echo “h1 { color: navy; }” >> style.css

# Vediamo cosa abbiamo cambiato nella working dir
$ git diff
— a/style.css
+++ b/style.css
body { margin: 0; background: #fff; }
+h1 { color: navy; }

# Aggiungiamolo alla staging e poi confrontiamo staging vs commit
$ git add style.css
$ git diff ← nessun output! La working dir è uguale alla staging
$ git diff –staged ← ora mostra la differenza tra staging e ultimo commit

Esempio D — Viaggiare nel tempo con git show

# Com’era il README nel primo commit?
$ git show HEAD~4:README.md
# Progetto Lab

# Com’è adesso?
$ git show HEAD:README.md
# Progetto Lab
## Istruzioni

# Dettagli completi di un commit specifico
$ git show HEAD~1 ← mostra autore, data, messaggio E il diff completo

🏋️ 3. Esercizi

🟢 Esercizio 1 — Esplora la storia (Facile)

Usando il repository dell’Esempio A (o il tuo mini-sito), rispondi a queste domande usando solo comandi Git:

a) Quanti commit ci sono? (usa git log --oneline e conta)
b) Qual è l’hash del primo commit?
c) Quali file sono stati toccati nel terzo commit?
d) Il file style.css è stato modificato in quanti commit?
e) Qual è il messaggio del penultimo commit? (usa HEAD~1)

🔵 Esercizio 2 — I tre diff (Medio)

a) Modifica index.html aggiungendo un paragrafo. Non fare git add.
b) Esegui git diff — vedi le modifiche? Sì, perché confronta working vs staging.
c) Esegui git diff --staged — vedi qualcosa? No, perché la staging è uguale all’ultimo commit.
d) Fai git add index.html.
e) Esegui git diff — vedi qualcosa? No, perché working e staging ora sono uguali.
f) Esegui git diff --staged — ora sì! Mostra le modifiche che andranno nel prossimo commit.
g) Fai il commit.
h) Spiega con parole tue perché git diff e git diff --staged si “scambiano” la visibilità delle modifiche quando fai git add.

🟠 Esercizio 3 — Indagine detective (Medio)

Un tuo compagno ha lavorato sul repository e tu devi capire cosa ha fatto. Usa solo comandi Git per rispondere:

a) Quanti commit ha fatto in totale?
b) In quale commit ha introdotto la parola “Benvenuto” nel codice? (usa -S)
c) Com’era il file style.css nel secondo commit? (usa git show)
d) Cosa è cambiato in style.css tra il secondo e il quarto commit? (usa git diff con gli hash)
e) Elenca tutti i commit che hanno toccato README.md.

🟣 Esercizio 4 — Formato personalizzato (Difficile)

git log supporta un formato completamente personalizzabile con --pretty=format:"...". Prova:

a) Esegui: git log --pretty=format:"%h %an %ar %s". Cosa mostra ogni colonna?
Suggerimento: %h=hash abbreviato, %an=nome autore, %ar=data relativa, %s=messaggio.

b) Crea un alias che usi questo formato: git config --global alias.storia 'log --pretty=format:"%h | %ar | %s" -n 10'

c) Prova il tuo alias: git storia. Funziona?

d) Sfida: crea un formato che mostri hash, data ISO e messaggio separati da tabulazioni. Cerca i placeholder nella documentazione (git log --help) o online.

❓ 4. Quiz di verifica

1. Qual è la differenza tra git log --oneline e git log --stat?

Mostra risposta

--oneline mostra una riga per commit con solo hash abbreviato e messaggio — è una panoramica rapida della storia. --stat mostra i dettagli completi di ogni commit (autore, data, messaggio) più la lista dei file toccati con il numero di righe aggiunte e rimosse. Usa --oneline per avere un colpo d’occhio, --stat per capire l’impatto di ogni commit sui file.


2. git diff non mostra nulla dopo che hai fatto git add. È un bug?

Mostra risposta

No, è il comportamento corretto. git diff (senza flag) confronta la working directory con la staging area. Dopo git add, le due aree contengono la stessa versione del file, quindi non ci sono differenze. Per vedere cosa hai in staging pronto per il commit, usa git diff --staged — questo confronta la staging area con l’ultimo commit.


3. Cosa significa HEAD~3?

Mostra risposta

HEAD~3 si riferisce al commit che si trova 3 posizioni indietro rispetto al commit corrente (HEAD). HEAD è il commit più recente sul branch attuale, HEAD~1 è il suo genitore, HEAD~2 il nonno, HEAD~3 il bisnonno. È un modo pratico per riferirsi ai commit recenti senza dover copiare gli hash. Ad esempio, git diff HEAD~3 HEAD mostra tutte le modifiche avvenute negli ultimi 3 commit.


4. Come fai a trovare in quale commit è stata introdotta la parola “login” nel codice?

Mostra risposta

Usa il filtro “pickaxe”: git log -S "login" --oneline. Questo cerca tutti i commit in cui la stringa “login” è stata aggiunta o rimossa nel contenuto dei file. È diverso da --grep, che cerca nel messaggio di commit. -S cerca nel codice. È uno strumento investigativo potente: ti dice esattamente chi, quando e in quale commit una certa parola o funzione è apparsa o sparita dal progetto.


5. Nell’output di git diff, una riga inizia con - (rosso) e quella subito dopo con + (verde). Cosa è successo?

Mostra risposta

La riga è stata modificata. Git ragiona per righe intere: non può dire “in questa riga è cambiata una parola”. Quindi mostra la riga vecchia come rimossa (con -, in rosso) e la riga nuova come aggiunta (con +, in verde). Leggendo le due righe una sotto l’altra, puoi vedere cosa è cambiato. Se vedi solo + senza un - corrispondente, è una riga veramente nuova. Se vedi solo -, è una riga cancellata senza sostituzione.


6. Vuoi vedere come era il file index.html nel primo commit, senza modificare nulla nel tuo progetto attuale. Come fai?

Mostra risposta

Usa git show HASH:index.html dove HASH è l’hash del primo commit (trovalo con git log --oneline). Ad esempio: git show e4f5a6b:index.html. Oppure, se conosci quanti commit fa è stato: git show HEAD~4:index.html. Questo comando stampa il contenuto del file come era in quel commit — senza toccare la tua working directory. È come “sbirciare” nel passato senza viaggiare nel tempo.


📚 Riepilogo della lezione

Cosa hai imparato oggi:
  • git log — la storia del progetto: --oneline (compatto), --stat (file), --graph (branch), -p (diff)
  • Filtri: --author, --grep, --after/--before, -- file, -S "stringa" (pickaxe)
  • Riferimenti: hash (es. e5f2a1b), HEAD (commit corrente), HEAD~n (n commit indietro)
  • git diff — working vs staging · git diff --staged — staging vs commit · git diff HEAD — working vs commit
  • Leggere un diff: + aggiunta · – rimozione · spazio contesto · @@ posizione
  • git show HASH — dettagli di un commit · git show HASH:file — contenuto di un file nel passato

Prossima lezione →

Lezione 06 — Annullare modifiche
git restore, git reset (soft/mixed/hard), git revert.
Quando usare quale — e gli errori comuni da evitare.

Corso Git & GitHub · Per studenti e insegnanti · Lezione 05 di 45