Comment pourrais-je utiliser git bisect pour trouver le premier bon commit?

90

J'ai le problème suivant:

  • la version masterfonctionne bien
  • la version de la dernière balise avant master(disons last) a un bogue
  • un collègue a besoin d'un correctif pour sa lastrévision pour ce bogue précis

D'accord. Demandons à notre ami git bisectla révision qui a corrigé le bogue:

git bisect start
git bisect bad last
git bisect good master

Mais cela ne fonctionnera pas:

Certains bons régimes ne sont pas les ancêtres des mauvais régimes.
git bisect ne peut pas fonctionner correctement dans ce cas.
Peut-être confondez-vous les bons et les mauvais régimes?

Des conseils pour surmonter cela? Ai-je manqué quelque chose dans la documentation?

eckes
la source
1
Je cours git bisect run ...pour automatiser la bissectrice. Je n'ai donc aucune chance d'échanger les mots goodet bad(c'était trop évident). Comment utiliser runpour trouver la première bonne révision?
Daniel Böhmer
@ DanielBöhmer: vous devez permuter les termes à l' intérieur de votre script en cours d'exécution, n'est-ce pas?
eckes
Le script exécuté par git bisect runrenvoie bon ou mauvais en tant que code de sortie, pas en tant que chaîne. Voir ma réponse que je viens de publier ci-dessous.
Daniel Böhmer
@ DanielBöhmer: eh bien, dans ce cas, vous devrez inverser le code de retour, n'est-ce pas?
eckes
C'est exact, c'est ce qui est décrit dans ma réponse.
Daniel Böhmer

Réponses:

98

Depuis git 2.7, vous pouvez utiliser les arguments --term-old et --term-new.

Par exemple, vous pouvez identifier un commit de résolution de problèmes ainsi:

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

Au fur et à mesure que vous testez, dites git bisect fixedou git bisect unfixedselon le cas.

Ancienne réponse, pour les versions de git antérieures à 2.7

Au lieu de vous entraîner temporairement à penser que mauvais signifie bon et bon signifie mauvais, pourquoi ne pas créer des alias?

En ~/.gitconfigajouter ce qui suit:

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

Vous pouvez commencer à identifier un commit de résolution de problèmes ainsi:

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

Au fur et à mesure que vous testez, dites git bisect-fixedou git bisect-unfixedselon le cas.

Michael Wolf
la source
5
En passant, git ne vous permet pas de créer des alias de sous-commandes. D'où les tirets. Si cela est réellement (ou rendu) possible, nous espérons que quelqu'un mettra à jour la réponse.
Michael Wolf
3
Même si vous utilisez des alias, la sortie de git ne le sera pas, donc elle rapportera toujours foo is the first bad commit, il semble donc qu'une formation temporaire soit toujours nécessaire, non?
ThomasW
2
Bon point. (J'ai voté pour votre commentaire.) Même si tout va bien, c'est au moins un peu moins de charge cognitive supplémentaire à gérer, et en tant que programmeurs, nous en avons déjà beaucoup.
Michael Wolf
1
Je recommande d'utiliser les alias «avant» et «après». De cette façon, vous n'avez pas la charge cognitive de faire l'inversion "quand je vois le bogue, je devrais écrire" bien ""; au lieu de cela, vous avez seulement la surcharge - probablement plus petite - de vous souvenir que vous recherchez l'apparition / la disparition d'un bogue (c'est-à-dire de vous souvenir du type de changement que vous recherchez - «avant quoi?»).
Jonas Kölker
1
@ JonasKölker, c'est une excellente idée. J'ai utilisé les alias suggérés dans la réponse, ainsi que bisect-after = bisect badet bisect-before = bisect good, conformément à votre recommandation. Maintenant, je peux utiliser l'un ou l'autre ensemble d'alias. Nous verrons ce que je finis par privilégier le plus après quelques utilisations.
Gabriel Staples
47

Je "tricherais" simplement et j'échangerais les significations du bon <=> mauvais.

En d'autres termes, considérez «mauvaise» comme quelque chose qui ne présente pas le problème, donc ce n'est pas la «bonne» version sur laquelle baser votre patch.

De toute façon, le bien et le mal sont des concepts assez subjectifs, non? :)

git bisect start
git bisect good last
git bisect bad master
inger
la source
2
Eh bien, si vous y réfléchissez, il n'y a pas de signification générale de ce qui est bon ou mauvais (probablement même pas en religion) .. cela dépend juste de vos objectifs. De cette façon, ce n'est pas vraiment de la triche - mais peut-être le péché de Git (pour rester sur le sujet religieux: D est de prendre un terme aussi controversé plutôt qu'un "objectif" / "origine" plus neutre ... Mais oui, la philosophie peut être l'esprit- ahurissant ;-)
inger
Ce doit être la toute première fois que j'entends dire que les bugs peuvent être "bons".
MarcH
1
C'est ce que j'ai fait avant de trouver cette question. Je ne vais plus le faire. Rappelez-vous, il suffit d'une seule mauvaise réponse avant que toute la bissection ne tourne mal. Ne vous tordez pas l'esprit.
proski du
20

Si vous utilisez git bisect runcomme je l'ai fait avec la provecommande de Perl (qui exécute des tests automatiques), vous n'avez aucune chance de simplement échanger goodet bad. Le succès des tests sera signalé comme code de sortie.

J'ai trouvé une syntaxe Bash valide pour annuler le code de sortie du programme exécuté par 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"

Cela m'a donné la première révision pour réussir les tests effectués prove.

Daniel Böhmer
la source
Je suis d'accord, je préfère ne pas modifier mon cas de test donc c'est parfait.
seanlinsley
8

Git vous permet maintenant de les utiliser oldet newsans les définir au préalable. Vous devez appeler git bisect startsans commits comme arguments supplémentaires, puis démarrer correctement la bissection en appelant

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

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

C'est essentiellement ce que @MarcH suggérait de mettre en œuvre.

GKFX
la source
1
C'est la réponse la plus pertinente (pour git moderne). Et la commande de démarrage devrait être (selon le lien que vous avez partagé):git bisect start --term-new fixed --term-old broken
Sam Protsenko
Vrai. Quand ces options ont-elles été introduites? J'aimerais mettre à jour ma réponse.
Michael Wolf
@MichaelWolf Ils sont apparus dans la version 2.7.0 .
GKFX
6

Les alias Git sont une bonne idée, mais les termes fixedet unfixedont le même problème que goodet bad: vous ne pouvez pas les rendre compatibles avec les régressions et les progressions. Il est facile de trouver des mots qui fonctionnent dans les deux sens: il suffit de les sélectionner dans la terminologie de recherche binaire originale qui est de nature neutre sans préjugé de ce qui est bon ou mauvais. Par exemple:

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

Avec des termes neutres comme ceux-ci, vous pouvez toujours taper: git bisect-high(ou git bisect-upper, ou git-bisect max, ... votre choix!) Si vous recherchez une régression ou une correction .

Dommage que les développeurs de git bisect ne puissent pas simplement réutiliser l'un des termes existants. L'interface utilisateur n'est pas la préoccupation de git en général: http://stevebennett.me/2012/02/24/10-things-i-hate-about-git/

Mars
la source
De: git.github.io/rev_news/2015/07/08/edition-5 "Certaines séries de patchs sont en cours de polissage pour permettre à git bisect d'utiliser une paire arbitraire de termes au lieu de bons et mauvais, ..."
MarcH