Her şey 5 Ocak 2010 tarihinde yazılan "A successful Git branching model" (Başarılı bir Git dallanma modeli) başlıklı yazı ile başladı. Bu yazıda @nvie, git depolarını derli toplu tutmak adına bir model önerdi. Sonrasında bu modeli kullanmayı oldukça kolaylaştıran git eklentilerini içeren git-flow isimli bir proje yayınladı.
Bu yazımda Git-flow modelini kısaca açıkladıktan sonra modeli gerçeklemeyi sağlayan git komutlarını ve bu işleri çok daha kolay hale getiren Git-flow eklentilerini irdelemeye çalışacağım. Son olarak ise SourceTree 1.5 ile gelen Git-flow kolaylıklarına kısaca değineceğim.
Git-flow modelinin altında Git sürüm kontrol sistemi yer alıyor. Bir başka deyişle modelin tüm aşamalarını Git komutlarıyla gerçekleştirmek mümkün. Git'in sağladığı neredeyse sıfır maliyetli dallanma ve tekrar birleştirme özellikleri aşağıdaki resimde genel olarak anlatmaya çalıştığım modelin temelini oluşturuyor.
Ana dallarımız olan develop ve master dalları hayatlarına sonsuza dek(en azından proje süresince) devam edecekler. master dalında her zaman production-ready(yayına alınabilir) kod bulunurken develop dalında bir sonraki sürüm için yapılan değişiklikler yer alıyor. master dalında her zaman yayınlanabilir kod olduğu için bu dala yapılan her commit bir betik ile otomatik olarak yayına alınabilir. develop dalı ise Jenkins gibi bir sürekli entegrasyon aracına bağlanarak her gece inşa edilebilir.
Yukarıdaki resimde git-flow ile geliştirme süreci başladığında master dalı 0.1 etiketi ile yayınlamış olan son güncel sürümde bulunmakta. Bu noktadan itibaren master dalından dallanarak yeni bir develop dalı oluşturuluyor. Mevcut durumda develop ve master dalı aynı koda işaret ediyorlar. Tüm geliştiriciler artık geliştirme sürecine develop dalından devam ederek bu dala commit ediyorlar.
Yeni özellik ekleneceği zaman bu özellik için feature(özellik) dalı açılıyor. Burada özellikten kasıt birden fazla commit içerecek görece büyük değişikliktir diyebiliriz. Aynı anda birden fazla özellik dalı açılabilir. Özelliklerin ayrı dallarda geliştirilmesi hem develop dalının gereksiz commitler ile dolmasını engeller hem de bu yöntemle özellikten vazgeçilmesi durumunda yalnızca özellik dalının silinmesi yeterli olur. Özellik tamamlandığında bu dal develop dalı ile birleştirilir(merge) ve özellik dalı silinir. Yani özellik dalları yalnızca özelliğin geliştirilmesi süresince yaşamlarına devam ederler.
Yeni bir sürüm yayınlanacağı zaman develop dalından yeni bir release dalı dallanır. Sürümdeki son değişiklikler(sürüm numarası değiştirmek gibi) bu dalda yapılır. Gerekli değişiklikler yapıldığında bu sürüm hem master hem de develop dallarına merge edilir ve master dalında sürüm numarası ile etiketlenir. Daha sonra release dalı silinir. Resimde 1.0 sürümü bu şekilde yayınlanmaktadır.
Yayınlanan sürümde kritik bir hata keşfedilmesi durumunda ve bu hatanın acilen çözülüp yayına alınması gerektiğinde hotfix dalları kullanılır. Gerekli hata çözümü yeni açılan hotfix dalında yapıldıktan sonra bu dal hem develop hem de master dalı ile birleştirilir. Yeni sürüm yeni bir sürüm numarası ile etiketlenir. Son olarak hotfix dalı silinir. Resimde 0.2 sürümü bu şekilde yayınlanmaktadır.
Çoğu Linux dağıtımı için git-flow paketi depolarda bulunmakta. Homebrew kullanıcıları
brew install git-flowkomutu ile Mac OS X için kolaylıkla kurulumu gerçekleştirebilirler. Diğer sistemler için kurulum bilgilerine buradan ulaşabilirsiniz.
Bu komut bulunduğu dizinde Git-flow sürecini başlatır. Komut çalıştırıldığında eğer mevcut değilse önce bir git repository oluşturur. Daha sonra kullanıcıya süreç için kullanılacak dal(branch) isimlerini sorar. Anlaşılacağı üzere dal isimleri özelleştirilebilir. Fakat uyumluluk adına dal isimlerinin varsayılan değerlerde bırakılması önerilir.
Initialized empty Git repository in /Users/fehmicansaglam/test/.git/ No branches exist yet. Base branches must be created now. Branch name for production releases: [master] Branch name for "next release" development: [develop] How to name your supporting branch prefixes? Feature branches? [feature/] Release branches? [release/] Hotfix branches? [hotfix/] Support branches? [support/] Version tag prefix? []
Böylece master ve develop dalları oluşmuş olur. Develop dalı seçili durumdadır.
[16:45:53]fehmicansaglam[test]:) $ git branch -v * develop 5fc4ad6 Initial commit master 5fc4ad6 Initial commit
Bu komut ile yeni bir özellik dalı açılır. Özellik adı performans olduğundan varsayılan özellik dalı feature/performans olacaktır.
[16:51:05]fehmicansaglam[test]:) $ git branch -v develop 5fc4ad6 Initial commit * feature/performans 5fc4ad6 Initial commit master 5fc4ad6 Initial commitAynı işi mevcut git komutlarıyla yapmak isteseydik aşağıdaki komutu kullanabilirdik.
git checkout -b myfeature feature/performans
Bu komut ile daha önce açılmış olan özellik dalı kapatılır. Kapatma işlemi önce özellik dalının develop dalına merge edilmesi ile başlar ardından da özellik dalının silinmesi ile sonlanır.
[16:58:01]fehmicansaglam[test]:) $ git branch -v * develop 75415e5 performans master 5fc4ad6 Initial commitAynı işi mevcut git komutlarıyla yapmak isteseydik aşağıdaki komutları kullanabilirdik.
git checkout develop git merge --no-ff feature/performans git branch -d feature/performans
Bu komut ile yeni bir sürüm yayını hazırlanmaya başlanır. Komut çalıştırıldığında develop dalından dallanan yeni bir release/1.0.0 dalı oluşur.
[17:02:18]fehmicansaglam[test]:) $ git branch -v develop 75415e5 performans master 5fc4ad6 Initial commit * release/1.0.0 75415e5 performansAynı işi mevcut git komutlarıyla yapmak isteseydik aşağıdaki komutu kullanabilirdik.
git checkout -b release/1.0.0 develop
Bu komut ile hazırlanması tamamlanan sürüm master dalına alınır. Yapılan değişiklikler hem master hem de develop dalı ile birleştirilir. master dalındaki son commit sürüm numarası ile etiketlenir. Ardından release dalı silinir.
[17:04:57]fehmicansaglam[test]:) $ git branch -v * develop 61ae36c Merge branch 'release/1.0.0' into develop master 68cc6e6 sürüm numarası güncellendi
[17:07:47]fehmicansaglam[test]:) $ git tag 1.0.0Aynı işi mevcut git komutlarıyla yapmak isteseydik aşağıdaki komutları kullanabilirdik.
git checkout master git merge --no-ff release/1.0.0 git tag -a 1.0.0 git checkout develop git merge --no-ff release/1.0.0 git branch -d release/1.0.0
Bu komut ile yeni bir hotfix başlatılıyor. Hotfixler acil güncellemelerde kullanılırlar ve master dalından dallanırlar. Komut çalıştırıldığında master dalından dallanan yeni bir release/1.0.0 dalı oluşur.
[17:16:10]fehmicansaglam[test]:) $ git branch -v develop 61ae36c Merge branch 'release/1.0.0' into develop * hotfix/1.0.1 e9f8075 kritik hata güncellemesi master 68cc6e6 sürüm numarası güncellendiAynı işi mevcut git komutlarıyla yapmak isteseydik aşağıdaki komutu kullanabilirdik.
git checkout -b hotfix/1.0.1 master
Bu komut ile hotfix tamamlanıyor. Değişiklikler hem develop hem de master dalına alınır. master dalı 1.0.1 ile etiketlenir ve hotfix dalı silinir.
[17:18:26]fehmicansaglam[test]:) $ git branch -v * develop 4ebcb2c Merge branch 'hotfix/1.0.1' into develop master d668862 Merge branch 'hotfix/1.0.1'
[17:18:28]fehmicansaglam[test]:) $ git tag -l 1.0.0 1.0.1Aynı işi mevcut git komutlarıyla yapmak isteseydik aşağıdaki komutları kullanabilirdik.
git checkout master git merge --no-ff hotfix/1.0.1 git tag -a 1.0.1 git checkout develop git merge --no-ff hotfix/1.0.1 git branch -d hotfix/1.0.1
Görüldüğü üzere model oldukça kolay olsa da Git-flow komutları olmadan ham Git komutları ile süreci yönetmek oldukça zor. Fakat Git-flow kurduktan sonra modelin avantajlarını göreceğinize ve kullanacağınıza inanıyorum.
Genelde konsolda çalışan biri olarak GUI uygulamalarını nadiren severim. SourceTree bu istisnalardan biri oldu. Uygulamanın 1.5 sürümü ile git-flow entegrasyonunun gelmesi işleri daha da kolaylaştırdı. Çoğu zaman süreçteki bir sonraki adıma tek bir düğme ile gitmek mümkün oluyor. Farklı bir adım izlemek isterseniz elbette seçme şansınız var. Daha ayrıntılı bilgi için şu blog yazısını okuyabilirsiniz.
Follow me on Twitter