2012-10-06 22 views
5

Sono nuovo di git e ho appena scoperto "git bisect". Come viene generalmente utilizzato quando è possibile verificare l'errore utilizzando un test dell'unità appena scritto (che non era in anticipo)?Come utilizzare git bisect: utilizzando i test unitari per determinare il commit errorneous?

Diciamo che abbiamo un repository contenente test unitari, ma - come così spesso - non erano completi. In alcune versioni scopriamo che una funzione non funziona, ma sappiamo che prima era in qualche versione. Sfortunatamente quella funzione non è stata verificata da un test unitario. Quello che mi piacerebbe fare ora è:

  1. Scrivi il caso di test (che fallisce in un primo momento, naturalmente)
  2. Cercare il commit introdurre l'errore utilizzando git bisect utilizzando questo tipo di test
  3. Correzione della errore e commit della correzione (e del test case)

Questo caso d'uso presenta un problema. Come git bisect verifica le vecchie versioni, il test case appena inserito non sarà lì, quindi non posso usarlo per verificare l'errore. Posso provare a non eseguire il test, ma a mantenerlo come cambio locale. Ma immaginando che il file di test sia stato modificato in alcune versioni tra di loro, probabilmente correrò in conflitti di fusione.

Quindi cosa fare? Come viene generalmente utilizzato il bisect di Git?

risposta

9

Di solito uso il bisect per identificare quando è stato introdotto un bug, in modo che possa guardare un singolo commit per la causa di un errore. Questo è utile quando so che qualcosa è abituato a funzionare e ora no. Per prima cosa scelgo o trovo un vecchio commit che funzionasse, contrassegnalo con git bisect good, segnalo con git bisect bad, quindi lavoriamo attraverso il bisect finché git non mi dice il commit che ha introdotto il problema. A volte posso scrivere il test unitario prima di iniziare questo processo, a volte non riesco a scriverlo fino a quando non ho visto il codice che ha introdotto il bug.

Quindi, diciamo che ho il test dell'unità, o qualche altro pezzo di codice o script che ho bisogno di usare in ogni punto durante il processo di git bisect. Lo stash è utile per tenerlo premuto mentre me ne vado. Quindi,

git stash save blah 
git bisect bad (and now I'm on a new commit) 
git stash pop 
mvn clean test 

git stash save blah 
git bisect good 
git stash pop 
mvn clean test 

e così via.

2

In primo luogo, prima di provare questo, assicurarsi che il git status è pulito - sto suggerendo utilizzando uno script che avrebbe invocare git reset --hard, quindi eventuali modifiche non sarebbe perso.

Un modo per fare ciò è copiare prima il codice sorgente per i test più recenti in un percorso che non è mai stato tracciato nella cronologia del repository (o da qualche parte al di fuori del repository). Poi scrivere uno script che:

  1. Copie delle prove più recenti in posizione nel proprio albero dei sorgenti
  2. esegue i test, risparmiando il codice di ritorno.
  3. Does un git reset --hard di spazzare via i cambiamenti dal punto 1
  4. Esce con il codice di ritorno salvati dal 2.

Poi, dopo aver segnato due commit come buono e cattivo per dare git bisect un posto da cui partire, è possibile utilizzare git bisect run YOUR-SCRIPT per trovare il primo commit in cui i test unitari più recenti avrebbero avuto esito negativo.

Questo metodo è essenzialmente ciò che è suggerito in the documentation for git bisect run, in cui si dice:

Si può trovare spesso che durante una sessione di bisect si desidera avere modifiche temporanee (ad esempio s/# define DEBUG 0/# define DEBUG 1/in un file di intestazione, o "la revisione che non ha questo commit richiede questa patch applicata per aggirare un altro problema questa bisection non è interessata a") applicata alla revisione in fase di test.

Per far fronte a tale situazione, dopo che la bisitica interna ha individuato la prossima revisione da testare, lo script può applicare la patch prima della compilazione, eseguire il test reale e successivamente decidere se la revisione (eventualmente con la patch necessaria) passato il test e poi riavvolgere l'albero allo stato originario. Infine, lo script dovrebbe uscire con lo stato del test reale per consentire al ciclo di comando "git bisect run" di determinare l'esito finale della sessione di bisect.

1

Non hai menzionato quale tecnologia stai usando, quindi userò Ruby come esempio, che è quello che mi è più familiare. Lo stesso principio dovrebbe applicarsi anche ad altre tecnologie.

  1. Posizionare l'aggiornati file di test al di fuori della directory del progetto. Qui darò per scontato che sia il /tmp/my_test.rb

  2. Dentro il repository, creare un piccolo script di shell, ad esempio, test_runner.sh:

    #!/usr/bin/env sh  
    cp -f /tmp/my_test.rb test/my_test.rb # This will potentially overwrite some old test file 
    ruby test/my_test.rb # Change for whatever test runner you use 
    test_result=$? 
    git checkout test/my_test.rb # Undoes any changes that might have been made 
    exit $test_result 
    
  3. Mark impegna come buono/cattivo, come si fa di solito con bisect.

  4. Utilizzare git bisect run test_runner.sh e andare a prendere una tazza di caffè mentre git trova il bug per voi.

Problemi correlati