GitHub yazılımcılar için çok güçlü bir silah ve bana göre, yazılım ve bilgisayar mühendislerinin 2020 yılında kullanıyor olması gereken bir kontrol paneli Github. İleride eski köye yeni adetler gelebilir fakat şu an köyün muhtarı GitHub. Neden diye soracak olursanız cevap da belli. Artık dünyanın her yerinden herkes GitHub kullanıyor!
Ancak ne yazık ki herkes git konusunda uzman değil veya sitede yeni. Size birazdan vereceğim üç komut ne yaptığınızı gerçekten anlamadığınız sürece ASLA kullanmamanız gerektiğini düşündüğüm komutlar.
“İleride kimilerinin bu makaleyi eleştireceğini ve arkamdan atıp tutacağını düşündüğümden şimdiden bir şeyleri açıklığa kavuşturayım. Makalenin başlığında “ASLA” ibaresi yer alsa da burada gerçekten “ASLA” demek istemiyorum. Biraz abartı hayranı olsam da burada aktarmaya çalıştığım fikir, bu komutlar karmaşıklığı yeterince arttırma potansiyeline sahip komutlar yani bu komutları kullanmaktansa daha basit komutlar kullanarak sorununuzu daha rahat çözebilirsiniz.
Ayrıca önyargılı olduğumu görüyorum çünkü neredeyse yalnızca nispeten küçük projeler üzerinde çalışıyorum ve bu projeler 1-7 mühendisten oluşan küçük ekiplerle göreceli olarak sivri sorunları çözüyor. Google’ı geliştiren kişi ben değilim. Müşterilerimiz için belirli sorunları çözen adamım ben. Oldukça karmaşık projelere sahip daha büyük ekipler üzerinde çalışıyorsanız projenizin veya alt bileşenlerinizin geçmişinin makul ölçüde gezilebilir olmasını sağlamak için git rebase ve git alt modülünü kullanmanız gerekebilir. Eğer bu gruptaysanız, umarım internetteki rastgele bir kişi tarafından hevesle yazılmış bir makaleyi okuyarak, git rebase veya git alt modülü kullanıp kullanmama konusunda şüpheye düşmezsiniz. En başta belirttiğim gibi bu makaleyi GitHub’da uzman olmayan kişilere yardımcı olmak için yazıyorum.”
Git submodule
Basit bir dille submodule komutu git deponuzda yeni bir git deposu oluşturmanızı sağlar! Anlatınca ne kadar basit değil mi fakat birden çok alt modülü içeren bir projeyi yönetmek külfetli olabilir.
git submodule add <repository location>
Yukarıdaki komut, belirtilen depoyu geçerli git deponuza bir dizin olarak ekler. Bu dizinin kendisi tam bir git deposudur. Dizini yeni alt modülle değiştirirseniz, TÜM git komutlarınızın tamamen yeni bir depoya taşımışsınız gibi davrandığını göreceksiniz. Bu da tam olarak istediğiniz şey olmayabilir.
Ben en üst düzey depoya “ana” depo ve alt modülde oluşturduğumuz depoya da “alt” demek istiyorum. Ana depo içinde, alt modül olan dizin, git içindeki diğer herhangi bir dosyanın işleneceği şekilde az çok tam olarak ele alınır. Alt kod deposu değiştirildiğinde, üst modülün git durumunda alt modulun yeni sahipleri olduğunu veya içeriği değiştirdiğini göreceksiniz. Üstün bakış açısıyla, bir git alt modülü, uzak bir konum ve bir commit kimliği içeren tek bir dosyadan başka bir şey olarak düşünülemez! Bu dosyayı güncellemenin tek yolu ve dolayısıyla üst modülün alt modüle referansı, farklı bir kayıt kimliğiyle kaydetmektir. Yalnızca alt deponun en son yürütmesi( diğer adıyla HEAD) değiştiğinde ana depo git add / git commit komutu alt modülü tamamlayabilir.
Bu sezgisel olarak, alt modül içinde aktif olarak çalışıyorsanız, iş akışının ana modulun alt modüle referanslarını da içermesi gerekir. Yani siz alt modüle bir komut verdiğinizde tüm projenin güncel olması için bu komutu ana modüle de vermeniz gerekir. Eğer birden çok alt modül kullanıyorsanız bu çok yorucu olabilir sonuçta ne kadar çok alt modül kullanırsanız üst modüllere işlemeniz gereken bir çok yeni komut demektir bu. Bu yüzden bence alt modüller sadece ana havuzun geliştirme ekibinden farklıysa kullanılmalıdır.
Çıtır Not: Git submodule ’leri kullanırken, ana deponun alt modülün içeriklerin yedeğini saklayamayacağını unutmayın. Alt modülün başvurduğu konuma sahip değilseniz, referans verdiğiniz şeyin o konumda sonsuza kadar var olacağına dair bir garanti yoktur.
Git filter-branch
Bu komut son derece kullanışlı bir niş kullanım alanına sahip, akıl almaz derecede tehlikeli de bir komuttur. İşin sonucunda güzel olan her şey zararlıya çıkıyor tekrardan.
git filter-branch –tree filter ‘<terminal command>’ HEAD
Yukarıdaki git komutu HEAD’den başlayan ve HEAD’den geriye doğru çalışan her kesinleştirme için <terminal command> çalıştıracaktır. Komut, her kayıt için yeni içerikle yeni bir kayıt yaratacaktır. Örneğin,özel bilgilerinizi yanlışlıkla git deponuzda bir dosya olarak kaydettiğinizi düşünelim. Birden bire birkaç işlemden sonra durumun böyle olduğunu fark ettiniz. Bu dosyayı her kaydetmeden kaldırarak önceki işlemlerin tümünü yeniden yazmak için aşağıdaki komutu kullanabilirsiniz.
git-filter-branch –tree-filter ‘rm –f filename’ HEAD
Harika! Bu dosya artık geçmişinizin hiçbir yerinde yok.
Peki neden bu dosyayı kaldıran yeni bir kesinleştirme oluşturmak yerine bunu yapmak isteyesiniz? Kötü niyetli biri önceki işlemlerinize göz atabilir de ondan. Bu yüzden geçmiş kaydetmelerin hepsinden kaldırmak sizin için daha güvenlidir.
Harika! Yapmak istediğimiz şeyi yaptık. Her şey harika görünüyor peki sıkıntı ne?
Sorunumuz ise artık tamamen yeni bir geçmişe sahip tamamen yeni bir havuz oluşturmuş olmamız. Bir ekiple birlikte çalışıyorsanız ve paylaşılmış ortak bir depo varsa artık bu depodaki itme veya çekme yeteneğini yok ettiniz! Bunu düzeltmek için uzak depoya zorla gönderebilirsiniz, ancak bu durumda potansiyel olarak değerli değişiklikleri kalıcı olarak yok edersiniz.
Artık ortak bir geçmiş olmadığından, yerel deponuzu uzak depoyla karşılaştırmanın manuel olarak yapılması veya git filter-branch’dan önce yapılması gerekir.
Ayrıca git filter-branch komutunun kendisinin oluşturduğu değişikliklerin kayıtlı geçmişi olmayacak. Git filter-branch ile uyguladığınız değişiklikler olduğundan kesinlikle emin olun çünkü bu komutun geri dönüşü yok!
Bu yüzden tarihi yeniden yazmanızı ben tavsiye etmiyorum. Risk almaya gerek yok.
Git rebase
En tartışmalı git komutu işte tam karşınızda. Git merge yerine git rebase’ i zorunlu kılan birçok geliştirme ekibi vardır. Şahsen ben git merge’ü git rebase yerine tercih ediyorum. Bunun sebebi de basit. Git rebase geçmişi yeniden yazar ve geçmişi yeniden yazmak doğası gereği tehlikedilir.
Kafası karışanlar için rebase ve merge arasındaki farkı ve merge’ü neden tercih ettiğimi ayrıntılı olarak açıklayayım.
Merge ve rebase aslında aynı sorunu çözerler çözdükleri sorun da paralel değişikliklere sahip iki dalı tek bir geçmişe sahip tek bir dalda birleştirmektir.
Aşağıdaki görüntüde gösterildiği gibi ana dalımızın ve bir özellik dalımızın olduğu durumu inceleyelim.
Özellik dalı, “m2” taahhüdündeki ana şubeden oluşturulmuştur. Özellik dalı daha sonra “f1” ve “f2” kayıtlarındaki depoda değişiklikleri yaptı. “f1” ve “f2” kayıtlarındaki depoda değişiklikler de buna bağlı olarak yapıldı. “f1” ve “f2” değişiklikleri geliştirilirken, ana şube “m3” bağlanarak ile güncellendi. Ana dalı, özellik dalında yaratılan değişikliklere nasıl güncelleriz peki? İşte burada merge ve rebase arasındaki farkı anlatacağım.
Git merge bunu özellik dalının tüm işlemlerini koruyarak yapar.
Ana dalda HEAD’i hem de özellik dalının HEAD’i ile tarihsel bir ilişkisi olan yeni bir kayıt oluşturacaktır. Bu birleştirme taahhüdü, iki kolun nihai durumlarını çözmek için mevcuttur. İki dal arasında yapılan değişiklikler otomatik olarak çözülmezse, bir birleştirme çakışması oluşur ve kullanıcı, birleştirme taahhüdünün oluşturulmasından önce hangi değişikliklerin tutulması gerektiğine karar vererek çakışmayı çözümler. Genelde bu birleştirmelerin sonucunda bir sıkıntı çıkmaz içiniz rahat olsun yani.
Git rebase ’e gelecek olursak, git rebase bununla birlikte, taahhütleri tarih içinde hareket ettirerek iki şubeyi tek bir tarihe çözmeyi başarır. Örneğin, “f1” taahhüdündeki değişiklikler yerine “m2” ye uygulanır. git rebase, “f1” ve “f2” de yapılan değişiklikleri kaydedecek, özellik dalını “m3” temelli olacak şekilde taşıyacak, ardından “m3” üzerine “f1” ve “f2” yi uygulayacak. Eğer bir çelişki olursa, yeni temel kesinliğe uygulanacak her bir kesinleştirme için bu çatışmayı tek tek çözmelisiniz.
Git rebase harika çünkü işleri bitirdiğinizde ortaya çıkan git geçmişi düz bir çizgi. Birden fazla ebeveyni olan tek bir kayıt yok. Ancak rebase’den sonra “f1” ve “f2” taahhütleri artık orijinal “f1” ve “f2” taahhütlerinin gerçek korumaları değildir. Kayıt kimlikleri farklı olacaktır. İçerikleri farklı olabilir. Sonuç olarak, git filter-branch’ın yarattığı aynı soruna düşebilirsiniz. Paylaşılan bir uzak havuzla çalışıyorsanız ve payback’i yerel olarak gerçekleştiriyorsanız yukarıdaki hususa dikkat etmelisiniz. Sizin yaptığınız değişiklikler depoya erişebilecek diğer kişilerin değerli içeriklerinin kalıcı olarak kaldırılmasına sebep olabilirsiniz.
Genel olarak, ekipler git rebase kullanımını yalnızca ana şubeye çekme talepleri sırasında gerçekleşecek şekilde aktarır. Böylelikle potansiyel işbirliği sorunlarından kaçınılır. Yine de tarihi asla yeniden yazmamanızı tavsiye ederim.
Özet Olarak
Genel olarak konuşursak, git içinde geçmişi yeniden yazan veya çoğu insanın git ile nasıl etkileşim kurduğuna dair geleneği değiştiren davranıştan kaçınılmalıdır. Git alt modülleri, tüm proje için yalnızca bir kez yapılmasının aksine, değişikliklerin birden çok düzeyde izlenmesine neden olarak genel git kuralını değiştirir.
Git filter-branch ve git rebase git geçmişinizi yeniden yazar bunları unutmayın. Ve git geçmişi değiştiğinde ortaya çıkan komplikasyonlar olduğunu konuştuk. Bence git rebase’in git merge’e göre çok az avantajı var ve neredeyse her zaman kaçınılması gerekiyor. Ancak git filter-branch’ın zorlu durumlarda kullanımı vardır. Bu kullanışlı bir araç olmaktan ziyade “Ulan ben buraya nasıl geldim” durumlarında kullanılır. Böyle bir şey olduğunu bilmek güzel fakat umarım onu asla kullanmamıza gerek kalmaz.
Meriç ÇAPAR
Bunlar da ilginizi çekebilir
Kötü Amaçlı Yazılım (Malware) Nedir? ve Bilgisayarınızı Nasıl Koruyabilirsiniz?
Yapay Zekâ 10 Farklı Şekilde Bu Şaşırtıcı Yetenekleri Gösterdi!
Yorumlar 3