Git
Chapters ▾ 2nd Edition

7.1 Git Alətləri - Reviziya Seçimi

İndiyə qədər mənbə kodu nəzarəti üçün Git deposunu idarə etməli və ya saxlamağınız lazım olan gündəlik əmrlərin və iş axınlarının çoxunu öyrəndiniz. Faylları tracking və committing əsas tapşırıqlarını yerinə yetirdiniz və quruluş sahəsinin gücünü və yüngül mövzunun branching’ni və birləşməsini istifadə etdiniz.

İndi Git’in gündəlik olaraq istifadə edə bilməyəcəyiniz, ancaq bir anda ehtiyacınız ola biləcəyi çox güclü şeyləri araşdıracaqsınız.

Reviziya Seçimi

Git, bir sıra commit-lərə, commit-lər dəstinə və ya commit-lərə istinad etməyə imkan verir. Bunlar mütləq açıq deyil, bilmək faydalıdır.

Tək Reviziyalar

Tamamilə 40 xarakterli SHA-1 hash ilə hər hansı bir commit-ə istinad edə bilərsiniz, lakin commit-ləri ifadə etmənin daha çox insan dostu yolları var. Bu bölüm, hər hansı bir commit-ə istinad edə biləcəyiniz müxtəlif yolları əks etdirir.

Qısa SHA-1

Git, SHA-1 hash-nın ilk bir neçə simvolunu verdiyiniz təqdirdə nəyi nəzərdə tutduğunuzu başa düşmək üçün kifayət qədər ağıllıdır, qismən qarışıq ən azı dörd simvol uzun və birmənalıdır; Başqa sözlə, obyekt verilənlər bazasındakı heç bir obyektdə eyni prefikslə başlayan bir hash ola bilməz.

Məsələn, müəyyən bir funksionallıq əlavə etdiyinizi bildiyiniz xüsusi bir commit-i araşdırmaq üçün əvvəlcə commit-i tapmaq üçün git log əmrini işə sala bilərsiniz:

$ git log
commit 734713bc047d87bf7eac9674765ae793478c50d3
Author: Scott Chacon <schacon@gmail.com>
Date:   Fri Jan 2 18:32:33 2009 -0800

    Fix refs handling, add gc auto, update tests

commit d921970aadf03b3cf0e71becdaab3147ba71cdef
Merge: 1c002dd... 35cfb2b...
Author: Scott Chacon <schacon@gmail.com>
Date:   Thu Dec 11 15:08:43 2008 -0800

    Merge commit 'phedders/rdocs'

commit 1c002dd4b536e7479fe34593e72e6c6c1819e53b
Author: Scott Chacon <schacon@gmail.com>
Date:   Thu Dec 11 14:58:32 2008 -0800

    Add some blame and merge stuff

Bu vəziyyətdə, hash 1c002dd... ilə başlayan commit-lə maraqlandığınızı varsayaq. Aşağıdakı git show varyasyonlarından hər hansı biri ilə əlaqəli olanı yoxlaya bilərsiniz (daha qısa versiyaların birmənalı olduğunu düşünərək):

$ git show 1c002dd4b536e7479fe34593e72e6c6c1819e53b
$ git show 1c002dd4b536e7479f
$ git show 1c002d

Git, SHA-1 dəyərləriniz üçün qısa, bənzərsiz bir qısaltmanı müəyyən edə bilər. --abbrev-commit git log əmrinə keçsəniz, çıxış daha qısa dəyərlərdən istifadə edəcək, lakin onları unikal saxlayır; yeddi simvol istifadə etmək üçün standartdır, lakin SHA-1-in birmənalı olması üçün onları daha uzun edir:

$ git log --abbrev-commit --pretty=oneline
ca82a6d Change the version number
085bb3b Remove unnecessary test code
a11bef0 Initial commit

Ümumiyyətlə, səkkiz-on simvol bir proyektdə bənzərsiz olmaq üçün kifayətdir. Məsələn, 2019-cu ilin fevral ayından etibarən, Linux kernelinin (olduqca əhəmiyyətli bir layihədir) 875.000-dən çox commit-i və obyekt bazasında təxminən yeddi milyon obyekti var, ilk 12 simvolda SHA-1’ləri eyni olan iki obyekt yoxdur.

Note
SHA-1 HAQQINDA QISA QEYD

Bir çox insan təsadüfi bir şəkildə, eyni SHA-1 dəyərinə qarışan depolarında iki fərqli obyektə sahib olacaqlarından bir anda narahat olurlar. Bəs onda nə etmək lazımdır? Əgər deponuzdakı əvvəlki fəərqli obyekti ilə eyni SHA-1 dəyərinə bərabər olan bir obyekt törətmisinizsə, Git əvvəlki obyekti Git verilənlər bazanızda görəcək, artıq yazıldığını düşünün və sadəcə yenidən istifadə edin. Bir nöqtədə yenidən həmin obyekti yoxlamağa çalışsanız, həmişə ilk obyektin məlumatlarını əldə edəcəksiniz.

Bununla birlikdə, bu ssenarinin nə qədər gülünc bir şəkildə ehtimal olunmadığının fərqində olmalısınız. SHA-1 həcmi 20 bayt və ya 160 bitdir. Tək bir toqquşma ehtimalının 50% olmasını təmin etmək üçün lazım olan təsadüfi yığılmış obyektlərin sayı təxminən 280-dir (toqquşma ehtimalını müəyyənləşdirmək üçün düstur p = (n(n-1)/2) * (1/2^160)). 280 1.2 x 1024 təşkil edir və ya 1 milyon milyard. Bu, yer üzündə qum dənələrinin sayından 1,200 dəfə çoxdur.

Burada SHA-1 toqquşması üçün nə lazım olduğunu düşünmək üçün bir nümunə var. Yer üzündəki 6,5 milyard insanın hamısı proqramlaşdırma aparsaydı və hər saniyədə hər biri bütün Linux nüvə tarixinə (6.5 milyon Git obyekt) bərabər olan bir kod istehsal etsəydi və onu böyük bir Git deposuna salsaydı, təxminən 2 il çəkərdi. Bu depoda bir SHA-1 obyektinin toqquşma ehtimalı 50% -ə çatacaq qədər obyekt var qədər. Beləliklə, SHA-1 toqquşması, proqramlaşma komandanızın hər bir üzvünün eyni gecədə əlaqəsi olmayan hadisələrdə canavarların hücumuna məruz qalması və öldürülməsi ehtimalı daha azdır.

Branch Referansları

Müəyyən bir commit-ə istinad etməyin bir sadə yolu branch-ın ucundakı commit-in olmasıdır; bu halda, sadəcə bir commit-ə istinad gözləyən hər hansı bir Git əmrində branch adını istifadə edə bilərsiniz. Məsələn, bir branch-dakı son commit obyektini araşdırmaq istəyirsinizsə, aşağıdakı mövzuda əmrlər ekvivalentdir ki, topic1 branch-ının ca82a6d... işarə etdiyini göstərir:

$ git show ca82a6dff817ec66f44342007202690a93763949
$ git show topic1

Bir branch-ın hansı konkret SHA-1-ə işarə etdiyini görmək və ya bu nümunələrdən hər hansı birinin SHA-1-lər baxımından nəyə bənzədiyini görmək istəyirsinizsə, rev-parse adlı Git santexnika alətindən istifadə edə bilərsiniz. Santexnika alətləri haqqında daha çox məlumat üçün Git’in Daxili İşləri-ə baxa bilərsiniz; əsasən, rev-parse aşağı səviyyəli əməliyyatlar üçün mövcuddur və gündəlik əməliyyatlarda istifadə üçün nəzərdə tutulmayıb. Ancaq bəzən həqiqətən nələrin baş verdiyini görmək lazım olduqda faydalı ola bilər. Burada branch-ınızda rev-parse işlədə bilərsiniz.

$ git rev-parse topic1
ca82a6dff817ec66f44342007202690a93763949

RefLog Qısa Adları

Gitin arxada işləyərkən arxa planda gördüyü işlərdən biri də reflog saxlamaqdır - HEAD və branch istinadlarınızın son bir neçə ayda olduğu bir qeyd.

Reflogunuzu git reflog istifadə edərək görə bilərsiniz:

$ git reflog
734713b HEAD@{0}: commit: Fix refs handling, add gc auto, update tests
d921970 HEAD@{1}: merge phedders/rdocs: Merge made by the 'recursive' strategy.
1c002dd HEAD@{2}: commit: Add some blame and merge stuff
1c36188 HEAD@{3}: rebase -i (squash): updating HEAD
95df984 HEAD@{4}: commit: # This is a combination of two commits.
1c36188 HEAD@{5}: rebase -i (squash): updating HEAD
7e05da5 HEAD@{6}: rebase -i (pick): updating HEAD

Branch ucunuz hər hansı bir səbəbdən yeniləndikdə Git bu məlumatları sizin üçün bu müvəqqəti tarixdə saxlayır. Köhnə commit-lərə də istinad etmək üçün reflog məlumatlarınızı istifadə edə bilərsiniz. Məsələn, deposunuzun HEAD-in əvvəlki beşinci dəyərini görmək istəyirsinizsə, reflog çıxışında gördüyünüz @{5} istinadından istifadə edə bilərsiniz:

$ git show HEAD@{5}

Bu sintaksisdən branch-ın müəyyən bir müddət əvvəl harada olduğunu görmək üçün də istifadə edə bilərsiniz. Məsələn, dünən master branch-ınızın harada olduğunu görmək üçün yaza bilərsiniz:

$ git show master@{yesterday}

Bu, dünən "master branch-ınızın ucunun harada olduğunu göstərəcəkdir. Bu texnika yalnız hələ də qeydlərinizdə olan məlumatlar üçün işləyir, buna görə də bir neçə aydan yuxarı commit-lər axtarmaq üçün istifadə edə bilməzsiniz.

Reflog məlumatlarını git log çıxışı kimi formatlanmış şəkildə görmək üçün git log -g işlədə bilərsiniz:

$ git log -g master
commit 734713bc047d87bf7eac9674765ae793478c50d3
Reflog: master@{0} (Scott Chacon <schacon@gmail.com>)
Reflog message: commit: Fix refs handling, add gc auto, update tests
Author: Scott Chacon <schacon@gmail.com>
Date:   Fri Jan 2 18:32:33 2009 -0800

    Fix refs handling, add gc auto, update tests

commit d921970aadf03b3cf0e71becdaab3147ba71cdef
Reflog: master@{1} (Scott Chacon <schacon@gmail.com>)
Reflog message: merge phedders/rdocs: Merge made by recursive.
Author: Scott Chacon <schacon@gmail.com>
Date:   Thu Dec 11 15:08:43 2008 -0800

    Merge commit 'phedders/rdocs'

Qeyd etmək vacibdir ki, reflog məlumatları ciddi şəkildə localdır - bu, yalnız deponuzda etdiyiniz işlərin bir qeydidir. Referanslar başqasının deposunun kopyasında eyni olmayacaq; ayrıca, əvvəlcə bir deponu klonladıqdan dərhal sonra, depoda hələ heç bir fəaliyyət baş vermədiyi üçün boş bir refloqa sahib olacaqsınız. git show HEAD@{2.months.ago}-ı işə salmaq, sizə yalnız ən azı iki ay əvvəl layihəni klonlaşdırdığınız təqdirdə uyğunlaşma commit-ini göstərəcəkdir - daha yaxınlarda klonlaşdırsanız, yalnız ilk local commit-i görəcəksiniz.

Tip
Reflogu Git-in shell tarixinin versiyası kimi düşünün

UNIX və ya Linux arxa planınız varsa, reflog-u Git-in shell tarixinin versiyası olaraq düşünə bilərsiniz, burada olanların yalnız sizin və sizin “sessiyanız” üçün açıq şəkildə əlaqəli olduğunu vurğulayan və eyni maşında işləyə başqa heç kimlə ilə əlaqəsi yoxdur.

Ancestry Referansları

Bir commit-i müəyyənləşdirməyin digər əsas yolu əcdadı ilə bağlıdır. Bir referansın sonunda bir ^ (caret) qoysanız, Git, bu commit-in valideynini ifadə etmək üçün onu təhlil edir. Tutaq ki, layihənizin tarixinə nəzər yetirdiniz:

$ git log --pretty=format:'%h %s' --graph
* 734713b Fix refs handling, add gc auto, update tests
*   d921970 Merge commit 'phedders/rdocs'
|\
| * 35cfb2b Some rdoc changes
* | 1c002dd Add some blame and merge stuff
|/
* 1c36188 Ignore *.gem
* 9b29157 Add open3_detach to gemspec file list

Daha sonra, “the parent of HEAD” mənasını verən HEAD^ göstərərək əvvəlki commit-i görə bilərsiniz:

$ git show HEAD^
commit d921970aadf03b3cf0e71becdaab3147ba71cdef
Merge: 1c002dd... 35cfb2b...
Author: Scott Chacon <schacon@gmail.com>
Date:   Thu Dec 11 15:08:43 2008 -0800

    Merge commit 'phedders/rdocs'
Note
Craet-i Windows-dan xilas etmək

Windows-da cmd.exe, ^ xüsusi bir xarakter daşıyır və fərqli davranılmalıdır. Ya ikiqat edə bilərsiniz, ya da commit arayışını quote-lara daxil edə bilərsiniz:

$ git show HEAD^     # will NOT work on Windows
$ git show HEAD^^    # OK
$ git show "HEAD^"   # OK

İstədiyiniz valideynin hansı olduğunu müəyyən etmək üçün ^-dən sonra bir rəqəm də göstərə bilərsiniz; məsələn, d921970^2 “d921970-in ikinci valideynidir.” deməkdir. Bu sintaksis yalnız birdən çox valideynə sahib olan birləşmə commit-ləri üçün faydalıdır - birləşdirmə commit-inin birinci valideyni birləşdikdə olduğunuz branch-dan (tez-tez master), birləşmə commit-nin ikinci valideyn hissəsi isə birləşdirilmiş branch-dan (topic deyək):

$ git show d921970^
commit 1c002dd4b536e7479fe34593e72e6c6c1819e53b
Author: Scott Chacon <schacon@gmail.com>
Date:   Thu Dec 11 14:58:32 2008 -0800

    Add some blame and merge stuff

$ git show d921970^2
commit 35cfb2b795a55793d7cc56a6cc2060b4bb732548
Author: Paul Hedderly <paul+git@mjr.org>
Date:   Wed Dec 10 22:22:03 2008 +0000

    Some rdoc changes

Digər əsas əcdad spesifikasiyası ~ (tilde)-dir. Bu da birinci valideynə aiddir, buna görə HEAD~HEAD^ bərabərdir. Fərq bir rəqəm göstərdiyiniz zaman aydın olur. HEAD~2, “ilk valideynin birinci valideyni” və ya “nənə və baba” deməkdir - ilk valideynlərə göstərdiyiniz vaxt keçir. Məsələn, əvvəllər sadalanan tarixdə HEAD~3:

$ git show HEAD~3
commit 1c3618887afb5fbcbea25b7c013f4e2114448b8d
Author: Tom Preston-Werner <tom@mojombo.com>
Date:   Fri Nov 7 13:47:59 2008 -0500

    Ignore *.gem

Yenidən ilk valideynin ilk valideyninin ilk valideyni olan HEAD~~~ yazıla bilər:

$ git show HEAD~~~
commit 1c3618887afb5fbcbea25b7c013f4e2114448b8d
Author: Tom Preston-Werner <tom@mojombo.com>
Date:   Fri Nov 7 13:47:59 2008 -0500

    Ignore *.gem

Bu sintaksisləri də birləşdirə bilərsiniz - əvvəlcədən istinadın ikinci əsas hissəsini (birləşdirmə əmri olduğunu düşünərək) HEAD~3^2 və s. istifadə edərək əldə edə bilərsiniz.

Commit Aralıqları

İndi fərdi commit-lər təyin edə bildiyinizə görə, commit-lərin hüdudlarını necə təyin edəcəyimizə baxaq. Bu, branch-larınızı idarə etmək üçün xüsusilə faydalıdır - çox sayda branch-ınız varsa, “Bu branch-da hələ əsas branch-a birləşdirmədiyim hansı iş var?” kimi suallara cavab vermək üçün spesifikasiyalardan istifadə edə bilərsiniz.

Cüt nöqtə

Ən geniş yayılmış spesifikasiya cüt nöqtəli sintaksisdir. Bu, əsasən Git-dən bir commit-dən əldə edilə bilən, digərinə çatmayan bir sıra commit-ləri həll etməsini xahiş edir. Məsələn, Aralıq seçimi üçün nümunə tarixçəsi kimi görünən commit tarixçəniz olduğunu söyləyin.

Aralıq seçimi üçün nümunə tarixçəsi
Figure 137. Aralıq seçimi üçün nümunə tarixçəsi

experiment branch-ınızda hələ master branch-ınıza birləşdirilməyənləri görmək istədiyinizi söyləyin. Git-dən sizə yalnız master..experiment ilə işləyənlərin bir jurnalını göstərməsini xahiş edə bilərsiniz - bu, ‘` master-dən əldə edilə bilməyən experiment-dən əldə edilə bilən bütün commit-lər’' deməkdir. Bu nümunələrdə qısalıq və aydınlıq üçün, diaqramdakı commit obyektlərinin hərfləri göstərəcəkləri qaydada həqiqi log çıxışı yerinə istifadə olunur:

$ git log master..experiment
D
C

Digər tərəfdən bunun əksini görmək istəyirsinizsə - bütün commit-lər experiment-də olmayan master-də işləyirsə - branch adlarını tərsinə çevirə bilərsiniz. experiment..master sizə experiment-dən əlçatmaz olan hər şeyi master-də göstərir:

$ git log experiment..master
F
E

Bu, experiment branch-ını yeniləmək və birləşdirmək istədiklərinizi önizləmək istəsəniz faydalıdır. Bu sintaksisin başqa bir tez-tez istifadəsi uzaq məsafəyə nəyi push edəcəyinizi görməkdir:

$ git log origin/master..HEAD

Bu əmr sizə cari branch-ınızdakı origin remote-dakı master branch-ında olmayan hər hansı bir commit-i göstərir. Bir git push işə salırsınızsa və mövcud branch-ınız origin/master izləyirsə, git log origin/master..HEAD tərəfindən sadalanan commit-lər serverə ötürülən commit-lərdir. Git-in HEAD olduğunu qəbul etməsi üçün sintaksisin bir tərəfini də tərk edə bilərsiniz. Məsələn, git log origin/master.. yazaraq əvvəlki nümunədəki ilə eyni nəticələr əldə edə bilərsiniz - bir tərəfi yoxdursa, HEAD əvəzlə.

Birdən Çox Pal

İkili nöqtəli sintaksis shorthand kimi faydalıdır, lakin bəlkə də hazırda olduğunuz branch-da olmayan bir neçə branch-dan birinin nə olduğunu görmək kimi düzəlişlərinizi göstərmək üçün ikidən çox branch göstərmək istəyirsiniz. Git, əlçatan commit-lər görmək istəmədiyiniz hər hansı bir istinaddan əvvəl ^ simvolunu və ya --not istifadə edərək bunu etməyə imkan verir. Beləliklə, aşağıdakı üç əmr bərabərdir:

$ git log refA..refB
$ git log ^refA refB
$ git log refB --not refA

Bu çox yaxşıdır, çünki bu sintaksislə sorğunuzda ikiqat nöqtəli sintaksis ilə edə bilməyəcəyiniz ikidən çox istinad daxil edə bilərsiniz. Məsələn, refA ya da refB-dən əldə edilə bilən, ancaq refC-dən edilməyən, bütün commit-ləri görmək istəyirsinizsə, aşağıdakılardan birini istifadə edə bilərsiniz:

$ git log refA refB ^refC
$ git log refA refB --not refC

Bu, branch-larınızda nə olduğunu anlamanıza kömək edəcək çox güclü bir revizyon sorğu sistemi yaradır.

Üçqat Nöqtə

Son böyük aralıq seçmə sintaksisi, hər ikisindən deyil, iki istinadın hər ikisi tərəfindən də əldə edilə bilən bütün commit-ləri təyin edən üç nöqtəli sintaksisdir. Aralıq seçimi üçün nümunə tarixçəsi-dakı commit tarixçəsinə baxın. master və ya experiment-də olanları görmək istəsəniz, lakin ümumi istinadları yox görmək istəməsəniz, işlədə bilərsiniz:

$ git log master...experiment
F
E
D
C

Yenə də, bu sizə normal bir log çıxışı verir, ancaq ənənəvi commit tarixi sifarişində görünən yalnız bu dörd commit üçün commit məlumatlarını göstərir.

Bu halda log əmri ilə istifadə olunan ümumi bir keçid, hər bir commit aralığın hansı tərəfində olduğunu göstərən --left-right-dır. Bu, nəticənin daha faydalı olmasına kömək edir:

$ git log --left-right master...experiment
< F
< E
> D
> C

Bu vasitələrlə Git-ə nəyi yoxlamaq istədiyinizi və ya commit-lərinizi daha asanlıqla bildirə bilərsiniz.