Versiyon Kontrol Sistemleri ve GIT
Last updated
Last updated
Herkese selam!
Versiyon kontrol sistemleri, bir projenin değişikliklerini takip etmek ve yönetmek için kullanılan yazılım araçlarıdır. Bu yazıda, yazılım dünyasının vazgeçilmez araçlarından olan versiyon kontrol sistemleri hakkında konuşacağız. Sonrasında ise günümüzün popüler sistemlerinden biri olan Git ve GitHub'a değineceğiz.
Başlamadan önce uzun bir yazı olacağını belirtmemde fayda var. O yüzden biraz gevşeyip rahatlayın ve kafeinli içecekleriniz hazır olduğunda Versiyon kontrol sistemi nedir? ile yumuşak bir giriş yaparak başlayalım :)
Versiyon kontrol sistemleri bir döküman üzerinde yapılan değişiklikleri adım adım kaydeden ve bunu yerel veya internet üzerindeki bir depoda (repository) saklayıp yönetmemize imkan sağlayan sistemlerdir. İşin içinde biraz matematik katarsak t sürede n tane dosya üzerindeki değişiklikleri yönetmemizi sağlayan sistemler olarak düşünebiliriz.
Bilinen versiyon kontrol sistemlerine örnek olarak CVS, SVN, Git, Mercurial, BitKeeper gibi sistemler gösterilebilir. Bunlar arasında en popüler olan ise Git'dir. Git nedir? demeden önce dilerseniz Neden VCS kullanmalıyız ve VCS türleri gibi konulara değinelim.
Geçmişte yazılımcılar sürüm kontrolü için yerel klasörlerde proje yedeklerini tutuyor ve hata ile karşılaştıklarında bu yedekler üzeridnen geri dönebiliyorlardı. Ek olarak birden fazla kişi tarafından geliştirilen projelerde geliştirme ortamı ortak olmadığından kodları birleştirirken klasörler arasında manuel olarak kopyalama ve yapıştırma işlemi yapmak gerekiyordu. Bu da hız ve zaman kaybı olarak kurum ve çalışana geri dönüyordu.
Böyle bir sistemin maliyetini anlamak için yavuzlar book projemizi düşünelim. Yaklaşık 30-35 farklı kişinin ortak bir sistemden bağımsız olarak kendi blogunu yazdığını, açılan PR'lar için kontrollerin manuel olarak sağlandığını, ana proje dosyası ile birleştirilecek olan yazıların klasörler arasında el ile kopyalanıp taşındığını, ana projenin gerisinde kalan dalların manuel olarak ana projeyle aynı olacak şekilde güncellendiğini ve bunun her bir yazı için tekrar tekrar yapıldığını hayal edin. Anlaması bile oldukça güç :)
Bu gibi sorunlara çözüm olarak hayatımıza giren versiyon kontrol sistemleri, geçmişte proje üzerinde yapılan değişiklikleri saklamamıza olanak sağlar, bu sayede projenin herhangi bir noktasına geri dönülebilmesini mümkün kılar. Bu yanlış yapılan bir güncellemeyi geri almak veya güncelleme sonrasında kaybedilen bir dosyayı geri getirmek için kullanılabilir.
VCS, birden fazla kişi tarafından aynı projenin gelitşirilmesine ve değiştirilmesine de olanak sağlar. Kalabalık projelerde işbirliği ve koordinasyonu artırmak, hataları azaltmak ve süreci verimli hale getirmek gibi avantajlar sağlar. Birkaç madde altında listelemek gerekirse bu avantajları şu şekilde sıralayabiliriz:
Projenin geliştirme sürecini hızlandırır ve ürünün çıkma süresini kısaltır.
Kalabalık projelerde eş zamanlı geliştirme ve değişikliğe olanak sağlar.
Her değişiklik için görüntülenebilirlik sağlar, bu sayede hatalar minimuma düşer.
Eski ve yeni kodlar arasında karşılaştırma yapmamızı mümkün kılar.
Açık kaynaklı projeler temel alınarak geliştirilen projelerde süreci kolaylaştırır.
Bu ve bunun gibi maddeleri çoğaltabileceğimiz gibi yazılım dünyasında da örneklerini görebildiğimiz senaryolar oldukça fazladır.
Versiyon kontrol sistemleri kullanım şekillerine göre 3 farklı başlık altında incelenebilir. Bunlar local, merkezi ve dağıtık versiyon kontrol sistemleridir. Şimdi sırasıyla bu başlıklara değinelim ve farklarını anlamaya çalışalım.
En eski versiyon kontrol sistemi yaklaşımıdır. Proje dosyaları ve yapılan değişiklikler direkt olarak geliştiricinin ana bilgisayarı üzerinde saklanır. Her commit bir versiyon olarak tutulur ve commit değerine hash ataması yapılarak versiyonlar birbirinden ayrılır. Versiyon görüntüleme imkanı sağlasa da bu sistemde sadece bir kullanıcı etkin bir şekilde çalışabilir.
Birden fazla etkin kullanıcının aynı proje üzerinde çalışabilmesi için ortaya atılmış versiyon kontrol sistemi tipidir. Bu sistemde proje ortak bir depo üzerinde tutulur ve birden fazla geliştirici aynı depo üzerinde işlemler gerçekleştirebilir. Ancak tek merkezli bir sunucu üzerinden işlemler gerçekleştirildiğinden arızlanması durumunda çalışmaların ve yeni sürümlerin kaydetilmesi mümkün olmamaktadır.
CVS, SVN gibi sistemler, merkezi versiyon kontrol sistemlerine örnek olarak gösterilebilir.
Merkezi versiyon kontrol sistemleri üzerindeki belirli eksikliklerden yola çıkılarak geliştirilmiştir. Bu sistemlerde merkezi bir depo yaklaşımı bulunmamaktadır. Proje üzerinde çalışan her makine projenin kopyasını kendi yerel makinesinde tutar. Proje üzerinde değişiklik yapmak isteyen geliştirici uzak sunucudaki depo ile iletişime geçmek zorunda değildir. Ortak olan tek şey projedir.
Git, Mercurial, BitKeeper gibi sistemler, dağıtık versiyon kontrol sistemlerine örnek olarak gösterilebilir.
Yukardaki örneklerde adı geçen sistemlere ek olarak günümüzde başlıca versiyon kontrol sistemi türleri GitHub, BitBucket, Azure Devops, Apache Subversion, SourceForge ve GitLab olarak karşımıza çıkmaktadır. GitHub, dünya geneline baktığımızda en popüler olan VCS platformudur. Hangi platformu kullanacağınız proje gereksinimleri ve ekibin ihtiyaçlarına göre şekillenebilir ancak yazının bundan sonraki kısmına Git üzerinden devam edeceğiz.
Bilgisayar bilimleri üzerine çalışan ancak yazılım dünyasına uzak olan birçok insan Git ve GitHub'ı aynı olgu olarak düşünseler de işin aslı öyle değildir. Git, geliştirme ortamındaki dosyaları versiyonlara ayırarak iterasyonlar halinde geliştirmeye olanak sağlayan ve kişisel bilgisayar üzerinde çalışan bir uygulama olarak düşünülebilir. GitHub ise Git kullanılarak geliştirilen projelerin depolanabileceği bir servistir.
Git'in ortaya çıkma hikayesi ise şu şekilde:
Başlamadan önce belirtmeliyim ki Linux Kernel projesi oldukça geniş kapsama sahip açık kaynak bir yazılım projesidir. Bu projenin gelişim süresinin büyük bir kısmında (1991-2002) yapılan değişiklikler, başta da bahsettiğimiz gibi yamalar ve arşivlenmiş dosyalar üzerinden ilerliyor. 2002 yılına geldiğimizde ise proje, dağıtık bir versiyon kontrol sistemi olan BitKeeper'ı kullanmaya başlıyor. Bu süreç, 2005 yılında BitKeeper ve Linux Kernel Geliştirme Ekibi arasındaki ilişkiler kesilene kadar devam ediyor ve hikaye burada başlıyor.
Geliştirme sürecinde hedeflenen unsurlar ise Hız, Minimal Tasarım, Doğrusal olmayan geliştirme desteği (branch), Tamamen dağıtık olması ve Linux çekirdeği tarafından desteklenmesi olarak kayıtlara geçiyor. Bu kapsamı günümüze kadar koruyan ve günümüz dünyasının en popüler sistemlerinden biri olan Git, Linus'un zamanında söz verdiği üzere 2 hafta gibi kısa bir sürede geliştiriliyor. Sonrasında Git'in kendi kaynaklarında yapılan açıklama ise şu şekilde oluyor:
Hayattaki harika olan diğer pek çok şey gibi, Git de yaratıcı yıkım ve ateşli tartışmaların sonucunda ortaya çıktı.
Ayrıca Linus, GIT'in açılımını şu şekilde ifade ediyor:
Düzgün çalışıp iş gördüğünde ve sizi mutlu ettiğinde "Global Information Tracker"; İstediğiniz gibi çalışmazsa ve sizi çıldırtırsa da "Goddamn Idiotic Truckload of shit".
Hikaye kısmını burada bitiriyorum. Şimdi gelin üzerinde konuştuğumuz bu sistemi kendi bilgisayarımıza nasıl kuracağımızı görelim.
Bu komut sonucunda bir hata mesajı ya da uyarıdan bağımsız olarak versiyon numaranızı ekranda görebiliyorsanız, düzgün bir şekilde kurulum tamamlanmış demektir.
Bu adıma kadar başarıyla geldikten sonra Git'in config ayarlarını basitçe düzenlememiz gerekmektedir. Bu kısımda düzenleyeceğimiz bilgiler arasında username
ve mail address
bilgileri bizi karşılıyor olacak. Bu noktada terminalde kaldığımız yerden devam ederek aşağıdaki komutları girmemiz yeterlidir:
Bu adımı da başarıyla tamamladıktan sonra git kullanıma hazır bir şekilde bizi bekliyor olacaktır.
Bu adıma kadar işlemleri tamamladığımıza göre gelin beraber Git'in çalışma mimarisinden biraz bahsedelim.
## Git'in Çalışma Mantığı
Git mimarisini anlarken, sistemi çok temel olarak bir kargo firmasına benzetebiliriz. Nasıl ki alışveriş yaptıktan sonra kargolarımız hazırlanıp, paketlenip, yola çıkıp, dağıtım merkezine geliyorsa; Git üzerinde yaptığımız değişiklikleri de bu şekilde düşünebiliriz. Bu mantık çerçevesinde bilmeniz gereken 4 temel kavramı maddeler halinde sırayla inceleyelim.
Working Tree, projenizin fiziksel dosyalarının ve dizinlerinin bulunduğu alandır. Bu alanda, üzerinde çalıştığınız ve değişiklikler yaptığınız dosyaları görebilirsiniz. Yani, çalışma ağacı, projenizin mevcut durumunu yansıtan ve üzerinde değişiklikler yapılan gerçek dosya ve klasörlerin bulunduğu alandır. Bu dosya ve klasörleri git add .
komutu ile staging area ya göndeririz.
Bunu kargo örneğindeki alışveriş kısmı gibi düşünebiliriz. Sepetteki değişikliklerimizi yapıp siparişi verme adımına kadar olan bütün süreç working wree adımına benzetilebilir.
Staging Area, projenizdeki değişiklikleri hazırladığınız ve bir sonraki commit'e dahil etmek istediğiniz dosyaları geçici olarak depoladığınız alandır. Yani, bu alana eklenen dosyalar, bir sonraki commit işlemi sırasında commit'e dahil edilecek olan dosyalardır. Staging Area, değişikliklerinizi adım adım incelemek ve gerektiğinde düzenlemek için bir ara alan sağlar. Bu ara alandaki dosyalarımızı local repository'e atmak için kullanacağımız komut git commit -m "mesajınız"
olacaktır.
Bizim örneğimizde bu adımı kargomuzun paketlenmesi olarak düşünebiliriz. Mağazadan henüz çıkmamış ancak çıkmaya hazır olarak paketleme bölümünde geçici olarak bekleyen bir paket gibi. İçeriği son kez kontrol edilir, gerekli kontroller sağlandıktan sonra paketimiz yola çıkmaya hazırdır.
Local Repository, projenizin yerel olarak saklandığı ve tüm commit geçmişinin bulunduğu alandır. Git'in tüm versiyon geçmişi ve projenin tamamı bu depoda saklanır. Yerel depo, bilgisayarınızın dosya sistemine yerleştirilmiş olan ".git" klasörü içinde bulunur. Bu depo, projenizin tüm geçmişini ve değişikliklerini izlemek, yönetmek ve geri almak için kullanılır. Örneğimize geri dönecek olursak bu adım nakliyat için kullanılan kamyonlarımız olarak düşünülebilir. Kargonun hareketleri dahil olmak üzere geçtiği tüm aşamaların kaydının tutulduğu senaryo da göz önüne alınırsa oldukça benzer bir senaryo olarak karşımıza çıkmaktadır.
Remote Repository, projenizin internet üzerinde uzaktaki bir sunucuda saklandığı alandır. Bu depo, genellikle projenizi diğer geliştiricilerle paylaşmak, işbirliği yapmak ve yedeklemek için kullanılır. GitHub, GitLab veya Bitbucket gibi hizmetler, projelerinizi uzak depolarda barındırmanıza ve diğer kullanıcılarla paylaşmanıza olanak tanır. Bizim örneğimizde bu aşama kargonun dağıtıma çıkmadan önce geldiği depo olarak düşünülebilir. Onlarca farklı kişiye gidecek olan kargoların tamamının depolandığı bu merkezleri remote repository'e benzetebiliriz.
Aşağıdaki görsele bakarak ve fiziksel ortamda verdiğimiz örnekleri de göz önüne alarak, bu işlemlerin soyut ortamda nasıl şekillendiğini görebiliriz:
Bu adımlara hakim olduktan sonra git üzerindeki temel kavramlardan da biraz bahsetmemiz gerektiğine inanıyorum. Bu kısımda bahsedeceğimiz kavramları bilmek, git üzerinde -özellikle komut satırında- ne yaptığımız hakkında fikrimiz olması açısından oldukça önemlidir. Bu kavramlar aynı zamanda, projenin farklı versiyonlarını oluşturmak, değişiklikleri izlemek ve işbirliği yapmak için gereklidir. Temel olarak 5 madde altında branch, master/main, commit, head ve conflict kavramlarını inceleyelim.
Branch (Dal): Bir Git reposunda, branch veya dal, projenin farklı bir versiyonunu temsil eder. Her branch, projenin belirli bir noktasındaki değişikliklerin bir kopyasıdır. Bu, farklı özelliklerin veya hata düzeltmelerinin ayrı ayrı geliştirilebileceği ve test edilebileceği anlamına gelir.
Master/Main: Master veya main, genellikle varsayılan ana dalı temsil eder. Bu dal, projenin en güncel ve kararlı sürümünü içerir. Ancak, "master" terimi yerine bazı platformlarda "main" terimi kullanılmaya başlanmıştır.
Commit: Bir commit, projenin belirli bir anındaki değişikliklerin bir kaydıdır. Bir commit işlemi, projedeki dosyaların belirli bir durumunu sabitlemek için kullanılır. Her commit, bir açıklama (commit mesajı) ile belgelenir ve projenin geçmişinde bir dönüm noktası oluşturur.
HEAD: HEAD, projenin şu anda çalışılan dalındaki son commit'i gösteren bir referanstır. Yani, HEAD, projenin "anlık durumunu" belirtir ve üzerinde çalışılan branch'i veya commit'i işaret eder.
Conflict: Bir conflict, genellikle aynı dosya üzerindeki farklı değişikliklerin çakışması sonucunda oluşan bir durumdur. Çatışma, aynı dosyanın aynı bölgesinde yapılan değişikliklerin uyumsuz olduğu durumlarda gerçekleşir.
Temel kavramlardan sonra bilmemiz gereken şey ise Temel Git Komutları'dır. Bu sayede projelerimizin versiyon kontrolü, işbirliği, dağıtılmış geliştirme süreci, proje yönetimi ve yazılım dağıtımı gibi maddeleri kontrol altında ve kolayca yönetilebilecek şekilde kalır. Bu kısımda bahsedeceğimiz komutlara tek tek bakalım.
git init: Yeni bir Git deposu oluşturmak için kullanılır. Bu komut, mevcut bir proje dizinini Git deposuna dönüştürür.
git clone [repository_url]: Uzak bir Git deposunu kopyalamak için kullanılır. Bu komut, bir uzak deposunun tam bir kopyasını yerel makinenize indirir.
git add [file_name(s)]: Çalışma dizinindeki değişiklikleri Staging Area'ya eklemek için kullanılır. Dosya adı belirtilmezse, tüm değişiklikler Staging Area'ya eklenir.
git commit -m "commit_message": Staging Area'daki değişiklikleri yerel deposuna kaydetmek için kullanılır. "-m" seçeneği ile bir commit mesajı belirtilir.
git status: Çalışma dizinindeki dosyaların durumunu ve Staging Area'daki dosyaları göstermek için kullanılır. Hangi dosyaların değiştirildiğini veya Staging Area'ya eklenmeyi beklediğini gösterir.
git log: Yerel depodaki commit geçmişini göstermek için kullanılır. Tüm commitlerin listesini, her bir commit'in kim tarafından yapıldığını, ne zaman yapıldığını ve commit mesajlarını içerir.
git push: Yerel depodaki değişiklikleri uzak bir depoya göndermek için kullanılır. Bu komut, yerelde yaptığınız commit'leri uzak bir depoya yükler.
git pull: Uzak bir depodan güncelleme almak için kullanılır. Bu komut, uzak depodaki değişiklikleri yerel depoya çeker ve yerel projeyi günceller.
git branch: Mevcut branch'leri göstermek için kullanılır. "-a" seçeneği ile uzak branch'leri de gösterebilirsiniz.
git checkout [branch_name]: Başka bir branch'e geçmek için kullanılır. Ayrıca, bu komutla bir dosyanın belirli bir commit'ini geri alabilirsiniz.
git merge [branch_name]: Farklı bir branch'deki değişiklikleri mevcut branch'e birleştirmek için kullanılır.
git rebase [branch_name]: Mevcut branch'i belirtilen bir branch'e yeniden tabanlamak için kullanılır. Bu, projenizin geçmişini daha düzenli ve düzgün tutmanıza yardımcı olabilir.
Bu temel Git komutları, Git'in temel işlevlerini gerçekleştirmenize olanak tanır. Projelerinizi yönetmek, değişiklikleri takip etmek ve işbirliği yapmak için bu komutları kullanarak Git'i etkili bir şekilde kullanabilirsiniz.
Evet, yine oldukça uzun bir yazı oldu. Örnek uygulamayla yazıyı desteklemek ve desteklememek arasında çokça kaldım ancak bu şekilde noktalamaya karar verdim. Bundan sonraki süreçte meraklı arkadaşlara sistemi kurcalayıp, çokça bozarak işin kalan kısmını uygulamalı olarak öğrenmek kalıyor :) Umarım açık ve bilgilendirici bir yazı olmuştur ve okurken keyif almışsınızdır.
Keyifli kodlamalar :))
Fotoğraftaki kişi , Linux işletim sisteminin yaratıcısı olarak kabul edilen kişi. BitKeeper ile ilişkilerin kesilmesinden sonra Linus, Linux Kernel'ı taşıyabileceği bir versiyon kontrol sistemi arıyor ancak istediği özellikleri tam anlamıyla karşılayan bir sistem bulamıyor. Bunun üzerine Linus, "İki haftada SVN ve CVS’den daha kullanılabilir bir sistem yazabilirim" şeklinde bir iddiada bulunuyor ve BitKeeper'ı kullanırken edindiği deneyimler sonucunda kendi dağıtık versiyon kontrol sistemini geliştirmeye başlıyor.
Gelelim Git'in kişisel bilgisayarımıza kurulumuna. Git'in kişisel bilgisayarınıza kurulumu oldukça basittir. İlk olarak, üzerinden işletim sisteminize uygun olan Git sürümünü indirin. İndirme işlemi tamamlandıktan sonra, indirdiğiniz dosyayı çalıştırarak kurulum sürecini başlatın. Kurulum süreci boyunca, genellikle varsayılan seçeneklerin çoğu sizin için uygun olacaktır. Kurulumu tamamladıktan sonra terminale girip aşağıdaki komutu yazın.