modulo 07 / lezione 31
Casi reali, debugging della storia, recupero
git bisect: trovare il commit che ha rotto qualcosa
Usare la ricerca binaria automatica di Git per trovare il commit colpevole di una regressione.
git bisect: trovare il commit che ha rotto qualcosa
git bisect usa la ricerca binaria sulla storia del repository. Tu indichi un commit “bad”, dove il problema esiste, e un commit “good”, dove il problema non esisteva. Git sceglie commit intermedi, tu li classifichi, e in pochi passaggi restringe il campo fino al commit che ha introdotto la regressione.
Non serve provarli tutti. Su 128 commit, una ricerca binaria può arrivare al colpevole in circa 7 passaggi.
Perché questa lezione conta
Quando un bug appare “da qualche parte nelle ultime settimane”, il rischio è perdere ore leggendo diff casuali o accusando l’ultima modifica visibile. bisect trasforma l’indagine in una procedura ripetibile.
La qualità del risultato dipende dalla qualità del test. Se non sai riprodurre il bug in modo affidabile, bisect può portarti fuori strada.
Obiettivo operativo
Alla fine della lezione devi saper avviare un bisect manuale, automatizzarlo con uno script, interpretare good, bad e skip, e chiudere la sessione senza lasciare il repository in uno stato ambiguo.
Modello mentale
bad non significa “commit brutto”. Significa: in questo commit il comportamento è rotto.
good significa: in questo commit il comportamento era corretto.
Git assume che tra il good e il bad esista un primo commit che introduce la regressione. Se il bug è intermittente, dipende dall’ambiente o appare e scompare più volte, il modello si indebolisce.
Flusso manuale
Prima identifica un commit sicuramente rotto e uno sicuramente funzionante:
git log --oneline --decorate
Poi avvia:
git bisect start
git bisect bad HEAD
git bisect good v1.8.0
Git farà checkout di un commit intermedio. A quel punto esegui il test manuale:
npm test -- auth
Se il bug c’è:
git bisect bad
Se il bug non c’è:
git bisect good
Alla fine Git stampa il primo commit sospetto.
Chiudi sempre:
git bisect reset
Questo ti riporta al punto di partenza.
Automazione con bisect run
Il caso migliore è avere uno script che ritorna exit code corretti:
git bisect start
git bisect bad HEAD
git bisect good v1.8.0
git bisect run ./scripts/repro-auth-timeout.sh
Convenzione:
0 -> good, test passa
1 -> bad, test fallisce
125 -> skip, commit non testabile
Esempio:
#!/bin/sh
npm ci --silent >/dev/null 2>&1 || exit 125
npm test -- auth-timeout
Se il setup fallisce per motivi non legati al bug, usa 125. Altrimenti Git potrebbe classificare come “bad” un commit che semplicemente non installa le dipendenze nel tuo ambiente.
Quando non usarlo
Evita bisect quando:
- il bug non è riproducibile;
- il test dipende da servizi esterni instabili;
- il repository cambia schema o dipendenze in modo incompatibile;
- il range contiene molti commit non compilabili;
- sai già che il problema è in una modifica piccola e recente.
In questi casi prima crea una riproduzione affidabile o restringi il campo con log, issue e PR.
Laboratorio guidato
In un repo demo crea 12 commit. Nei primi il test passa, in uno introduci un bug, nei successivi aggiungi modifiche non correlate.
Procedura:
- scrivi un test o script che fallisce solo dopo il bug;
- marca
HEADcome bad; - marca il primo tag o commit stabile come good;
- esegui prima bisect manuale;
- ripeti con
git bisect run; - confronta numero di passaggi e risultato;
- chiudi con
git bisect reset.
Output atteso
Versiona nel progetto una procedura di debug:
Bug:
Comando di riproduzione:
Commit bad:
Commit good:
Script bisect:
Commit individuato:
Fix o revert proposto:
Errori comuni
Partire senza good noto. Se non sai quando funzionava, stai solo esplorando.
Usare un test intermittente. Bisect amplifica l’inaffidabilità.
Dimenticare bisect reset. Resti su un commit intermedio e rischi di lavorare nel punto sbagliato.
Confondere commit colpevole e autore colpevole. Il commit indica l’introduzione tecnica del comportamento, non racconta da solo decisioni, vincoli e contesto.
Checklist di verifica
- so avviare e chiudere
git bisect; - so scegliere good e bad affidabili;
- so scrivere uno script con exit code corretti;
- so usare
skipquando il commit non è testabile; - so trasformare il risultato in fix, revert o indagine successiva.
Collegamenti
- Modulo: Casi reali, debugging della storia, recupero - lezione 31 del corso.
- Si collega a
git log, test automatici e procedure di debugging.