git bisect
Impara il comando git bisect per cercare in modo binario la cronologia dei commit e trovare esattamente quale commit ha introdotto un bug. Include l'automazione con run.
Il comando git bisect ti aiuta a trovare l'esatto commit che ha introdotto un bug eseguendo una ricerca binaria attraverso la cronologia. Indichi a Git un commit in cui il codice funzionava ("good") e uno in cui è rotto ("bad"), e Git esegue il checkout del punto intermedio perché tu lo testi, dimezzando l'intervallo sospetto ogni volta finché rimane un unico responsabile.
Questo capitolo spiega come eseguire manualmente una sessione di bisect, come leggere il progresso che Git stampa dopo ogni risposta, come automatizzare l'intera ricerca con un comando di test, come saltare i commit non testabili e come recuperare in caso di errore.
Definizione
Perché la ricerca binaria
Se un bug è comparso da qualche parte negli ultimi 1.000 commit, controllarli uno per uno sarebbe estenuante. La ricerca binaria ha bisogno di soli circa dieci test per individuare il colpevole, perché ogni risposta dimezza i candidati rimanenti — circa log2(N) passi per N commit. git bisect automatizza la contabilità in modo che tu debba solo rispondere "funziona qui?"
Avviare una sessione di bisect
Avvia la sessione, poi contrassegna lo stato attuale rotto e un commit passato noto come buono:
git bisect start
git bisect bad # the current commit is broken
git bisect good v1.4.0 # this tag was known to workGit esegue il checkout di un commit a metà strada tra i due. Compili e testi quella revisione, poi riporti il risultato:
git bisect good # this commit works — bug is newer
# or
git bisect bad # this commit is broken — bug is here or olderDopo ogni risposta Git stampa quanto dell'intervallo rimane ed esegue il checkout del prossimo punto intermedio:
Bisecting: 7 revisions left to test after this (roughly 3 steps)
[a1b2c3d4...] Refactor the parserRipeti il ciclo test-e-marca finché Git annuncia il primo commit difettoso:
a1b2c3d4 is the first bad commit
commit a1b2c3d4...
Refactor the parserLeggere il risultato con git bisect log
In qualsiasi momento puoi consultare le risposte che hai fornito finora. È utile anche per conservare un registro della sessione:
git bisect logSe sospetti di aver contrassegnato erroneamente un commit, reimposta e riproduci un log corretto invece di ricominciare da capo:
git bisect log > bisect-run.txt # edit out the mistaken line
git bisect reset
git bisect replay bisect-run.txtTerminare la sessione
Quando Git segnala il colpevole, torna al punto di partenza:
git bisect resetQuesto ripristina HEAD al branch su cui ti trovavi prima del bisect.
Automazione con git bisect run
Se puoi esprimere il test come uno script o un comando che termina con 0 per buono e con valore non zero per cattivo, Git eseguirà l'intera ricerca in modo automatico:
git bisect start HEAD v1.4.0
git bisect run npm testGit esegue il checkout di ogni punto intermedio, lancia il comando, interpreta il codice di uscita e si ferma al primo commit che fallisce — senza marcature manuali.
Il comando può essere qualsiasi eseguibile: una riga singola, uno script shell o un binario. Il codice di uscita 0 significa buono, qualsiasi codice tra 1 e 127 (eccetto 125) significa cattivo. Il codice di uscita speciale 125 indica a Git che il commit non può essere testato ed equivale a eseguire git bisect skip — usalo quando la build stessa è rotta a quella revisione:
#!/bin/sh
# test.sh — skip commits that don't even compile
make || exit 125
./run-the-failing-case # exits non-zero when the bug is presentgit bisect start HEAD v1.4.0
git bisect run ./test.shgit bisect run deve essere idempotente e autonomo. Se il test lascia artefatti di build o file modificati, aggiungi un passaggio di pulizia in modo che il checkout successivo parta da zero — altrimenti un binario obsoleto può far sembrare difettoso un commit buono.Saltare i commit che non puoi testare
A volte il commit estratto è rotto per un motivo non correlato — non compila, o manca una dipendenza — quindi non puoi sinceramente dire "buono" o "cattivo". Dì a Git di metterlo da parte:
git bisect skipGit sceglie un commit vicino e continua a restringere l'intervallo. Se troppi commit in una regione vengono saltati, Git potrebbe segnalare un intervallo di candidati invece di un singolo commit.
Opzioni comuni
| Comando | Descrizione |
|---|---|
git bisect start | Avvia una sessione di bisect. |
git bisect bad [<commit>] | Contrassegna un commit come rotto (predefinito: quello corrente). |
git bisect good [<commit>] | Contrassegna un commit come funzionante. |
git bisect skip | Salta un commit che non può essere testato (ad esempio, non compila). |
git bisect run <cmd> | Automatizza la ricerca usando il codice di uscita di un comando di test. |
git bisect log | Stampa le risposte buone/cattive fornite finora. |
git bisect replay <file> | Riproduce un log di bisect salvato. |
git bisect reset | Termina la sessione e ripristina il HEAD originale. |
Comandi correlati
Una volta che bisect individua il colpevole, questi comandi ti aiutano a esaminarlo e ad agire:
- git show — visualizza le modifiche esatte introdotte dal commit difettoso.
- git blame — mostra quale commit ha modificato per ultimo una riga specifica.
- git log — sfoglia la cronologia in cui bisect ha cercato.
- git revert — annulla il commit difettoso senza riscrivere la cronologia.
- git checkout — come Git sposta
HEAD, che bisect utilizza internamente.