Git
Chapters ▾ 2nd Edition

3.1 Git Branching - Dallar

Nearly every VCS has some form of branching support. Branching means you diverge from the main line of development and continue to do work without messing with that main line. In many VCS tools, this is a somewhat expensive process, often requiring you to create a new copy of your source code directory, which can take a long time for large projects.

Some people refer to Git’s branching model as its “killer feature,” and it certainly sets Git apart in the VCS community. Why is it so special? The way Git branches is incredibly lightweight, making branching operations nearly instantaneous, and switching back and forth between branches generally just as fast. Unlike many other VCSs, Git encourages workflows that branch and merge often, even multiple times in a day. Understanding and mastering this feature gives you a powerful and unique tool and can entirely change the way that you develop.

Dallar

Git’in dallanma yöntemini gerçekten anlamak için bir adım geriye çekilip Git’in verileri nasıl sakladığını incelememiz gerekiyor.

Başlangıç bölümünden hatırlayabileceğiniz gibi Git, verileri bir dizi değişiklik veya farklılık olarak değil, bir dizi poz olarak saklar.

Git, bir katkı işlediğinizde, izleme (stage) aldığınız içeriğin pozunun işaretçisini içeren bir katkı nesnesi saklar. Bu nesne aynı zamanda yazarın adını ve e-posta adresini, katkı mesajını ve öncel katkı veya katkılara ilişkin işaretçileri içerir. İlk katkı (first commit) için sıfır; normal bir katkı için bir; ve birden fazla dalın birleşmesinden kaynaklanan bir katkı içinse çoklu öncel katkı bulunur.

Bunu görselleştirmek için, üç dosya içeren bir dizine sahip olduğumuzu ve bunların hepsini izleme alıp, katkı olarak işlediğinizi varsayalım. Dosyaları izlemlemek, her bir dosya için bir sağlama toplamı (checksum) hesaplar (Başlangıç bölümünde bahsettiğimiz SHA-1 karması), dosyanın bu sürümünü Git reposunda saklar (Git bunlara blobs olarak atıfta bulunur)(Binary Large OBject: ikilik geniş nesne), ve bu sağlama toplamını izlem alanına ekler:

$ git add README test.rb LICENSE
$ git commit -m 'The initial commit of my project'

git commit komutunu çalıştırarak bir katkı oluşturduğunuzda, Git her alt dizinin (bu durumda sadece kök (root) proje dizini) doğrular ve bunları Git reposunda bir ağaç nesnesi (tree object) olarak saklar. Git daha sonra meta verileri ve kök proje ağacının işaretçisini içeren bir katkı nesnesi oluşturur. Böylece gerektiğinde pozu yeniden oluşturabilir.

Git reponuz artık beş nesne içeriyor: - Her biri üç dosyadan birinin içeriğini temsil eden üç blob - Dizinin içeriğini ve hangi dosya adlarının hangi blob olarak depolandığını listeleyen bir ağaç - Kök ağacın işaretçisini ve tüm katkı metaverisini içeren bir katkı

Bir katkı ve onun ağacı.
Görsel 9. Bir katkı ve onun ağacı

Eğer bazı değişiklikler yaparsanız ve tekrar katkı olarak işlerseniz, sonraki katkı, kendinden hemen önceki katkıya işaret eden bir işaretçiyi depolar.

Katkı ve öncel katkılar.
Görsel 10. Katkı ve öncel katkılar

Git’teki bir dal, temel olarak üzerindeki katkılardan birinin hafif ve taşınabilir bir işaretçisidir. Git’te varsayılan dal master adıyla ifade edilir (anadal). Katkıları işlemeye başladığınızda, en son işlediğiniz katkıyı gösteren bir master dalı alırsınız. Her katkı işlediğinizde, master dalı işaretçisi otomatik olarak ileri hareket eder.

Git’teki master dalı özel bir dal değildir. Tam olarak diğer diğer dallar gibi davranır. Hemen hemen her repoda bulunmasının tek nedeni, git init komutunun varsayılan olarak onu oluşturması ve çoğu insanın bunu değiştirmeye uğraşmamasıdır.

Bir dal ve katkı geçmişi.
Görsel 11. Bir dal ve katkı geçmişi

Yeni bir Dal Açma

Yeni bir dal oluşturduğunuzda ne olur? Öncelikle, bu size etrafında dolaşabileceğiniz yeni bir işaretçi oluşturur. Diyelim ki testing adında yeni bir dal oluşturmak istiyorsunuz. Bunu git branch komutu ile yaparsınız:

$ git branch testing

Bu, şu anda işlediğiniz katkı için yeni bir işaretçi oluşturur.

Aynı katkı dizisine işaret eden iki dal.
Görsel 12. Aynı katkı dizisine işaret eden iki dal

Git, şu anda hangi dalda olduğunuzu nasıl bilir? Bunu HEAD adlı özel bir işaretçiyi kullanarak yapar. Yalnız bu Subversion veya CVS gibi alışkın olduğunuz diğer sürüm denetleyicilerindeki (VCS) HEAD kavramından çok farklıdır. Git’te bu, şu anda üzerinde çalıştığınız yerel dalın bir işaretçisidir. Mevcut senaryomuzda halen master dalındasınız. git branch komutu sadece yeni bir dal oluşturdu ama henüz o dala geçiş yapmadı.

Bir dala işaret eden HEAD.
Görsel 13. Bir dala işaret eden HEAD

Dal işaretçilerinin nereye işaret ettiğini görmek için en basitinden bir git log komutu çalıştırabilirsiniz. Bu seçenek, --decorate olarak adlandırılır.

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

f30ab katkısının hemen yanında master ve testing dallarını görebilirsiniz.

Dallararası Geçiş

Var olan bir dala geçmek için git checkout komutunu çalıştırırsınız. Hadi yeni oluşturduğumuz testing dalına geçelim:

$ git checkout testing

Bu komut HEAD işaretçisinin yönünü testing dalına çevirir.

Mevcut dalı gösteren HEAD işaretçisi.
Görsel 14. Mevcut dalı gösteren HEAD işaretçisi

Peki bunun önemi nedir? Hadi şimdi başka bir katkı işleyelim:

$ vim test.rb
$ git commit -a -m 'made a change'
Bir katkı işlendiğinde `HEAD` ileriye doğru hareket eder.
Görsel 15. Bir katkı işlendiğinde HEAD 'in işaret ettiği dal ileriye doğru hareket eder.

İlginç bir şekilde, testing dalınız ileri hareket etti ancak master dalınız halen en son bıraktığımız halde (testing dalına geçiş yaptığınız anda üzerinde bulunduğunuz katkıya işaret ediyor). Hadi master dalımıza tekrar geçelim:

$ git checkout master
Başka dala geçtiğinizde HEAD’in yönü değişir.
Görsel 16. Başka dala geçtiğinizde (git checkout) HEAD’in yönü değişir

Bu komut iki şey yaptı: İlk olarak, HEAD işaretçisini tekrar master dalına çevirdi ve ikinci olarak, çalışma dizinindeki dosyaları master 'ın işaret ettiği poza geri dönderdi. Bu aynı zamanda, şu andan itibaren yapacağınız değişikliklerin projenin eski bir sürümünden sapacağı anlamına gelir. Bu testing dalındaki yaptığınız çalışmayı geri sararak daha farklı bir yöne gidebilmenizi sağlar.

Örnek 5. Dallar arasında geçiş yapmak çalışma dizinindeki dosyaları değiştirir

Git’te dallar arasında geçiş yaparken, çalışma dizininizdeki dosyaların değişeceğini unutmamalısınız! Eğer daha eski bir dala geçerseniz, çalışma dizininiz o dalda son katkı işlediğiniz ana geri döner. Eğer Git bunu temiz bir şekilde gerçekleştiremezse, geçiş yapmanıza hiç izin vermez.

Hadi bir kaç değişiklik yapalım ve katkı işleyelim:

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

Şimdi projenizin geçmişi sapmış durumda (bakınız Ayrık geçmiş (Divergent history)). Bir dal oluşturdunuz, ona geçtiniz, üzerinde çalıştınız, ardından ana dalınıza geri döndünüz ve bambaşka bir iş yaptınız. Her iki değişiklik farklı dallarda yalıtılmış durumdadır: Dallar arasında geçiş yapabilirsiniz ve istediğinizde onları birleştirebilecek durumdasınız. Bunların hepsini basit branch, checkout ve commit komutları ile yaptınız.

Ayrık geçmiş.
Görsel 17. Ayrık geçmiş (Divergent history)

Bu durumu git log komutuyla kolayca görebilirsiniz. Eğer git log --oneline --decorate --graph --all komutunu çalıştırırsanız; katkı geçmişiniz, dal işaretçilerinin nereye baktığı ve geçmişinizin nasıl ayrıldığı ekranda yazacaktır.

$ 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
* 34ac2 fixed bug #1328 - stack overflow under certain conditions
* 98ca9 initial commit of my project

Git’teki bir dal, aslında işaret ettiği katkının 40 karakterlik SHA-1 sağlamasını tutan basit bir dosya olduğu için, dalları oluşturmak ve yok etmek Git için çok kolaydır. Yeni bir dal oluşturmak, bir dosyaya 41 bayt yazmak kadar hızlı ve basittir (40 karakter ve bir satırbaşı).

Bu, yöntem olarak projenin tüm dosyalarını ikinci bir dizine yedeklemeyi seçen, çoğu eski VCS aracının kullandığı yolun kesin bir zıttıdır. Yedekleme yöntemi, projenin boyutuna bağlı olarak birkaç saniye veya hatta dakika bile sürebilir. Oysa Git’te katkı işlemi her zaman anlık olarak gerçekleşir. Ayrıca, katkı işlerken öncel katkıları da kaydettiğimiz için, birleştirmek için uygun bir nokta bulma işlemi otomatik olarak yapılır ve genellikle çok kolaydır. Bu özellikler, geliştiricileri sık sık dallar oluşturmaları ve kullanmaları yönünde cesaretlendirir.

Haydi, neden bunu yapmanız gerektiğini görelim.

Örnek 6. Tek komutla dal oluşturmak ve o dala geçiş yapmak

Yeni bir dal oluşturmak ve aynı anda o yeni dala geçmek sık karşılaşılan bir durumdur. Bunu tek komutla gerçekleştirebiliriz: git checkout -b <newbranchname>.

scroll-to-top