Av: Mattias Wallander
2017-11-17
Hitta buggen med git bisect
Häromdagen hittade vi en riktig dålig bugg som under vissa omständigheter tyngde ner webbläsarfliken så pass mycket att den behövde dödas. Jag var glad att Firefox nyligen delade upp sidinnehåll och webbläsargränssnittet i olika trådar.
Vi visste att vi inte hade det här problemet förut men hur skulle vi kunna hitta var buggen hade uppstått utan att det skulle krävas en massa manuellt arbete? Det var då jag mindes ett git-kommando en kollega på ett tidigare projekt regelbundet lovordade. Det var git bisect.
git bisect är ett kommando som hjälper dig att hitta den specifika commit där ett problem sågs första gången. Det fungerar genom att göra en binärsökning från två startpositioner, en där buggen finns och en där buggen inte finns.
Skillnaden mellan linjär och binär sökning är O(n) mot O(log n). Det betyder att för, säg, ett tusen punkter kommer den linjära sökningen i värsta fall kolla igenom alla ett tusen punkter. Men den binära sökningen behöver bara kolla ~10 punkter. Du kanske inte har ett tusen commits att gå igenom men det kommer göra skillnad även på en mindre skala.
Låt oss testa detta. Starta sökningen genom att köra följande:
git bisect start
Nästa sak du behöver göra är att hitta två commits där en är dålig (den har buggen) och en är bra (den har inte buggen). Givet att buggen finns där du står på nuvarande branch, kör detta:
git bisect bad
Vill du använda en annan commit är det bara att lägga till dess hash på slutet av kommandot.
Sen behöver du hitta en commit där buggen ännu inte har introducerats. Eftersom binära sökningen är rätt snabb skulle jag säga att du inte behöver finjustera det här valet. Gå bara tillbaka till första stället du hittar och kör sedan:
git bisect good 234bcd
Efter du kört detta kommer git göra jobbet och du behöver bara svara ifall en commit är bra eller dålig. Git kommer självt hämta ut en ny commit som du validerar eller invaliderar för att sen spara svaret genom att antingen köra git bisect good eller git bisect bad. Efter varje kommando kommer git checka ut en ny commit enligt den binära sökningen. Efter ett tag kommer den rapportera att den hittat den commit som introducerade buggen så att du kan göra det som behövs för att fixa problemet.
För att avsluta och gå tillbaka till där du var innan du startade, kör följande kommando. Det kan du även göra om du skulle vilja avbryta proceduren i förtid.
git bisect reset
Nästa gång du stöter på en ny bugg som du vet inte fanns där tidigare, prova git bisect och se hur mycket snabbare det går att hitta orsaken!