Git
Chapters ▾ 2nd Edition

7.10 Mga Git na Kasangkapan - Pagdebug gamit ang Git

Pagdebug gamit ang Git

Bilang karagdagan sa pagiging pangunahin para sa kontrol ng bersyon, Ang Git ay nagbibigay rin ng ilang utos para tumulong sa pag-debug sa iyong source code na mga proyekto. Dahil ang Git ay dinisenyo upang pangasiwaan ang halos anumang uri ng nilalaman, ang mga kasangkapang ito ay medyo generic, ngunit maaari nilang madalas na makatulong sayo upang maghanap ng isang bug o salarin kapang ang mga bagay ay nagkakamali.

Ang Annotation ng File

Kung ikaw ay sumusubaybay ng isang bug sa iyong code at gusto mong malaman kapag ito ay ipinakilala at bakit, ang annotation ng file ay madalas na iyong pinakamahusay na kasangkapan. Ito ay nagpapakita sa iyo kung anong commit ang huling binago sa bawat linya ng anumang file. Kung nakikita mo na ang pamamaraan na iyon sa iyong code ay buggy, maaari mong i-annotate ang file gamit ang git blame para malaman kung anong commit ang responsable para sa pagpapakilala sa linyang iyon.

Ang mga sumusunod na halimbawa ay gumagamit ng git blame para matukoy kung anong commit at nag-commit ang responsable para sa mga linya sa itaas na antas na Linux kernel na Makefile at, higit pa, gumagamit ng -L na opsyon upang paghigpitan ang output sa annotation ng mga linya 69 hanggang 82 sa file na iyon:

$ git blame -L 69,82 Makefile
b8b0618cf6fab (Cheng Renquan  2009-05-26 16:03:07 +0800 69) ifeq ("$(origin V)", "command line")
b8b0618cf6fab (Cheng Renquan  2009-05-26 16:03:07 +0800 70)   KBUILD_VERBOSE = $(V)
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 71) endif
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 72) ifndef KBUILD_VERBOSE
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 73)   KBUILD_VERBOSE = 0
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 74) endif
^1da177e4c3f4 (Linus Torvalds 2005-04-16 15:20:36 -0700 75)
066b7ed955808 (Michal Marek   2014-07-04 14:29:30 +0200 76) ifeq ($(KBUILD_VERBOSE),1)
066b7ed955808 (Michal Marek   2014-07-04 14:29:30 +0200 77)   quiet =
066b7ed955808 (Michal Marek   2014-07-04 14:29:30 +0200 78)   Q =
066b7ed955808 (Michal Marek   2014-07-04 14:29:30 +0200 79) else
066b7ed955808 (Michal Marek   2014-07-04 14:29:30 +0200 80)   quiet=quiet_
066b7ed955808 (Michal Marek   2014-07-04 14:29:30 +0200 81)   Q = @
066b7ed955808 (Michal Marek   2014-07-04 14:29:30 +0200 82) endif

Pansinin na ang unang patlang ay ang bahagyang SHA-1 ng commit na huling nabago sa linyang iyon. Ang sunod na dalawang mga patlang ay mga nakuhang halaga mula sa commit na iyon — ang pangalan ng may-akda at ang petsa ng pag-akda sa pag-commit na iyon — kaya madali mong makita kung sino ang nagbago sa linya at kung kailan. Pagkatapos ay may kasunod na bilang ng linya at ang nilalaman ng file. Tandaan din ang ^1da177e4c3f4 na commit na mga linya, na kung saan ang ^ na prefix ay nagtatakda ng mga linya na pinakilala ang paunang commit sa repositoryo at mayroong hindi nabago mula noon. Ito ay isang nakakalito, dahil ngayon ay makikita mo ang hindi bababa sa tatlong iba’t ibang pamaraan sa na ginagamit ni Git ang ^ sa pagbago ng isang commit na SHA-1, ngunit iyan ang ibig sabihin dito.

Isa pang cool na bagay tungkol sa Git ay hindi ito makasubaybay ng file na tahasang pagpapalit ng pangalan. Ito ay nagtatala sa mga snapshot at sinusubukang tingnan kung ano ang ipinahiwatig sa binago na pangalan, pagkatapos sa katotohanan. Isa sa interesadong mga tampok nito ay maaari kang magtanong para malaman ang lahat ng mga uri ng kilos ng code din. Kung ikaw ay papasa sa -C hanggang git blame, ang Git nag-aaral ng file na iyong ina-annotate at sinusubukang malaman kung saang mga snippet ng code na nasa orihinal na dumating kung sila ay nakopya mula kung saan. Halimbawa, sabihin natin na ikaw ay nag-refactor ng isang file na pinangalanan na GITServerHandler.m sa maramihang mga file, isa na ang GITPackUpload.m. Sa pamamagitan ng pagsisisi ng GITPackUpload.m na may -C na opsyon, maaari mong makikita kung saan mga seksyon ng code na orihinal na nagmumula:

$ git blame -C -L 141,153 GITPackUpload.m
f344f58d GITServerHandler.m (Scott 2009-01-04 141)
f344f58d GITServerHandler.m (Scott 2009-01-04 142) - (void) gatherObjectShasFromC
f344f58d GITServerHandler.m (Scott 2009-01-04 143) {
70befddd GITServerHandler.m (Scott 2009-03-22 144)         //NSLog(@"GATHER COMMI
ad11ac80 GITPackUpload.m    (Scott 2009-03-24 145)
ad11ac80 GITPackUpload.m    (Scott 2009-03-24 146)         NSString *parentSha;
ad11ac80 GITPackUpload.m    (Scott 2009-03-24 147)         GITCommit *commit = [g
ad11ac80 GITPackUpload.m    (Scott 2009-03-24 148)
ad11ac80 GITPackUpload.m    (Scott 2009-03-24 149)         //NSLog(@"GATHER COMMI
ad11ac80 GITPackUpload.m    (Scott 2009-03-24 150)
56ef2caf GITServerHandler.m (Scott 2009-01-05 151)         if(commit) {
56ef2caf GITServerHandler.m (Scott 2009-01-05 152)                 [refDict setOb
56ef2caf GITServerHandler.m (Scott 2009-01-05 153)

Ito ay talagang kapaki-pakinabang. Karaniwan, ikaw ay makakakuha nang isang orihinal na commit kung saan kinopya mo ito ang code na higit pa, dahil iyon ang unang pagkakataon na iyong hinawakan ang mga linya sa file na ito. Sinasabihan ka ni Git ang orihinal na commit na iyong sinulat ang mga linyang iyon, kahit na ito ay nasa ibang file.

Pag-annotate ng file ay tumutulong kung alam mo kung saan ang issue ay nagsisimula. Kung hindi mo alam kung ano ang breaking, at nagkakaroon ng dose-dosena o daan-daan na mga commit mula ng iyong huling estado na kung saan alam mo ang code ay gumagana, malamang na mababalik ka sa git bisect para sa tulong. Ang bisect na utos ay gumagawa ng isang binary na paghahanap sa pamamagitan ng iyong commit na kasaysayan upang tumulong na tukuyin nang mas mabilis hangga’t maaari na kung saan ang commit ay ipinakilala ang isyu.

Sabihin natin na ikaw ay naka-push na isang release sa iyong code sa isang produksyon na environment, ikaw ay makakuha ng mga bug report tungkol sa isang bagay na hindi nangyayari sa iyong development environment, at ikaw ay hindi makaiisip kung paano ang code ay gumagawa ng ganoon. Bumalik ka sa iyong code, at parang may nangyari na maaari kang gumawa uli ng isyu, ngunit hindi mo matukoy kung ano ang nangyari. Kaya mo mag-bisect sa code upang matukoy. Una ikaw ay magpatakbo sa git bisect start para umpisahan ito, at pagkatapos ay ikaw ay gumamit ng git bisect bad para sabihan ang sistema na ang kasalukuyang commit na ikaw ay nandoon ay nabasag. Pagkatapos, dapat mong sabihin ang bisect kapag ang huling kilalang magandang estado ay, gumagamit ng git bisect good <good_commit>:

$ git bisect start
$ git bisect bad
$ git bisect good v1.0
Bisecting: 6 revisions left to test after this
[ecb6e1bc347ccecc5f9350d878ce677feb13d3b2] error handling on repo

Naisip ni Git na mga 12 na mga commit ay dumating sa pagitan ng commit na iyong minarkahan bilang ang huling mabuting commit (v1.0) at ang kasalukuyang masamang bersyon, at ito ay sinusuri ang gitna para sayo. Sa puntong ito, maaari kang magpatakbo ng iyong pagsubok upang makita kung ang isyu at umiiral sa commit na ito. Kung ito ay gumagawa, pagkatapos ito ay ito pay pinakilala minsan bago ang gitnang commit; kung hindi ito gumagawa, kaya ang problema ay ipinakilala minsan pagkatapos ng gitnang commit. Iyon pala ay walang isyu dito, at ikaw ay nagsasabi ni Git sa pamamagitan ng pag-type ng git bisect good at ipagpatuloy ang iyong paglalakbay:

$ git bisect good
Bisecting: 3 revisions left to test after this
[b047b02ea83310a70fd603dc8cd7a6cd13d15c04] secure this thing

Ngayon ikaw ay nasa ibang commit, sa gitna sa pagitan sa iyong nasubukan na at ang iyong masamang commit. Maaari kang magpatakbo sa iyong pagsubok muli at tignan na ang commit na ito ay nasira, kaya sabihan ang Git sa pamamagitan ng git bisect bad:

$ git bisect bad
Bisecting: 1 revisions left to test after this
[f71ce38690acf49c1f3c9bea38e09d82a5ce6014] drop exceptions table

Ang commit na ito ay mabuti, at ngayon ang Git ay maroong lahat ng mga impormasyon na kung saan ang isyu ay ipinakilala. Sinasabi nito sa iyo na ang SHA-1 sa unang masamang commit at nagpakita ng maraming commit na impormasyon at kung saan ang mga file ay nabago sa pag-coomit para matukoy ang nagyayari na maaaring mayroong ipinakilala sa bug na ito:

$ git bisect good
b047b02ea83310a70fd603dc8cd7a6cd13d15c04 is first bad commit
commit b047b02ea83310a70fd603dc8cd7a6cd13d15c04
Author: PJ Hyett <pjhyett@example.com>
Date:   Tue Jan 27 14:48:32 2009 -0800

    secure this thing

:040000 040000 40ee3e7821b895e52c1695092db9bdc4c61d1730
f24d3c6ebcfc639b1a3814550e62d60b8e68a8e4 M  config

Kaya tapos ka na, dapat kang magpatakbo ng git bisect reset upang i-reset ang iyong HEAD sa kung nasaan ka nag-umpisa, o ikaw ay nagtapos ng isang kakaibang estado:

$ git bisect reset

Ito ay isang makapangyarihang kasangkapan na maaaring makatulong para tingnan ang daan-daang mga commit para sa ipinakilalang bug sa minuto. Sa katunayan, kung mayroon kang isang script na lumabas sa 0 kung ang proyekto ay mabuti o hindi-0 kung ang proyekto ay masama, maaari kang buong mag-awtomatiko sa git bisect. Una, ikaw ay muling magsasabi nito na ang scope sa bisect sa pamamagitan ng pagbibigay ng kilalang masama at mabuting mga commit. Maaari mong gawin ito sa pamamagitan sa paglista sa kanila na gamit ang bisect start na utos kung gusto mo, paglista ng kilalang masamang commit muna at ang kilalang magandang commit sa pangalawa:

$ git bisect start HEAD v1.0
$ git bisect run test-error.sh

Sa paggawa ay awtomatikong nagpapatakbo ng test-error.sh sa bawat checked-out na commit hanggang ang Git ay makakita sa unang sirang commit. Maaari ka ding magpatakbo ng ibang bagay na tulad ng make o make tests o anumang mayroon kang napapatakbo ng awtomatiko para susubukan para sa iyo.