Guida

git log, diff, show e blame: come leggere la cronologia di un progetto Git

Aggiornato: · Skillaria.Top

git log mostra l'elenco dei commit e sa filtrarli per autore, data, file e testo; git diff confronta cartella di lavoro, index e qualsiasi commit; git show visualizza un commit per intero; git blame indica quale commit ha modificato per ultimo ogni riga di un file.

Quattro comandi coprono quasi tutte le domande sulla cronologia di un progetto. git log risponde a «cosa è successo», git diff a «cosa è cambiato esattamente», git show a «cosa c'è dentro un commit specifico», git blame a «chi ha scritto questa riga e quando». Di seguito, tecniche pratiche per ciascuno, con i flag che si usano davvero nello sviluppo quotidiano.

git log: l'elenco dei commit

Senza argomenti git log mostra i commit del branch corrente dal più recente al più vecchio: hash SHA-1 completo, autore, data e messaggio. Si scorre in un pager (di solito less): spazio per la pagina successiva, /testo per cercare, q per uscire.

commit 7be41d0c9a2e4f1b8d6c3e5a7f9b0c2d4e6f8a1b
Author: Anna Petrova <anna@example.com>
Date:   Mon Oct 5 14:22:10 2026 +0300

    feat: caching delle risposte API

Non serve copiare l'hash per intero: Git riconosce qualsiasi prefisso univoco da 4 caratteri in su, in pratica ne bastano 7.

Output compatto: --oneline

git log --oneline -10
# 7be41d0 (HEAD -> main, origin/main) feat: caching delle risposte API
# 1c02e8f fix: timeout delle richieste
# 9a4b3c2 refactor: client spostato in un modulo

Il flag -10 (o -n 10) limita il numero di commit. Tra parentesi ci sono i puntatori: dove si trovano HEAD, i branch locali e remoti, i tag.

Il grafo dei branch: git log --graph

Chi cerca «git graph» di solito intende proprio questo: la visualizzazione di diramazioni e merge direttamente nel terminale.

git log --oneline --graph --all
# * 3e1f0aa (feature/auth) feat: accesso tramite token
# | * 7be41d0 (HEAD -> main) feat: caching delle risposte API
# |/
# * 1c02e8f fix: timeout delle richieste
# *   5d2c7b1 Merge branch 'feature/search'
# |\
# | * 8f3a9e0 feat: ricerca
# |/
# * 9a4b3c2 refactor: client spostato in un modulo

--all mostra tutti i branch, non solo quello corrente. Conviene creare un alias: git config --global alias.lg "log --oneline --graph --all --decorate", dopodiché basta git lg.

Formato personalizzato: --pretty=format

git log --pretty=format:"%h %ad %an %s" --date=short
# 7be41d0 2026-10-05 Anna Petrova feat: caching delle risposte API

I segnaposto principali: %h hash breve, %H completo, %an autore, %ae la sua e-mail, %ad data dell'autore, %ar data relativa («2 days ago»), %s titolo del messaggio.

Come filtrare la cronologia con git log

Per autore e data

git log --author="Anna"
git log --since="2 weeks ago" --until="2026-10-01"
git log --since=yesterday --oneline

--author accetta un'espressione regolare e cerca sia nel nome sia nell'e-mail. Git capisce le date sia in forma libera sia in formato ISO.

Per testo del messaggio

git log --grep="fix" -i --oneline

-i rende la ricerca insensibile alle maiuscole. Se il vostro team scrive i numeri dei ticket nei messaggi, così trovate subito tutti i commit di un'attività.

Per file o cartella

git log --oneline -- src/api/client.py
git log --follow -p -- src/api/client.py

Il doppio trattino separa i percorsi dai branch. --follow segue la cronologia del file anche attraverso le rinomine (funziona per un solo file), -p mostra la patch di ogni commit.

Per codice modificato: la ricerca «piccone»

git log -S "retry_count" --oneline     # commit in cui è cambiato il numero di occorrenze della stringa
git log -G "timeout\s*=" --oneline    # commit con righe nel diff che corrispondono alla regex

-S trova il commit in cui una funzione o variabile è stata aggiunta o rimossa: insostituibile quando dovete capire dove è finito un pezzo di codice.

Intervalli di commit

git log main..feature      # cosa c'è in feature ma non in main
git log origin/main..HEAD  # i miei commit locali non ancora inviati
git log --no-merges        # senza merge commit
git log --stat             # quali file e quante righe sono stati modificati

git diff: cosa è cambiato esattamente

La cosa principale da capire su git diff è quali due stati confronta. La confusione su questo punto è all'origine della domanda «perché il diff è vuoto, ho cambiato tutto».

ComandoCosa confronta
git diffcartella di lavoro rispetto all'index (modifiche non preparate)
git diff --staged (--cached)index rispetto all'ultimo commit (cosa entrerà nel commit)
git diff HEADcartella di lavoro rispetto all'ultimo commit (tutto insieme)
git diff A Bdue commit, branch o tag
git diff A...Ble modifiche in B dal momento della diramazione da A

Se avete fatto git add, il normale git diff diventa vuoto: le modifiche sono già nell'index, guardate --staged. I file nuovi, mai aggiunti, il diff non li mostra affatto.

Come leggere l'output del diff

diff --git a/config.py b/config.py
index 3b18e51..a1c4f02 100644
--- a/config.py
+++ b/config.py
@@ -10,7 +10,7 @@ DEFAULTS = {
     "host": "localhost",
-    "timeout": 5,
+    "timeout": 30,
     "retries": 3,

Le righe con - sono state rimosse, quelle con + aggiunte, le altre sono contesto. L'intestazione @@ -10,7 +10,7 @@ significa: il frammento inizia alla riga 10 e occupa 7 righe nella versione vecchia e in quella nuova.

Flag utili di git diff

git diff --stat main feature      # riepilogo per file
git diff --name-only HEAD~3       # solo i nomi dei file modificati
git diff --word-diff               # modifiche parola per parola, comodo per i testi
git diff -w                        # ignorare le modifiche agli spazi
git diff main feature -- src/      # limitare a una cartella

Prima di ogni commit è utile guardare git diff --staged: è l'ultima occasione per notare un print di debug o un file aggiunto per sbaglio.

git show: un commit per intero

git show mostra i metadati del commit e il suo diff rispetto al genitore. Senza argomenti, l'ultimo commit.

git show 7be41d0
git show HEAD~2 --stat           # senza patch, solo il riepilogo
git show v1.2.0                  # tag: annotazione e commit
git show main:src/config.py      # il file com'era in quel commit

L'ultima forma <revisione>:<percorso> è particolarmente utile: permette di vedere una vecchia versione del file senza passare su di essa. Reindirizzate l'output in un file e recupererete il contenuto eliminato senza checkout.

git blame: chi ha modificato questa riga

git blame file mostra per ogni riga l'ultimo commit che l'ha modificata, l'autore e la data. Il nome suona accusatorio, ma in realtà è uno strumento per trovare il contesto: individuare il commit, leggerne il messaggio e capire perché è stato fatto così.

git blame -L 40,60 src/api/client.py
# 1c02e8f3 (Anna Petrova 2026-09-28 11:04:51 +0300 41)     timeout = settings.timeout
# 9a4b3c2e (Ivan Smirnov 2026-09-14 18:30:02 +0300 42)     session = build_session()
  • -L 40,60: solo un intervallo di righe; funziona anche -L :nome_funzione.
  • -w: ignorare le modifiche agli spazi, per non finire sui commit di formattazione.
  • -C: seguire le righe spostate da altri file.
  • --ignore-rev <hash> o il file .git-blame-ignore-revs: saltare commit massivi come la formattazione automatica.

Scenario tipico di indagine: git blame trova il commit, git show lo mostra per intero, git log sul file dà le modifiche vicine.

Ai commit ci si può riferire non solo con gli hash. HEAD~1 è il genitore del commit corrente, HEAD~3 il bisnonno. HEAD^2 è il secondo genitore di un merge commit. Funzionano anche i nomi di branch, tag e branch remoti: origin/main~2. Per vedere l'intero progetto a un vecchio commit si usa git switch --detach <hash>, per tornare git switch -.

Cronologia buona e cronologia cattiva

Tutti questi comandi sono utili tanto quanto è sensata la cronologia. Messaggi come «fix», «wip», «altre modifiche» rendono inutili git log --grep e git blame. Un buon commit è una sola modifica logica con un titolo che spiega cosa e perché: fix: timeout API aumentato a 30 s per il gateway lento. Fra sei mesi sarà proprio un commit così che blame troverà, facendovi risparmiare un'ora.

In pratica: indagare su un bug attraverso la cronologia

Supponiamo che dopo l'ultima release le richieste all'API abbiano iniziato a fallire per timeout. Ecco come la combinazione dei comandi porta alla causa in un paio di minuti.

  1. Guardiamo cosa è entrato nella release: git log v1.4.0..v1.5.0 --oneline. L'elenco è breve, ma dai titoli il colpevole non è evidente.
  2. Restringiamo per file: git log v1.4.0..v1.5.0 --oneline -- src/api/. Restano due commit.
  3. Cerchiamo nel codice: git log -S "timeout" --oneline -- src/api/ trova il commit in cui è cambiato il valore del timeout.
  4. Lo guardiamo per intero: git show 1c02e8f. Dal diff si vede che il timeout è stato ridotto da 30 a 5 secondi, e il messaggio spiega «velocizziamo la risposta della UI».
  5. Controlliamo chi altro ha toccato quella riga: git blame -L :build_session src/api/client.py.

Da qui la soluzione è ingegneristica: ripristinare il valore, spostare il timeout nelle impostazioni o annullare il commit con git revert. Se invece i commit sono centinaia e trovare il colpevole a occhio è impossibile, viene in aiuto git bisect: una ricerca binaria nella cronologia che in pochi passi indica il commit che ha rotto il comportamento.

Impostazioni che semplificano la vita

git config --global log.date iso            # formato delle date in log
git config --global diff.colorMoved zebra   # evidenziare le righe spostate nel diff
git config --global core.pager "less -FRX"  # non aprire il pager per output brevi

Se l'output deve essere elaborato da uno script, disattivate colori e pager: git --no-pager log --format="%H %s" --no-color. Per l'elaborazione automatica usate l'hash completo %H: i prefissi brevi col tempo possono diventare ambigui in un repository grande.

git log con i filtri --oneline, --graph, --author, -S e i percorsi risponde alla domanda «cosa è successo». git diff confronta cartella di lavoro, index e commit: l'importante è ricordare cosa confronta per impostazione predefinita. git show apre un singolo commit o una vecchia versione di un file, e git blame porta da una riga di codice alla decisione che l'ha generata. La lettura della cronologia e la navigazione tra i commit sono affrontate in pratica nel corso su Git.

Domande frequenti

Come uscire da git log?

Premete q: l'output è aperto nel pager less. Per stampare senza pager usate git --no-pager log oppure il flag -n con un numero piccolo.

Come vedere la cronologia di un file eliminato?

Eseguite git log --oneline -- percorso/del/file (con il doppio trattino), e per il contenuto prima dell'eliminazione git show &lt;hash&gt;^:percorso/del/file.

Come confrontare un branch locale con quello remoto?

Prima git fetch, poi git diff origin/main oppure git log origin/main..HEAD per vedere i vostri commit non ancora inviati.

Esiste una visualizzazione grafica della cronologia?

Sì, insieme a Git viene fornito gitk, e il grafo della cronologia è integrato in VS Code, negli IDE JetBrains e nelle interfacce web di GitHub e GitLab.

Perché git diff non mostra nulla?

Molto probabilmente le modifiche sono già state aggiunte all'index con git add: guardate git diff --staged. I nuovi file non tracciati git diff non li mostra affatto.

Impara l’argomento in video

Questo argomento è trattato in modo approfondito, con pratica, nel corso «Git da zero a sviluppatore sicuro».

Vai al corso