Git
Chapters ▾ 2nd Edition

7.10 Git Alətləri - Git ilə Debugging

Git ilə Debugging

Əsasən versiyaya nəzarət etməklə yanaşı, Git, source code layihələrinizi debug etməyə kömək etmək üçün bir neçə əmr verir. Git, demək olar ki, hər hansı bir məzmun növünü idarə etmək üçün tərtib olunduğundan, bu vasitələr ümumidir, lakin tez-tez işlər səhv olduqda bug və ya culprit üçün ovlanmağınıza kömək edə bilər.

Fayl Annotasiyası

Kodunuzdakı bir səhvi izləyirsinizsə və onun nə vaxt tətbiq olunduğunu və nə üçün olduğunu bilmək istəyirsinizsə, fayl annotasiyası çox vaxt ən yaxşı vasitədir. O sizə hər hansı bir faylın hər sətirini dəyişdirmək üçün son commit-i göstərir. Aşağıdakı nümunə, üst səviyyəli Linux kernel Makefile-də və daha sonra hansı commit və committer-in cavabdeh olduğunu müəyyən etmək üçün git balme-dən istifadə edir, bundan əlavə loqotipin output-nu həmin sənədin 69-dan 82-yə qədər olan xətləri ilə məhdudlaşdırmaq üçün `-L `seçimindən istifadə edir:

$ 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

Diqqət yetirin ki, ilk sahə həmin xətti son dəyişdirən commit-in qismən SHA-1 hissəsidir. Növbəti iki sahə həmin commit-dən çıxarılan dəyərlərdir - müəllifin adı və həmin commit-in müəllif tarixi - bu xətti kimin və nə vaxt dəyişdirdiyini asanlıqla görə bilərsiniz. Bundan sonra xətt nömrəsi və faylın məzmunu gəlir. Həm də ^1da177e4c3f4 commit xətlərinə diqqət yetirin, burada ^ prefiksi deposunun ilkin commit-ə daxil edilmiş və indiyədək dəyişməmiş xətləri təyin edir. Bu çaşdırıcı bir şeydir, çünki indi Git-in SHA-1-i dəyişdirmək üçün ^-dan istifadə etdiyi ən az üç fərqli üsulu gördünüz, amma burada da bunun mənası budur.

Git’in başqa bir xoş cəhəti, fayl adlarını açıq şəkildə izləməməsidir. O, bu anları qeyd edir və sonra gerçəkləşdirildikdən sonra adının dəyişdirildiyini anlamağa çalışır. Bunun maraqlı xüsusiyyətlərindən biri odur ki, hər cür kod hərəkətini də anlamağını istəyə bilərsiniz. Əgər –C-ni git blame-ə ötürsəniz, Git yazdığınız faylı təhlil edir və başqa yerdən kopyalandığı təqdirdə içərisindəki kod parçalarının haradan gəldiyini anlamağa çalışır. Məsələn, GITServerHandler.m adlı bir faylı GITPackUpload.m`olan birdən çox sənədə refactoring etdiyinizi fərz edək. `GITPackUpload.m-u -C seçimi ilə blame edərək kodun bölmələrinin əvvəlcə haradan gəldiyini görə bilərsiniz:

$ 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)

Bu həqiqətən faydalıdır. Normalda, kodun surətini çıxardığınız zaman orijinal commit-i götürdüyünüz üçün alırsınız, çünki bu sənəddəki bu sətirlərə ilk dəfə toxunursunuz. Git, başqa bir sənəddə olsa belə, bu sətirləri harada yazdığınızın orijinal commit-ni bildirir.

Bir faylın qeyd edilməsi, əgər məsələnin nədən başlayacağını bilirsinizsə kömək edir. Əgər nəyin pozulduğunu bilmirsinizsə və kodun işlədiyini bildiyiniz son vəziyyətdən bəri onlarla və yüzlərlə iş görülmüşdürsə, çox güman ki, kömək üçün git bisect-ə müraciət edə bilərsiniz. bisect əmri bir problemi ortaya qoyduğunu mümkün qədər tez müəyyənləşdirməyə kömək etmək üçün commit tarixçənizlə ikili axtarış aparır.

Deyək ki, kodunuzu bir istehsal mühitinə push etdiniz, inkişaf mühitinizdə baş verməyən bir şey haqqında bug hesabatları alırsınız və kodun niyə belə etdiyini təsəvvür edə bilmirsiniz. Kodunuza qayıdırsınız və məsələni yenidən yarada biləcəyiniz ortaya çıxır, ancaq nəyin səhv olduğunu anlaya bilmirsiniz. Bunu bilmək üçün kodu bisect edə bilərsiniz. Əvvəlcə git bisect-i işə salın, sonra sistemin hazırkı commit-in pozulduğunu söyləmək üçün git bisect bad istifadə edin. Daha sonra, git bisect good <good_commit> istifadə edərək, son məlum olan yaxşı vəziyyətin nə vaxt olduğunu bisect-ə deməlisiniz.

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

Git anlayır ki, son yaxşı commit (v1.0) kimi qeyd edilmiş commit-lə hazırkı pis versiya arasında təxminən 12 əmr gəlir və bu sizin üçün orta birini yoxlayır. Bu anda, problemin bu commit-ə görə olub olmadığını görmək üçün testinizi işə sala bilərsiniz. Bunu edərsə, onda bu orta commit-dən bir müddət əvvəl tətbiq edilmişdir; etmirsə, problem orta commit-dən bir müddət sonra ortaya çıxır. Buradan heç bir problem çıxmır və Git’ə git bisect good yazaraq işinizi davam etdirdiyinizi deyə bilərsiniz:

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

İndi siz sınadığınızla pis commit-in yarısının ardınca gələn başqa bir commit-dəsiniz. Yenidən testinizi həyata keçirirsiniz və bu commit-in pozulduğunu görürsünüz, buna görə git bisect bad ilə Git-ə deyirsiniz:

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

Bu commit yaxşıdır və indi Git məsələnin harada tətbiq olunduğunu müəyyənləşdirmək üçün lazım olan bütün məlumatlara sahibdir. Bu sizə ilk pis commit-ə aid SHA-1 deyir və commit məlumatlarının bəzilərini göstərir və bu bug-da hansı hadisələrin baş verdiyini anlamaq üçün bu sənəddə nəyin dəyişdirildiyini göstərir:

$ 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

Bitirdikdən sonra başlamazdan əvvəl olduğunuz yeri bərpa etmək üçün git bisect reset işlətməlisiniz, yoxsa qəribə bir vəziyyətə düşəcəksiniz:

$ git bisect reset

Bu, bir neçə dəqiqə ərzində təqdim edilmiş bir bug üçün yüzlərlə commit-i yoxlamağa kömək edə biləcək güclü bir vasitədir. Əslində, 0-dan çıxacaq bir ssenariniz varsa, əgər layihə yaxşıdırsa və ya 0-dan pisdirsə, layihə ümumilikdə pisdirsə, git bisect-ini tam avtomatlaşdıra bilərsiniz. Birincisi, məlum pis və yaxşı əmrləri verməklə yenidən bisetin həcmini söyləyin. İstədiyiniz təqdirdə bisect start əmri ilə siyahıya alınmaqla, məlum pis commit-i birinci və məlum yaxşı commit-i ikinci sıralamaqla bunu edə bilərsiniz:

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

Bunu etmək Git ilk pozulmuş commit-ni tapana qədər hər test edilmiş test-error.sh üzərində avtomatik olaraq işə salır. Siz həmçinin testlər edə bilə və ya sizin üçün avtomatlaşdırılmış testləri işlədən hər hansı bir şeyi işlədə bilərsiniz.