Yazılım dünyası DVCS (Distributed Version Control System)’lere geçerken seyirci kalıp CVS’i sorgulamamak ayıp olurdu. Bu yazımda CVS’te olmayıp DVCS’lerin (özellikle Mercurial ve GIT’in) bize vaad ettiklerini, DVCS’lerin birbirlerine göre üstünlüklerini-ezikliklerini anlatmaya çalışacağım.
Tarihçe
Öncelikle DVCS’lerden önceki furya olan CVS ve SVN gibi araçların eski olduklarından, yazıldıkları dönemlere göre dizayn edildiklerinden bahsetmek gerek. Biraz tarih dersi vermek gerekirse CVS 1986 yılında, SVN’de 2000 yılında yazılmaya başlanmış. Bu araçların dizayn edildiği zamanlarda dağıtık (distributed) çalışma, günümüzdeki farklı lokasyonlardan - uzaktan çalışan insanların bulunduğu foundation projelerinde olduğu kadar önemli olmadığı için öyle dizayn edilmemişler. Ortada bir tane repository var ve tüm geliştiriciler bu repository’ye kod girişi yapıyorlar. Lokal repository gibi bir kavram söz konusu değil.
Uygulanabilirlik
Bu noktada “bizde şunun şurasında aynı yerde çalışan insanlarız, bu zımbırtılara ihtiyacımız yok” diyebilirsiniz, saygı duyarım =) Ama bu distributed çalışma olanağı öncelikle kolaylıkla ve lineer olmayan branching/merging yapmaya izin verdiği için bizimde işimize yarayabilir. Lineer branch history’den biraz daha bahsetmek gerekirse svn’de örnek bir proje geçmişi ve dallanması aşağıdaki şekilde olabilir:
Şekil 1: Visualization of a simple Subversion project [1]
Agile çalışıp SCRUM yapanlar sprint bazlı development branch’lere çıkmak isteyebilir. Hatta bununda ötesinde her developer’ın kendi branch’i olup unit testi veya code review’ları tamamlanmayan kodun sprint branch’ine konulmaması gibi uçuk uygulamalarda bulunabiliriz. Örneğin aşağıdaki akış biraz karışık görünsede oluşturan arkadaş epey geniş düşünmüş ve bütün olası problemleri bertaraf etmeye çalışmış, faydalı bir dizayn olmuş:
Şekil 2: A successful GIT branching model [2]
Bu kadar branch’i / merge’ü CVS’te yaptığınızı düşünsenize !
GIT & Mercurial vs CVS
Bu temel farkın dışında modern araçların CVS’e üstünlüklerini maddeler halinde sıralamak gerekirse:
1) CVS atomik işlem yapmadığı için yarıda kalan bir commit sistemi stabil olmayan bir durumda bırakabilir. Veya bir dizi dosyayı commit etmek istersiniz ancak bazıları commit edilip bazıları edilmeyebilir. GIT ve Mercurial’da commitler atomic, dolayısıyla sistem daha stabil.
2) CVS’te değişikler dosya bazlı tutulurken GIT ve Mercurial’da changeset commit yapılıyor. Bu sayede bir commit silsilesini geri almak istediğimizde CVS’te tek tek dosyaları bir önceki versiyona çekmemiz gerekirken DVCS’lerde changeset’i geri almak kafi. Çözüm olarak CVS’te manual tag’leme yapılmalı.
3) CVS’te klasörlerin tarihçesi tutulmuyor. Birinci sınıf nesne değil, versiyonlanmıyor.
4) CVS ile dosya veya klasörleri taşımak veya yeniden adlandırmak mümkün değilken modern DVCS araçlarında bu mümkün.
5) CVS’te commit’ler üstünde geniş bir kontrol hakkı yok. Örneğin commit öncesi code review şartı koymak pek mümkün ve uygulanabilir değil. Sadece bazı CVS hook script’leriyle pre-commit ve post-commit yapılabiliyor.
6) DVCS’lerde branching/merging günlük hayatın bir parçası olarak kabul edilmiş durumda. CVS’te bunlar birer öcü =) CVS’te branch ve tag açmak, yönetmek ve silmek zor.
GIT vs Mercurial
GIT ve Mercurial’ın CVS’e üstünlükleri konusunda tartışma konusu olacak pek birşey yok. Ancak Mercurial vs GIT dendiği noktada tartışmalar şiddetleniyor. Google’ın bile buna bulaştığını ve DVCS Analizi
[3] isminde bir döküman hazırladığını belirtmem gerekiyor.
GIT ve Mercurial aslında büyük ölçüde birbirlerine benziyorlar. Ancak kendi içlerinde kıyaslamak gerekirse, birbirlerine göre avantaj/dezavantajları şöyle listelenebilir:
| GIT | Mercurial |
GIT commit, pull, merge gibi operasyonlarda daha hızlı
| Mercurial büyük ölçüde pyhton ile yazılmış. Native olarak Windows desteği sunuyor. GIT’te ise cygwin, mingw, msysGit gibi unix porting’leri üzerine kurulum yapabiliyorsunuz. Ki bu durumda GIT hız avantajını kaybetmiş oluyor
|
GIT branch’leri ref adı altında bir referans objesi ile (pointer to commit) tutuyor. Bu sayede bu pointer’ları (dolayısıyla branch’leri) kolaylıkla yeniden isimlendirebiliriz, silebilir, fetch ve push yapabiliriz. Mercurial’da ise branch’ler üzerinde bu kadar rahat operasyonlara izin verilmiyor. Branch’ler silinemiyor, sadece kapatılabiliyor
| Mercurial’daki komut ve seçenek sayısı GIT’ten daha az. Bu yüzden öğrenmesi daha kolay. Ayrıca komut isimleride geleneksel VCS’lere daha çok benziyor
|
Bu noktada DCVS’lere olası bir geçişin özellikle çok sık ve fazla sayıda branch’e çıkma - merge etme gibi ihtiyaçlardan ortaya çıktığını hatırlatıp bu konuda daha başarılı olduğundan GIT’in öne çıktığını belirtmem gerekiyor.
Birazda piyasada bu araçlar ne durumda, kimler kullanıyor, hangisi daha popüler gibi soruları cevaplamaya çalışayım:
GIT :
- Linux Kernel, Eclipse, Android, Fedora, GNOME, Perl, VLC vs GIT’e geçmiş durumda.
- Eclipse plugin’i mevcut. Eclipse projeleri kodlarıda GIT ile maintain edildiği için native olarak destekliyor. Ayrıca Eclipse plugin’i Mercurial’ın Eclipse plug’inine göre 3 kat daha popüler.
- Syntevo’nun SmartGIT isimli ücretsiz ve cross-platform olan programı ile Eclipse dışındanda başarıyla kullanılabilir.
Mercurial:
- Mozilla, OpenJDK, OpenOffice, Atlassian
[4], Python, Netbeans vs Mercurial kullanmakta.
- Eclipse plugin’i mevcut. Ancak GIT pluginine göre 3’te bir oranında popüleriteye sahip. Dolayısıyla Eclipse camiasında daha az destekçisi bulunuyor.
- GUI olarak open-source ve cross-platform olan TortoiseHg’ye sahip.
GIT & Mercurial Komut Listesi
GIT ve Mercurial’ın komut listesine gelirsek şöyle bir tablo ile karşılaşıyoruz:
Git
| Mercurial
|
git pull
| hg pull -u
|
git fetch
| hg pull
|
git reset --hard
| hg revert -a --no-backup
|
git revert <commit>
| hg backout <cset>
|
git add <new_file>
| hg add <new_file> (Only equivalent when <new_file> is not tracked.)
|
git add <file>
| Not necessary in Mercurial.
|
git add -i
| hg record
|
git commit -a
| hg commit
|
git commit --amend
| hg qimport -r tip ; hg qrefresh -e ; hg qfinish tip (Requires the MqExtension.)
|
git blame
| hg blame or hg annotate
|
git blame -C
| not available in Mercurial?
|
git bisect
| hg bisect
|
git rebase --interactive
| hg histedit <base cset> (Requires the HisteditExtension.)
|
git stash
| hg shelve (Requires the ShelveExtension or the AtticExtension.)
|
git merge
| hg merge
|
git cherry-pick <commit>
| hg graft <cset>
|
git rebase <upstream>
| hg rebase -d <cset> (Requires the RebaseExtension.)
|
git format-patch <commits> and git send-mail
| hg email -r <csets> (Requires the PatchbombExtension.)
|
git am <mbox>
| hg mimport -m <mbox> (Requires the MboxExtension and the MqExtension. Imports patches to mq.)
|
git checkout HEAD
| hg update
|
git log -n
| hg log --limit n
|
Tablo1: GIT ve Mercurial komut listesi [5]
Referanslar: