git-bisect(1): Skillnad mellan sidversioner
Admin (diskussion | bidrag) (Skapade sidan med '{{manpage|section=1|title=git-bisect}} == NAMN == git-bisect - Använd binärsökning för att hitta den commit som introducerade ett fel == SYNOPSIS == '''git bisect''' <underkommando> <alternativ> == BESKRIVNING == Kommandot tar olika underkommandon och olika alternativ beroende på underkommandot: * git bisect start [--term-(bad|new)=<term-new> --term-(good|old)=<term-old>] [--no-checkout] [--first-parent] [<bad> [<good>...]] [--] [<sökvägsspecifikation>...] * gi...') |
(Ingen skillnad)
|
Versionen från 9 april 2025 kl. 05.10
NAMN
git-bisect - Använd binärsökning för att hitta den commit som introducerade ett fel
SYNOPSIS
git bisect <underkommando> <alternativ>
BESKRIVNING
Kommandot tar olika underkommandon och olika alternativ beroende på underkommandot:
- git bisect start [--term-(bad|new)=<term-new> --term-(good|old)=<term-old>] [--no-checkout] [--first-parent] [<bad> [<good>...]] [--] [<sökvägsspecifikation>...]
- git bisect (bad|new|<term-new>) [<rev>]
- git bisect (good|old|<term-old>) [<rev>...]
- git bisect terms [--term-(good|old) | --term-(bad|new)]
- git bisect skip [(<rev>|<intervall>)...]
- git bisect reset [<commit>]
- git bisect (visualize|view)
- git bisect replay <loggfil>
- git bisect log
- git bisect run <cmd> [<arg>...]
- git bisect help
Detta kommando använder en binärsökningsalgoritm för att hitta vilken commit i ditt projekts historik som introducerade ett fel. Du använder det genom att först tala om för det en "dålig" commit som är känd för att innehålla felet, och en "bra" commit som är känd för att vara innan felet introducerades. Sedan väljer git bisect en commit mellan dessa två ändpunkter och frågar dig om den valda commiten är "bra" eller "dålig". Det fortsätter att minska intervallet tills det hittar exakt den commit som introducerade ändringen.
Faktum är att git bisect kan användas för att hitta den commit som ändrade vilken som helst egenskap hos ditt projekt; t.ex. den commit som fixade ett fel, eller den commit som gjorde att ett benchmarks prestanda förbättrades. För att stödja denna mer generella användning kan termerna "old" och "new" användas istället för "good" och "bad", eller så kan du välja dina egna termer. Se avsnittet "Alternativa termer" nedan för mer information.
Grundläggande bisect-kommandon: start, bad, good
Antag till exempel att du försöker hitta den commit som bröt en funktion som var känd för att fungera i version v2.6.13-rc2 av ditt projekt. Du startar en bisect-session på följande sätt:
$ git bisect start $ git bisect bad # Aktuell version är dålig $ git bisect good v2.6.13-rc2 # v2.6.13-rc2 är känd för att vara bra
När du har angett minst en dålig och en bra commit, väljer git bisect en commit i mitten av det historikintervallet, checkar ut den och matar ut något liknande följande:
Bisecting: 675 revisions left to test after this (roughly 10 steps)
Du bör nu kompilera den utcheckade versionen och testa den. Om den versionen fungerar korrekt, skriv
$ git bisect good
Om den versionen är trasig, skriv
$ git bisect bad
Då kommer git bisect att svara med något liknande
Bisecting: 337 revisions left to test after this (roughly 9 steps)
Fortsätt upprepa processen: kompilera trädet, testa det och beroende på om det är bra eller dåligt, kör git bisect good eller git bisect bad för att be om nästa commit som behöver testas.
Slutligen kommer det inte att finnas några fler revisioner kvar att inspektera, och kommandot kommer att skriva ut en beskrivning av den första dåliga commiten. Referensen refs/bisect/bad kommer att lämnas pekande på den commiten.
Bisect reset
Efter en bisect-session, för att rensa upp bisektionsstatusen och återgå till den ursprungliga HEAD, utfärda följande kommando:
$ git bisect reset
Som standard kommer detta att återställa ditt träd till den commit som var utcheckad innan git bisect start. (En ny git bisect start kommer också att göra det, eftersom den rensar upp den gamla bisektionsstatusen.)
Med ett valfritt argument kan du istället återgå till en annan commit:
$ git bisect reset <commit>
Till exempel kommer git bisect reset bisect/bad att checka ut den första dåliga revisionen, medan git bisect reset HEAD kommer att lämna dig på den aktuella bisektions-commiten och undvika att byta commits alls.
Alternativa termer
Ibland letar du inte efter den commit som introducerade ett brott, utan snarare efter en commit som orsakade en förändring mellan något annat "gammalt" tillstånd och "nytt" tillstånd. Till exempel kanske du letar efter den commit som introducerade en viss fix. Eller du kanske letar efter den första commiten där källkodsfilnamnen slutligen alla konverterades till ditt företags namngivningsstandard. Eller vad som helst.
I sådana fall kan det vara mycket förvirrande att använda termerna "bra" och "dåligt" för att hänvisa till "tillståndet före förändringen" och "tillståndet efter förändringen". Så istället kan du använda termerna "old" och "new" i stället för "good" och "bad". (Men observera att du inte kan blanda "good" och "bad" med "old" och "new" i en enda session.)
I denna mer generella användning förser du git bisect med en "ny" commit som har någon egenskap och en "gammal" commit som inte har den egenskapen. Varje gång git bisect checkar ut en commit testar du om den commiten har egenskapen. Om den har det, markera commiten som "new"; annars, markera den som "old". När bisektionen är klar kommer git bisect att rapportera vilken commit som introducerade egenskapen.
För att använda "old" och "new" istället för "good" och bad, måste du köra git bisect start utan commits som argument och sedan köra följande kommandon för att lägga till commits:
git bisect old [<rev>]
för att indikera att en commit var före den sökta förändringen, eller
git bisect new [<rev>...]
för att indikera att den var efter.
För att få en påminnelse om de termer som används för närvarande, använd
git bisect terms
Du kan bara få den gamla termen med git bisect terms --term-old eller git bisect terms --term-good; git bisect terms --term-new och git bisect terms --term-bad kan användas för att lära dig hur du kallar de commits som är nyare än den sökta förändringen.
Om du vill använda dina egna termer istället för "bad"/"good" eller "new"/"old", kan du välja vilka namn du vill (förutom befintliga bisect-underkommandon som reset, start, ...) genom att starta bisektionen med
git bisect start --term-old <term-old> --term-new <term-new>
Om du till exempel letar efter en commit som introducerade en prestandaregression kan du använda
git bisect start --term-old fast --term-new slow
Eller om du letar efter den commit som fixade ett fel kan du använda
git bisect start --term-new fixed --term-old broken
Använd sedan git bisect <term-old> och git bisect <term-new> istället för git bisect good och git bisect bad för att markera commits.
Bisect visualize/view
För att se de för närvarande misstänkta i gitk, utfärda följande kommando under bisektionsprocessen (underkommandot view kan användas som ett alternativ till visualize):
$ git bisect visualize
Git detekterar en grafisk miljö genom olika miljövariabler: DISPLAY, som är inställd i X Window System-miljöer på Unix-system. SESSIONNAME, som är inställd under Cygwin i interaktiva skrivbordssessioner. MSYSTEM, som är inställd under Msys2 och Git för Windows. SECURITYSESSIONID, som kan vara inställd på macOS i interaktiva skrivbordssessioner.
Om ingen av dessa miljövariabler är inställd används istället git log. Du kan också ange kommandoradsalternativ som -p och --stat.
$ git bisect visualize --stat
Bisect log och bisect replay
Efter att ha markerat revisioner som bra eller dåliga, utfärda följande kommando för att visa vad som har gjorts hittills:
$ git bisect log
Om du upptäcker att du har gjort ett misstag när du angav status för en revision, kan du spara utdata från detta kommando till en fil, redigera den för att ta bort felaktiga poster och sedan utfärda följande kommandon för att återgå till ett korrigerat tillstånd:
$ git bisect reset $ git bisect replay den-filen
Undvika att testa en commit
Om du mitt i en bisect-session vet att den föreslagna revisionen inte är bra att testa (t.ex. den misslyckas med att bygga och du vet att felet inte har något att göra med det fel du jagar), kan du manuellt välja en närliggande commit och testa den istället.
Till exempel:
$ git bisect good/bad # föregående runda var bra eller dålig.
Bisecting: 337 revisions left to test after this (roughly 9 steps)
$ git bisect visualize # oj, det är ointressant.
$ git reset --hard HEAD~3 # försök 3 revisioner före vad
# som föreslogs
Kompilera och testa sedan den valda revisionen och markera därefter revisionen som bra eller dålig på vanligt sätt.
Bisect skip
Istället för att välja en närliggande commit själv kan du be Git att göra det åt dig genom att utfärda kommandot:
$ git bisect skip # Aktuell version kan inte testas
Men om du hoppar över en commit som ligger intill den du letar efter, kommer Git inte att kunna säga exakt vilken av dessa commits som var den första dåliga.
Du kan också hoppa över ett intervall av commits istället för bara en commit, med hjälp av intervallnotation. Till exempel:
$ git bisect skip v2.5..v2.6
Detta talar om för bisect-processen att ingen commit efter v2.5, upp till och inklusive v2.6, bör testas.
Observera att om du också vill hoppa över den första commiten i intervallet skulle du utfärda kommandot:
$ git bisect skip v2.5 v2.5..v2.6
Detta talar om för bisect-processen att commits mellan v2.5 och v2.6 (inklusive) ska hoppas över.
Minska bisektionen genom att ge fler parametrar till bisect start
Du kan ytterligare minska antalet försök om du vet vilken del av trädet som är involverad i problemet du spårar genom att ange sökvägsspecifikationsparametrar när du utfärdar kommandot bisect start:
$ git bisect start -- arch/i386 include/asm-i386
Om du i förväg känner till mer än en bra commit kan du minska bisektionsutrymmet genom att ange alla bra commits omedelbart efter den dåliga commiten när du utfärdar kommandot bisect start:
$ git bisect start v2.6.20-rc6 v2.6.20-rc4 v2.6.20-rc1 --
# v2.6.20-rc6 är dålig
# v2.6.20-rc4 och v2.6.20-rc1 är bra
Bisect run
Om du har ett skript som kan avgöra om den aktuella källkoden är bra eller dålig kan du göra en bisektion genom att utfärda kommandot:
$ git bisect run mitt_skript argument
Observera att skriptet (mitt_skript i exemplet ovan) ska avslutas med koden 0 om den aktuella källkoden är bra/gammal, och avslutas med en kod mellan 1 och 127 (inklusive), förutom 125, om den aktuella källkoden är dålig/ny.
Varje annan avslutskod kommer att avbryta bisect-processen. Det bör noteras att ett program som avslutas via exit(-1) lämnar $? = 255, (se manualsidan för exit(3)), eftersom värdet trunkeras med & 0377.
Den speciella avslutskoden 125 bör användas när den aktuella källkoden inte kan testas. Om skriptet avslutas med denna kod kommer den aktuella revisionen att hoppas över (se git bisect skip ovan). 125 valdes som det högsta rimliga värdet att använda för detta ändamål, eftersom 126 och 127 används av POSIX-skal för att signalera specifik felstatus (127 är för kommando hittades inte, 126 är för kommando hittades men är inte körbart – dessa detaljer spelar ingen roll, eftersom de är normala fel i skriptet, så långt som bisect run berörs).
Du kan ofta upptäcka att du under en bisect-session vill ha tillfälliga modifieringar (t.ex. s/#define DEBUG 0/#define DEBUG 1/ i en header-fil, eller "revision som inte har denna commit behöver denna patch applicerad för att kringgå ett annat problem som denna bisektion inte är intresserad av") applicerade på den revision som testas.
För att hantera en sådan situation kan skriptet, efter att den inre git bisect hittar nästa revision att testa, applicera patchen innan kompilering, köra det verkliga testet och därefter avgöra om revisionen (eventuellt med den nödvändiga patchen) klarade testet och sedan återställa trädet till det ursprungliga tillståndet. Slutligen bör skriptet avslutas med statusen för det verkliga testet för att låta kommandoloopen git bisect run bestämma det slutliga resultatet av bisect-sessionen.
ALTERNATIV
- --no-checkout
- Checka inte ut det nya arbetsträdet vid varje iteration av bisektionsprocessen. Uppdatera istället bara referensen med namnet BISECT_HEAD så att den pekar på den commit som ska testas.
- Detta alternativ kan vara användbart när testet du skulle utföra i varje steg inte kräver ett utcheckat träd.
- Om arkivet är bart antas --no-checkout.
- --first-parent
- Följ endast den första föräldra-commiten när en merge-commit påträffas.
- Vid detektering av regressioner som introducerats genom sammanslagning av en gren kommer merge-commiten att identifieras som introduktionen av felet och dess förfäder kommer att ignoreras.
- Detta alternativ är särskilt användbart för att undvika falska positiva resultat när en sammanslagen gren innehöll trasiga eller icke-byggbara commits, men själva sammanslagningen var OK.
EXEMPEL
- Automatiskt bisecta en trasig byggnation mellan v1.2 och HEAD:
$ git bisect start HEAD v1.2 -- # HEAD är dålig, v1.2 är bra $ git bisect run make # "make" bygger applikationen $ git bisect reset # avsluta bisect-sessionen
- Automatiskt bisecta ett testfel mellan origin och HEAD:
$ git bisect start HEAD origin -- # HEAD är dålig, origin är bra $ git bisect run make test # "make test" bygger och testar $ git bisect reset # avsluta bisect-sessionen