Cumartesi, Mart 07, 2009

neden git kullanır insan?

şirkette subversion'dan git'e geçilmesi ardından yaşanan yoğun git karşıtlığı nedeniyle bir süredir git'i savunmak durumunda kalıyorum zaman zaman, ama çok da başarılı olduğum söylenemez, ben de savunmamı yazılı hale getirmeye karar verdim, belki böyle daha ikna edici olabilirim.

aslında şurada git'in diğer versiyon kontrol sistemlerine göre üstünlükleri oldukça detaylı açıklanmış.

kişisel tercih sebeplerimi özetlemem gerekirse:

* geliştirmenin bir kısmını teslim etmeye izin vermesi.
* 'git add -p' komuduyla çalıştırılan etkileşimli teslim modu.
* dallarla çalışmayı olağan hale getirmesi.
* geçmiş teslimleri birleştirme/bölme, teslim mesajını sonradan düzenleme gibi geçmişe yönelik işlemlere izin vermesi.
* ana depo ile klonlanan depo arasında bir farkın olmaması, daha doğrusu bir ana depo olmaması.
* başkasının yerine teslim edebilme olanağı sunması.
* "git-am" ile teslimlerin eposta yoluyla paylaşımının kolaylaştırılması.

bekir zamanında parkyeri'nde rcs'den svn'e geçildiğinde, insanların "nasıl yani, bir dosya değiştiğinde tüm deponun revizyonu mu değişecek" şeklinde tepki gösterdiklerinden bahsetmişti. git'e geçerek dosya dosya teslim edebilme özelliğimizi geri kazanmış olduk, hatta daha da fazlasını yapabilir hale geldik, artık hunk hunk teslimler yapabiliyoruz. yani değil dosya dosya, dosyada yaptığımız değişikliklerin bir kısmını bile teslim edebilir hale geldik.

git'te 3 aşamalı bir teslim anlayışı var. "git add" ile yaptığınız değişiklikleri önce "index"'e teslim ediyorsunuz; sonra "git commit" ile çalıştığınız dala; en son olarak da başka bir ana depo söz konusu ise "git push" ile, başka bir ana dal söz konusu ise "git merge" ile son teslimi yapmış oluyorsunuz.

svn'de "svn commit" ile tek aşamada yapılan bir işi niye böyle zorlu bir hale getirdik diye deliren insanlar olabiliyor bu durumda. öncelikle bu 3 aşamada yapılan işi, "svn commit"'in yaptığı işe denk saymak çok yanlış. geçmişte uzun zamanlı bir geliştirme yapacaksam (örneğin 1 haftalık) svn-rcs karışık kullanımına yöneliyordum. svn'den çektiğim depoyu aynı zamanda bir rcs deposuna çevirerek geri almayacağımdan emin olduğum değişiklikleri rcs deposuna teslim ediyordum, ve rcs diffleri üzerinden geliştirmeye devam ediyordum. aksi takdirde yama 1 haftada çok büyüyordu ve gözden geçirme olanaksız hale geliyordu. tabi svn-rcs karışık kullanımı bu derdimi çözüyor olmasına karşın hayatıma yeni dertler sokabiliyordu. git bu açıdan ilaç gibi geldi diyebilirim, bence gayet şık çözmüşler meseleyi. artık geliştirme esnasında ne zaman kopuk ve sonucundan emin olmadığım bir yola yönelecek olsam, "git add" ile kaybetmek istemediğim değişiklikleri öncelikle index'e alıyorum, koda korkmadan dalabiliyorum, baktım yolun sonu iyi değil, "git co ." ile anında temiz noktaya geri dönüş yapabiliyorum. 3 günlük bir geliştirme yapacaksam, her gün akşam "git add" ile yaptığım işi gözden geçirip varsa kalıcı kod, teslimlerimi yapıyorum, böylece 3 gün sonunda kocaman bir yama gözden geçirmektense bu işi gün gün yaparak gözden kaçırma durumunu en aza indirgemiş oluyorum.

"git add -p" index teslimlerini etkileşimli bir hale getirerek insanın işini epey bir kolaylaştırıyor. hunkları teker teker önünüze getirerek kabul edip etmediğinizi soruyor. tüm hunkların üzerinden geçerek kalacak kodları "index"'e ekliyorum, düzeltme gereken yerlerde arka planda değişiklikleri yapıyorum, hunklar bittikten sonra yeni düzeltmelerin teslimi için işlemi tekrarlıyorum, en sonunda sadece atılacak değişiklikler geriye kalıyor, "git co ." komuduyla bu kodları atıyorum.

svn-rcs karışık kullanacağına svn'de bir dal açsaydın da rahat etseydin diye düşünebilirsiniz, onu da denedim ancak svn'de dal kullanımı hiç de dökumanlarda yazıldığı gibi pratik bir şey değil. herşeyden önce dalı açma sebebim trunk'da yapamayacağım işleri dalda yapabilmek. peki bir insan trunk'da ne yapamaz? sonradan silme ihtimali olduğu kodların teslimini yapmaktan çekinir mesela, ya da tek satırlık teslimlerle ilerlemeyi tercih etmezsin genelde teslim logunu kirletmemek için. dalda bütün bunları yapabiliyorum artık güzel, geliştirmemizi bitirdik, geldik yaptıklarımızı trunk'a geçirmeye. bu aşamada benim yaptığım, dalı açtığım noktayla geldiğim son nokta arasındaki farktan hazırladığım yamayı trunk'a uygulamaktı. böylece dalda yazdığım çöp kodları ve tek satırlık teslimleri trunk'a almamış oluyordum, ancak o zaman da dal ile trunk arasındaki bağ kopuyordu, "svn merge" komudunu hiç kullanmaz oluyordum yani gerçek anlamda dal açmış olmuyordum aslında. svn'de dal açmış olmamın svn-rsc karışık kullanımına göre yarattığı tek fark geliştirmede geldiğim son noktayı ve geçtiğim aşamaları diğer insanlarla da paylaşabiliyor olmamdı. aslında "svn merge" hiç kullanmıyor da değildim, trunk'da yapılan değişiklikleri dala almak için tek yönlü bir şekilde kullanıyordum, onda da her defasında "svn merge -rX:Y" dediğimde X dahil oluyor muydu olmuyor muydu diye sürüncemede kaldığımı hatırlarım. dalda yaptığım değişikliklerden hazırladığım yamayı trunk'a uygulayıp teslim ettikten sonra, dalı trunk'la eşit hale getirme meselesi var tabi bir de. onun için de dalda, çatalladığım ilk revizyona döndükten sonra, o revizyon ile trunk'taki son revizyon arasını, geri aldığım dala "svn merge" ile birleştirirdim. bütün bu işlemler çok külfetli geldiğinden kısa sürede svn'de dal kullanımından vazgeçmiş, svn-rcs karışık kullanımına geri dönmüştüm.

peki svn'de dalla çalışmak problem de git de değil mi? pek değil, git'in tüm kurgusu dalların birleştirilmesi üzerine kurulu olduğundan tüm dal işlemleri gündelik hale geliyor, kısa sürede svn'de uzak durmaya çalıştığınız bir sürü şeyi çoktan refleks haline getirmiş oluyorsunuz. bir de git'te, "git rebase" diye bir komut var, yukarıda saydığım tüm problemleri tek kalemde çözüyor. bir daldan çatallayarak yeni bir dal oluşturdunuz, bu sırada ana dalda insanlar değişiklik yapmaya devam ediyor, bu değişiklikleri açtığıniz dala almak için "git rebase ANADAL" demeniz yeterli. ve artık açtığınız dalda korkmadan dilediğinizi özgürce yapabilirsiniz, çünkü git ile geçmişi de değiştirmeniz mümkün, yaptığınız tek satırlık teslimleri birleştirerek tek bir teslim haline getirebilirsiniz, geçmiş teslim mesajını değiştirebilir, "git cherry-pick" komudu ile başka dallarda hoşunuza giden değişiklikleri nokta atışı ile kendi dalınıza geçirebilirsiniz.

svn'de geçmişte değişiklik yapabilmeniz için svnadmin gibi bir komuda ve bazı izinlere ihtiyacınız olur, git'te ise bir depoyu klonladığınızda ana depoyu yerelinize çekmiş olursunuz. ana depo üzerinde yapabileceğiniz her işi yerelinizde de yapabilirsiniz. deponun geçmişinde bir şey değiştirebilmeniz için sistem yöneticilerine "şu değişikliği yapabilir misiniz?" diye e-posta atmanız gerekmez.

parkyeri'nde gözden geçirmeleri eposta ile yapardık, geliştirmenizi tamamladığınızda "[YAMA]" etiketli bir epostayla yamanızı yayınlardınız, herhangi biri gözden geçirip teslim edebilirsin dedikten sonra yamayı gönderen teslimi gerçekleştirirdi, eğer biri birşeyi beğenmezse yamayı gönderen gerekli değişiklikleri yapar ve tekrar bir yama gönderirdi. eğer süreç şu şekilde olsa bence daha etkin bir çalışma yöntemi olurdu. geliştirmesini bitiren yamayı yayınlar, bir diğer kişi yamayı kendi deposuna uygular, problemli bulduğu yerlerde istediği değişiklikleri yapar ve teslimi gerçekleştirir. bu şekilde aynı yamanın ufak değişiklikler yüzünden 8 defa gönderilmesi derdinden de kurtulmuş oluyoruz. bir de yama gözden geçirmek için eposta üzerinden hızlıca bir göz atmak çok uygun bir yöntem değil, gözden kaçırmalara çok açık, yamayı yerelinize uygularsanız ister istemez testini de yapar halde bulacaksınız kendinizi, bu da gözle yakalayamadığınız hataları yakalayabilmenizi sağlayacaktır, örneğin yamaya eklenmesi unutulmuş bir değişiklik varsa, veya ayar dosyasında yapılması gereken bir değişiklik yamaya eklenmemişse testiniz patlayacağından anında durumun farkına varabilirsiniz.

yalnız bu çalışma yönteminde, svn'de başkasının yerine teslim yapamadığınızdan değişikliklerin sahiplik bilgisinin kaybedilmesi gibi ciddi bir dert var. git'te ise istediğiniz kişi bilgileriyle teslim yapmanız mümkün. ve özellikle "git am" komudu ile teslimlerin eposta ile paylaşımı çok pratik bir hal aliyor, tek bir komutla eposta'daki yamayı yerelinize teslim edebiliyor ve yerelinizdeki teslimleri eposta haline getirebiliyorsunuz.

sonuç olarak bence git üzerine gerçekten kafa yorulmuş ve güzel tasarlanmış, kişisel olarak yasadığım bir çok derde çözüm oldu. git diğer versiyon kontrol sistemlerinin sunduğu özellikleri sağladığı gibi daha da fazlasını sunuyor. o yüzden git kullanan bir insan herhangi bir versiyon kontrol sistemini kullanabilir, ama tersinin doğru olduğunu söylemek zor. bu nedenle diğer versiyon kontrol sistemlerine alışmış ve halinden memnun olan insanlar yadırgayabiliyorlar, işlerin gereksiz karmaşıklaştırıldığını düşünüyorlar. bence karmaşıklaştırılıyor olsa bile gereksiz karmaşıklaştırılmıyor, yukarıda saydığım ve benim kendimce daha karmaşık çözümler ürettiğim bir sürü problemi çok güzel çözmüş. aslında birşeyi karmaşıklaştırdığı görüşünü de paylaşmıyorum, sadece farklılaştırıyor, ve alıştıktan sonra gündelik kullanımda diğer versiyon kontrol sistemlerinden daha fazla veya daha az yormuyor diye düşünüyorum.

özetle bence git doğru seçim.

1 yorum: