Desenvolvimento

4 jan, 2010

Git: Localizando a origem de um bug através de busca binária entre os commits

Publicidade

No artigo de hoje, vamos abordar uma funcionalidade muito interessante do Git, a qual nos permite fazer uma busca binária no projeto procurando o commit exato onde o bug foi introduzido no projeto. 

Cenário: Você não é o único desenvolvedor que trabalha no projeto. Enquanto você trabalha em um branch, outras pessoas trabalham em outros branches, e no final todos fazem o merge no branch master. O merge é feito várias vezes por semana. Em um belo dia, uma funcionalidade que antes funcionava perfeitamente para de funcionar, mas ninguém sabe dizer quem foi o responsável por quebrar aquela parte da aplicação, e como não existia uma suíte de testes cobrindo tal funcionalidade, o bug foi commitado.

Problema: Onde o erro foi commitado?
Solução: Utilizar o comando git bisect.

O projeto possui os seguintes commits:

commit 5c370fe0c059566a88e41699bfb7fea0abf4da0c
Author: Alberto Leal
Date: Sat Dec 12 11:05:04 2009 -0200

CBR 98575 - Cert verification

commit bd9e83fe1def11a38436d159b1ce721920fb9565
Author: Alberto Leal
Date: Sat Dec 12 11:04:25 2009 -0200

CBR 26345 - Regression

commit 61de4d21518855196426986ee0798c1e69f05ae0
Author: Alberto Leal
Date: Sat Dec 12 11:03:37 2009 -0200

bug 123 fixed

commit 32c8ce277a7db30aea67f7397a06596b1fc8bfdf
Author: Alberto Leal
Date: Sat Dec 12 11:02:58 2009 -0200

sessionTimeout features added

commit 1973d569ac052697c6e35e7e26b4e7b03ba09616
Author: Alberto Leal
Date: Sat Dec 12 11:01:58 2009 -0200

slogan on the header

commit 294d5cac2d9b400b7d244d71c6db5849f61fad6a
Author: Alberto Leal
Date: Sat Dec 12 11:01:01 2009 -0200

initial commit @gmail.com>@gmail.com>@gmail.com>@gmail.com>@gmail.com>@gmail.com>

**Para efeito de didática, já sabemos que o bug está no commit:
bd9e83fe1def11a38436d159b1ce721920fb9565

Antes de iniciar a busca binária, deve-se saber pelo menos um commit onde não existia o bug. Neste caso, sabemos que até o segundo commit tudo funcionava perfeitamente. Mas, para ter certeza disso, execute o comando abaixo, rode a aplicação e teste:

git checkout 1973d569ac052697c6e35e7e26b4e7b03ba09616

Observação: Estamos utilizando poucos commits, mas no “mundo real” os commits são muitos.

Após constatar que não existe o bug no segundo commit, volte para o último commit da mesma maneira:

git checkout 5c370fe0c059566a88e41699bfb7fea0abf4da0c

Agora chegou a vez de utilizar o comando git bisect. A idéia é marcar os commits como bad(ruim) e good(bom), e deixar que o Git faça uma busca binária entre os commits.

Alberto:repo Alberto$ git bisect start
Alberto:repo Alberto$ git bisect bad
Alberto:repo Alberto$ git bisect good 1973d569ac052697c6e35e7e26b4e7b03ba09616
Bisecting: 1 revisions left to test after this (roughly 1 steps)
[61de4d21518855196426986ee0798c1e69f05ae0] bug 123 fixed

Antes de mais nada, é necessário informar ao Git que vamos iniciar uma busca binária, para isso execute git bisect start. Repare que após iniciar o bisect, marcamos o último commit como bad e o segundo commit como good.

Em seguida o Git fez uma busca binária e encontrou o commit “bug 123 fixed”. Neste momento você deve executar a sua aplicação para ver se o bug está lá.

Não, o bug não está lá, portanto, marcamos o commit como good:

Alberto:repo Alberto$ git bisect good
Bisecting: 0 revisions left to test after this (roughly 0 steps)
[bd9e83fe1def11a38436d159b1ce721920fb9565] CBR 26345 - Regression

Novamente, o Git faz uma busca binária e encontra mais um commit para ser analisado. Após rodar a aplicação, constata-se que o erro está no commit atual que o bisect encontrou “CBR 26345 – Regression”:

Alberto:repo Alberto$ git bisect bad
bd9e83fe1def11a38436d159b1ce721920fb9565 is first bad commit
commit bd9e83fe1def11a38436d159b1ce721920fb9565
Author: Alberto Leal
Date: Sat Dec 12 11:04:25 2009 -0200

CBR 26345 - Regression

:100644 100644 9309150acfad8f21cb460ee17663fcbeaf212aa0 172b5ae1734b7bd1e1ac46b5cade3e61cbfddff1 M imasters.txt
@gmail.com>

Pronto! Agora já sabemos em qual commit o bug foi introduzido. E, para finalizar, da mesma forma que informamos ao Git que desejávamos fazer uma busca binária, devemos informá-lo que já terminamos, executando o comando abaixo:

Alberto:repo Alberto$ git bisect reset
Previous HEAD position was bd9e83f... CBR 26345 - Regression
Switched to branch 'master'

Muita gente acha que quando se está trabalhando sozinho em um projeto
de software não é necessário utilizar um sistema de controle de
versões. O que é um falácia. Utilizar um SCM é indispensável e indiferente à quantidade de desenvolvedores que está trabalhando no projeto.