Come posso usare git bisect per trovare il primo BUON commit?


90

Ho il seguente problema:

  • la versione masterfunziona bene
  • la versione dell'ultimo tag prima master(diciamo last) ha un bug
  • un collega ha bisogno di una patch per la sua lastrevisione per quel determinato bug

Va bene. Chiediamo al nostro amico git bisectla revisione che ha risolto il bug:

git bisect start
git bisect bad last
git bisect good master

Ma non funzionerà:

Alcuni buoni giri non sono antenati dei cattivi giri.
git bisect non può funzionare correttamente in questo caso.
Forse sbagli giri buoni e cattivi?

Qualche suggerimento per superare questo problema? Mi sono perso qualcosa nei documenti?


1
Sto correndo git bisect run ...per automatizzare la bisettrice. Quindi non ho la possibilità di scambiare le parole goode bad(era troppo ovvio). Come utilizzare runper trovare la prima buona revisione?
Daniel Böhmer

@ DanielBöhmer: devi scambiare i termini all'interno del tuo script in esecuzione, vero?
eckes il

Lo script eseguito da git bisect runrestituisce buono o cattivo come codice di uscita, non come stringa. Vedi la mia risposta che ho appena pubblicato di seguito.
Daniel Böhmer

@ DanielBöhmer: beh, in quel caso dovrai invertire il codice di ritorno, vero?
eckes il

Esatto, questo è ciò che è descritto nella mia risposta.
Daniel Böhmer

Risposte:


98

A partire da git 2.7, puoi usare gli argomenti --term-old e --term-new.

Ad esempio, puoi identificare un commit per la risoluzione dei problemi in questo modo:

git bisect start --term-new=fixed --term-old=unfixed
git bisect fixed master
git bisect unfixed $some-old-sha1

Mentre esegui il test, dì git bisect fixedo git bisect unfixedcome appropriato.

Vecchia risposta, per le versioni di git precedenti alla 2.7

Invece di allenarti temporaneamente a pensare che cattivo significa buono e buono significa cattivo, perché non creare degli alias?

In ~/.gitconfigaggiunta il seguente:

[alias]
        bisect-fixed = bisect bad
        bisect-unfixed = bisect good

Puoi iniziare a identificare un commit per la risoluzione dei problemi così:

$ git bisect start
$ git bisect-fixed master
$ git bisect-unfixed $some-old-sha1

Mentre esegui il test, dì git bisect-fixedo git bisect-unfixedcome appropriato.


5
Per inciso, git non ti consente di creare alias di sottocomandi. Da qui i trattini. Se effettivamente è (o è possibile), si spera che qualcuno aggiornerà la risposta.
Michael Wolf

3
Anche se usi gli alias, l'output di git non lo farà, quindi riporterà ancora foo is the first bad commit, quindi sembra che l'addestramento temporaneo sia ancora necessario, no?
ThomasW

2
Punto valido. (Ho votato positivamente il tuo commento). Anche se si spera che sia almeno un po 'meno carico cognitivo aggiuntivo da affrontare, e come programmatori ne abbiamo già molti.
Michael Wolf

1
Consiglio di utilizzare gli alias "prima" e "dopo". In questo modo non hai il sovraccarico cognitivo di fare l'inversione "quando vedo il bug, dovrei scrivere" buono ""; invece hai solo l'overhead - probabilmente più piccolo - di ricordare che stai cercando l'apparizione / scomparsa di un bug (cioè ricordare che tipo di cambiamento stai cercando - "prima di cosa?").
Jonas Kölker

1
@ JonasKölker, è un'ottima idea. Ho usato gli alias suggeriti nella risposta, così come bisect-after = bisect bade bisect-before = bisect good, secondo la tua raccomandazione. Ora posso utilizzare entrambi i set di alias. Vedremo quale finisco per privilegiare di più dopo pochi utilizzi.
Gabriel Staples

47

Vorrei solo "imbrogliare" git e scambiare significati di buono <=> cattivo.

In altre parole, considera "cattivo" come qualcosa che non presenta il problema, quindi questa non è la versione "buona" su cui basare la tua patch.

Bene e male sono comunque concetti piuttosto soggettivi, giusto? :)

git bisect start
git bisect good last
git bisect bad master

2
Beh, se ci pensi non c'è un significato generale di cosa sia buono o cattivo (probabilmente nemmeno nella religione) .. dipende solo dai tuoi scopi. In questo modo non è davvero un inganno, ma forse il peccato di Git (per rimanere sull'argomento religioso: D è prendere un termine così controverso piuttosto che un "obiettivo" / "origine" più neutrale .. Ma sì, la filosofia può essere la mente- sbalorditivo ;-)
inger

Questa deve essere la prima volta che sento che i bug possono essere "buoni".
MarcH

1
Questo è quello che ho fatto prima di trovare questa domanda. Non lo farò più. Ricorda, basta una risposta sbagliata prima che l'intera bisezione vada storta. Non distorcere la tua mente.
proski

20

Se stai usando git bisect runcome ho fatto io con il provecomando di Perl (che esegue test automatici) non hai possibilità solo di scambiare goode bad. Il successo dei test verrà segnalato come codice di uscita.

Ho trovato una sintassi Bash valida per negare il codice di uscita del programma eseguito da git bisect run:

git bisect start
git bisect bad HEAD                 # last revision known to PASS the tests
git bisect good $LAST_FAIL_REVISION # last revision known to FAIL the tests
git bisect run bash -c "! prove"

Questo mi ha dato la prima revisione per superare i test eseguiti prove.


Sono d'accordo, preferirei non modificare il mio caso di test, quindi è perfetto.
seanlinsley

8

Git ora ti consente di usarli olde newsenza prima definirli. Devi chiamare git bisect startsenza commit come ulteriori argomenti, quindi avviare correttamente la bisezione chiamando

git bisect old <rev>
git bisect new <rev>

https://git-scm.com/docs/git-bisect#_alternate_terms

Questo è essenzialmente ciò che @MarcH stava suggerendo di implementare.


1
Questa è la risposta più rilevante (per git moderno). E il comando di partenza dovrebbe essere (secondo il link che hai condiviso):git bisect start --term-new fixed --term-old broken
Sam Protsenko

Vero. Quando sono state introdotte queste opzioni? Vorrei aggiornare la mia risposta.
Michael Wolf

@MichaelWolf Sono apparsi nella versione 2.7.0 .
GKFX

6

Gli alias Git sono una buona idea, tuttavia i termini fixede unfixedhanno lo stesso problema di goode bad: non puoi farli essere compatibili sia con le regressioni che con le progressioni. È facile trovare parole che funzionano in entrambi i modi: è sufficiente prenderle dalla terminologia di ricerca binaria originale che è di natura neutra senza preconcetti su cosa sia buono o cattivo. Per esempio:

git config --global alias.bisect-high 'bisect bad'
git config --global alias.bisect-low  'bisect good'

Con termini neutri come questi puoi sempre digitare: git bisect-high(or git bisect-upper, or git-bisect max, ... your choice!) Se stai cercando una regressione o una correzione .

Peccato che gli sviluppatori di git bisect non potessero semplicemente riutilizzare nessuno dei termini esistenti. L'interfaccia utente non riguarda in generale git: http://stevebennett.me/2012/02/24/10-things-i-hate-about-git/


Da: git.github.io/rev_news/2015/07/08/edition-5 "Alcune serie di patch vengono perfezionate per consentire a git bisect di utilizzare una coppia arbitraria di termini invece di buoni e cattivi, ..."
MarcH
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.