Git
Chapters ▾ 2nd Edition

3.1 Git’də Branch - Nutshell’də Branch’lar

Demək olar ki, hər bir VNS’nin bir növ branching dəstəyi var. Branching əsas inkişaf xəttindən uzaqlaşmağınız və bu ana xəttlə qarışmadan işinizi davam etdirməyiniz deməkdir. Bir çox VNS alətində bu, bir qədər bahalı bir prosesdir və tez-tez mənbə kodu qovluğunun yeni bir nüsxəsini yaratmağınızı tələb edir, bu da böyük layihələr üçün çox vaxt apara bilər.

Bəzi insanlar Git’in branching modelini “qatil xüsusiyyəti” olaraq adlandırırlar və bu, Git’i VNS cəmiyyətində fərqləndirir. Niyə bu qədər xüsusidir? Git branch’larının yolu inanılmaz dərəcədə yüngüldür və branching əməliyyatlarını anında edir və branch’lar arasında ümumiyyətlə eyni sürətlə irəliləyir. Bir çox digər VNS’lərdən fərqli olaraq Git, gündə bir neçə dəfə dəfələrlə branch və birləşən iş axınlarını təşviq edir. Bu xüsusiyyəti anlamaq və mənimsəmək sizə güclü və bənzərsiz bir vasitə verir və inkişaf yolunuzu tamamilə dəyişə bilər.

Nutshell’də Branch’lar

Git-in branching yolunu həqiqətən başa düşmək üçün geri addım atmalı və Git-in məlumatlarını necə saxladığını araşdırmalıyıq.

Başlanğıc fəsildən xatırladığınız kimi, Git məlumatları bir sıra dəyişikliklər və ya fərqlər kimi saxlamır, əksinə snapshotlar kimi saxlayır.

Commit etdiyiniz zaman Git, səhnələşdirdiyiniz məzmunun snapshotu olan bir commit obyekti saxlayır. Bu obyekt eyni zamanda müəllifin adını və e-poçt adresini, yazdığınız mesajı və bu commit-i yerinə yetirmədən əvvəl gələn (törədicisi və ya valideynləri) göstəriş və göstərişləri göstərmişdir: ilkin commit üçün sıfır valideynlər, normal bir commit üçün bir valideyn və iki və ya daha çox branch-ın birləşməsi nəticəsində əmələ gələn çoxlu valideynlər.

Bunu görüntüləmək üçün üç fayldan ibarət bir qovluğunun olduğunu fərz edək və hamısını səhnələşdirib commit götürdünüz. Faylların qurulması hər biri üçün bir yoxlama cədvəlini tərtib edir (Başlanğıcbəhs etdiyimiz SHA-1 hash), faylın həmin versiyasını Git depolarında saxlayır (Git kimi blobs onlara aiddir) istifadə edərək sahəsinə nəzarət hissəsini əlavə edir:

$ git add README test.rb LICENSE
$ git commit -m 'Initial commit'

git commit əmrini yerinə yetirdikdə, Git hər alt bölməni yoxlayır (bu vəziyyətdə yalnız root layihə qovluğu) və onları Git deposunda ağac obyekti kimi saxlayır. Git sonra metadata və root layihə ağacına göstərici olan bir obyekt yaradır ki, lazım olduqda həmin anı yenidən yarada bilsin.

Git deposunda artıq beş obyekt var: üç blobs (hər üç fayldan birinin məzmununu təmsil edən), qovluğun məzmununu sadalayan bir tree və hansı fayl adlarının blobs kimi saxlanıldığını və o root ağacına və göstərilən bütün metadata göstərici ilə bir commit.

Commit və onun ağacı
Figure 9. Commit və Onun Ağacı

Bəzi dəyişikliklər etsəniz və yenidən commit etsəniz, növbəti əmr əvvəlcədən gələn commit göstəricisini saxlayır.

Commitlər və onun valideynləri
Figure 10. Commit-lər və Onun Valideynləri

Git-dəki bir branch, onun commit-ləri arasındakı yüngül daşınan göstəricilərindən biridir. Git-də standart branch adı master-dir. Commit etməyə başladığınız zaman etdiyiniz son commit-ə işarə edən bir master branch verilir. Hər dəfə commit etdiyiniz zaman master branch-ı göstəricisi avtomatik olaraq irəliləyir.

Note

“mater” branch-ı Git-də xüsusi branch deyildir. Tamamilə hər hansı digər branch kimidir. Təxminən hər bir deponun bir səbəbi, git init əmrinin onu standart olaraq yaratması və çoxlarının onu dəyişdirmək üçün narahat etməməsidir.

Branch və onun commit tarixi
Figure 11. Branch və Onun Commit Tarixi

Təzə Branch Yaratmaq

Yeni bir branch yaratdıqda nə baş verir? Yaxşı, bunu etmək hərəkət etməyiniz üçün yeni bir göstərici yaradır. Deyək ki, testing adlı yeni bir branch yaratmaq istəyirsiniz. Bunu git branch əmri ilə edirsiniz:

$ git branch testing

Bu, hazırda olduğunuz eyni commit yeni bir göstərici yaradır.

Eyni seriyaya commit edən iki branch
Figure 12. Eyni seriyaya commit edən iki branch

Git hazırda hansı branch-ın üzərində olduğunu necə bilir? HEAD adlı xüsusi bir göstərici saxlayır. Qeyd edək ki, Subversion və ya CVS kimi istifadə oluna biləcəyiniz digər VNS-lərdəki HEAD anlayışından çox fərqlidir. Git-də bu, hazırda olduğunuz lokal branch-a işarədir. Bu vəziyyətdə yenə də master-in üstündəsiniz. git branch əmri yalnız yeni bir branch yaratdı - o branch-a keçmədi.

Branch-a HEAD göstəricisi
Figure 13. Branch-a HEAD göstəricisi

Şöbə nöqtələrinin göstərildiyi yerləri göstərən sadə git log əmrini işlədərək bunu asanlıqla görə bilərsiniz. Bu seçim --decorate adlanır.

$ git log --oneline --decorate
f30ab (HEAD -> master, testing) Add feature #32 - ability to add new formats to the central interface
34ac2 Fix bug #1328 - stack overflow under certain conditions
98ca9 Initial commit

f30ab əməlinin yanında orada olan mastertesting branch-larını görə bilərsiniz.

Switching Branches

Mövcud bir branch-a keçmək üçün git checkout əmrini yerinə yetirirsiniz. Yeni testing branch-a keçək:

$ git checkout testing

Bu, testing şöbəsinə işarə etmək üçün HEAD-ı hərəkətə gətirir.

HEAD mövcud filiala işarə edir
Figure 14. HEAD mövcud branch-ı işarə edir

Bunun əhəmiyyəti nədir? Yaxşı, başqa bir commit edək:

$ vim test.rb
$ git commit -a -m 'made a change'
HEAD branch-ı bir commit götürüldükdə irəliləyir
Figure 15. HEAD branch-ı bir commit götürüldükdə irəliləyir

Bu, maraqlıdır, çünki indi testing branch-nız irəliləmişdir, ancaq master branch-nız branch-ları dəyişmək üçün git checkout zamanı işlədiyiniz vəzifəni göstərir. Gəlin yenidən master branch-a qayıdaq:

$ git checkout master
Note
git log həmişə _bütün branch-ları göstərmir

Hal-hazırda git log işlətməli olsaydınız, yeni yaradılan testing branch-nın hara getdiyi barədə düşünə bilərsiniz, çünki çıxışda görünməyəcəkdir.

Branch yoxa çıxmadı; Git sadəcə bu branch-la maraqlandığınızı bilmir və sizə nə istədiyini göstərməyə çalışır. Başqa sözlə, default olaraq, git log, yalnız yoxladığınız branch-ın altındakı törəmə tarixçəsini göstərəcəkdir.

İstədiyiniz branch üçün törəmə tarixçəsini göstərmək üçün onu dəqiq göstərməlisiniz: git log testing. Bütün branch-ları göstərmək üçün git log əmrinizə --all əlavə edin.

Siz çıxış edəndə HEAD hərəkət edir
Figure 16. Siz çıxış edəndə HEAD hərəkət edir

Bu əmr iki şeyi etdi. HEAD göstəricisini master branch-a göstərmək üçün geri qoydu və işçi qovluğunuzdakı faylları master işarələdiyi şəklə geri çevirdi. Bu da bu anda etdiyiniz dəyişikliklərin layihənin köhnə versiyasından ayrılacağını bildirir. Fərqli bir istiqamətə gedə bilmək üçün testing şöbənizdə gördüyünüz işləri geri qaytarır.

Note
Branch-ları dəyişdirmək işçi qovluğunuzdakı faylları dəyişdirir

Git-də filialları dəyişdirdiyiniz zaman işlədiyiniz qovluqdakı faylların dəyişəcəyini nəzərə almaq vacibdir. Köhnə bir branch-a keçsəniz, işlədiyiniz qovluq bu branch-da sonuncu dəfə etdiyiniz kimi görünəcəkdir. Git təmiz bir şəkildə edə bilmirsə, ümumiyyətlə keçməyə imkan verməz.

Yeniən bir neçə dəyişiklik və commit edək:

$ vim test.rb
$ git commit -a -m 'made other changes'

İndi layihənizin tarixi fərqləndi (bax Fərqli tarix). Bir branch yaratdınız və işə keçdiniz, bir az iş gördünüz, sonra yenidən əsas branch-a keçdiniz və başqa işlər gördünüz. Bu dəyişikliklərin hər ikisi ayrı-ayrı branch-da ayrılır: hazır olduqda filiallar arasında geri və irəli keçə bilərsiniz. Və siz bunların hamısını sadə branch, checkout`və `commit əmrləri ilə etdiniz.

Fərqli tarix
Figure 17. Fərqli tarix

Bunu git log əmri ilə də asanlıqla görə bilərsiniz. git log --oneline --decorate --graph --all işlədirsinizsə,branch-larınızın harada olduğunu və tarixinizin necə ayrıldığını göstərən əmrlərinizin tarixini çap edəcəkdir.

$ git log --oneline --decorate --graph --all
* c2b9e (HEAD, master) Made other changes
| * 87ab2 (testing) Made a change
|/
* f30ab Add feature #32 - ability to add new formats to the central interface
* 34ac2 Fix bug #1328 - stack overflow under certain conditions
* 98ca9 initial commit of my project

Git-dəki bir branch, əslində, işarələdiyi 40 simvol SHA-1 çeki olan sadə bir fayl olduğundan, branch-lar yaratmaq və məhv etmək asan və ucuzdur. Yeni bir filial yaratmaq, 41 baytı bir fayla yazmaq qədər sürətli və sadədir (40 simvol və yeni bir xətt).

Bu, ən köhnə VNS alətlər şöbəsinin, layihənin bütün sənədlərinin ikinci qovluğa kopyalanmasını özündə cəmləşdirən yoldan kəskin şəkildə fərqlidir. Layihənin ölçüsündən asılı olaraq bu bir neçə saniyə və ya hətta dəqiqə çəkə bilər, halbuki Git-də proses həmişə ani olur. Ayrıca, valideynlərimizi etdiyimiz zaman qeyd etdiyimiz üçün birləşmə üçün uyğun bir birləşmə bazası tapmaq avtomatik olaraq bizim üçün edilir və ümumiyyətlə bunu etmək çox asandır. Bu xüsusiyyətlər inkişaf etdiriciləri tez-tez filial yaratmağa və istifadə etməyə həvəsləndirməyə kömək edir.

Görək niyə belə etməlisiniz.

Note
Yeni bir branch yaratmaq və eyni zamanda ona keçid

Yeni bir branch yaratmaq və eyni zamanda yeni branch-a keçmək istəmək tipikdir - bu bir əməliyyatla with git checkout -b <newbranchname> ilə edilə bilər.