28 puan yazan GN⁺ 2023-11-24 | 1 yorum | WhatsApp'ta paylaş
  • Birçok kişi Git branch’in nasıl çalıştığını sezgisel bulmuyor.
  • Git branch’lere dair yaygın sezgisel model ile branch’lerin Git’in içinde gerçekte nasıl temsil edildiği arasındaki fark açıklanıyor.
  • Sezgisel model ile Git’in gerçek çalışma biçiminin aslında birbirine çok yakından bağlı olduğu gösteriliyor.
  • Sezgisel modelin sınırları ve neden sorun çıkarabileceği tartışılıyor.

Sezgisel branch modeli

  • Birçok kişi branch’i “elma ağacının dalı” benzetmesiyle düşünüyor.
  • Git’te branch’in “ebeveyn” kavramı yok; bu yüzden bir branch’i main’den dallanmış gibi düşünmekten farklı.

Git’te branch, tüm geçmişi kapsar

  • Git’te branch, yalnızca ayrılmış commit’lerden ibaret değil; önceki tüm commit geçmişini içerir.
  • Örnek bir depo üzerinden hem main hem de mybranch için 4 commit bulunduğu gösteriliyor.

Branch’ler commit ID ile saklanır

  • Git içinde branch’ler, commit ID içeren küçük metin dosyaları olarak saklanır.
  • Her branch’in en son commit’i ilgili dosyada kayıtlıdır.
  • Commit’ler arasında ebeveyn-çocuk ilişkisi olmadığı için Git, branch’ler arasındaki ilişkiyi bilemez.

İnsanların sezgisi genelde o kadar da yanlış değil

  • İnsanların Git’e dair sezgisinin “yanlış” olduğunu söylemek biraz anlamsız.
  • “Yanlış” bir model bile pratikte faydalı olabilir.

Rebase, “sezgisel” branch kavramını kullanır

  • Rebase, yalnızca “sezgisel” branch’e ait commit’leri main üzerine yeniden uygular.
  • Rebase sonucu, sezgisel modelle uyumludur.

Merge de “sezgisel” branch kavramını kullanır

  • Merge commit’leri kopyalamaz, ancak ortak bir temel commit gerektirir.
  • Merge base, sezgisel modele göre branch’in ayrıldığı commit’i bulur.

GitHub pull request’leri de sezgisel fikri kullanır

  • GitHub’da mybranch’i main ile birleştirmek için pull request oluşturduğunuzda, yalnızca sezgisel branch’e ait commit’ler gösterilir.

Sezgi iyidir ama sınırları vardır

  • Sezgisel branch tanımı gerçek Git çalışmasıyla oldukça iyi örtüşür, ancak Git main ile ondan ayrılmış bir branch’i farklı şekilde algılayamaz.

Trunk ve ondan ayrılan branch’ler

  • İnsanlar main ile mybranch’i farklı algılar ve bu, Git’i kullanma biçimlerini etkiler.
  • Git, bir branch’in başka bir branch’in “dalı” olup olmadığını ayırt etmez.

Git, rebase’i “ters yönde” de yapabilir

  • Git, bir branch’in başka bir branch’in “dalı” olup olmadığını bilmediği için hangi branch’in ne zaman rebase edilmesi gerektiğini kullanıcı belirlemelidir.
  • Hem git rebase main hem de ters yöndeki git rebase mybranch mümkündür. Merge için de aynısı geçerlidir.

Git branch’leri arasında hiyerarşi olmaması biraz tuhaf

  • main branch’inin özel olmadığı sözü, Git’in branch’ler arasındaki ilişkiyi tanımamasından kaynaklanır.
  • Branch’ler arasında ilişkiler vardır, ama Git bundan habersizdir.

Git branch arayüzü de tuhaf

  • Yalnızca “ayrılmış” commit’leri görmek istediğinizde git log ile git diff kullanma biçimi farklıdır.

GitHub’da varsayılan branch özeldir

  • GitHub’ın “varsayılan branch”i vardır ve bu branch özel bir rol oynar.

GN⁺ görüşü

Bu yazıdaki en önemli nokta, insanların Git branch’lerine dair sezgisel anlayışı ile Git’in gerçekte nasıl çalıştığı arasındaki farkı kavramak. Yazı, özellikle başlangıç seviyesindeki yazılım mühendislerinin Git branch kavramını daha iyi anlamasına ve daha etkili kullanmasına yardımcı olacaktır. Git branch’lerine dair sezgisel modelin gerçek iş akışıyla nasıl örtüştüğünü ve Git’in branch’ler arasındaki ilişkileri neden takip etmediğini görmek ilgi çekici ve öğretici.

1 yorum

 
GN⁺ 2023-11-24
Hacker News görüşü
  • Branch, commit'i işaret eden bir pointer'dır ve her yeni commit oluşturulduğunda bu pointer güncellenir. Branch, tag gibi dolaşan bir isim olarak görülebilir. Commit'in kendisi parent commit'i işaret ettiği için branch, adlandırılmış bir giriş noktasına sahip ilişkili commit'ler zinciridir. Branch silindiğinde artık adlandırılmış bir etiket kalmaz ve geriye yalnızca ilişkili commit'ler zinciri kalır.
  • Commit soy ağacını 'ileri' değil 'geri'yi işaret eden pointer'lar olarak düşünmek anlamayı kolaylaştırır. Branch bir commit ID'si olduğundan, parent link'lerini geriye doğru takip ederek o branch'in tüm geçmişi bulunabilir. 'Branch point', iki commit zincirinin buluştuğu noktadır; merge commit ise özeldir, çünkü iki geçmişin birleştirildiğini gösterir.
  • Kişisel projelerde git reset --hard ve git stash ile değişiklikleri ve branch pointer'larını manipüle ettiğimi gören arkadaşlarım bazen sinirleniyor. Hatalı bir merge'ü geri almak için git reset --hard <merge öncesi son commit> kullanıyorum; yerel branch'teki küçük düzeltmeleri main branch'e uygulamak içinse git stash kullandıktan sonra main branch'e checkout edip git stash apply çalıştırıyorum.
  • Git'te 'main özeldir' diye bir kavram yoktur, ancak GitLab gibi araçlar hataları azaltmak için korumalı branch özelliği sunabilir. 'Parent' ve 'child' branch kavramı aslında ilginç olabilir ve uzun süreli destek branch'leri için birden fazla 'parent' branch'i desteklemek gerekebilir.
  • Merge, rebase ve pull request yaparken diğer branch'i açıkça belirtmeniz gerekir. Çünkü Git, kullanıcının hangi branch'i temel aldığını bilemez. Bazen bir feature branch'i başka bir feature branch'e merge etmek isteyebilirsiniz; bu yüzden hangi branch'in hangisine merge edileceğini net biçimde belirtmek gerekir.
  • İnsanların sahip olduğu sezgi teknik olarak kısmen yanlış olsa bile, o sezgiye sahip olmalarının geçerli nedenleri vardır.
  • git add ve git commit kullanımını bilenlere yönelik dinamik bir eğitim var. Bu eğitim, branch'leri görselleştirerek okumanıza ve anlamanıza yardımcı oluyor.
  • Git komutlarını çalıştırırken 'her zaman' mevcut branch'i değiştirdiğinizi hatırlarsanız, Git söz dizimini 'kolayca' anlayabilirsiniz. Örneğin git merge my-branch, my-branch'i mevcut branch'e merge eder; git rebase my-branch ise mevcut branch'i my-branch'in üzerine rebase eder.
  • Branch'in (head) o branch'in başladığı taban commit'i işaret eden bir 'kuyruğu' olsa iyi olurdu. Branch sık sık rebase edildiği için bazen nereden başladığını düşünmek gerekir. Git, taban commit'in maine ait olduğunu söylese daha kullanışlı olurdu.
  • Mailing list'e 'patch' gönderirken taban commit'i isteğe bağlı olarak ekleyebilirsiniz. Bunun nedeni, değişikliklerin en son sürüme mi, ana geliştirme branch'ine mi yoksa entegrasyon branch'ine mi dayandığının her zaman net olmamasıdır. git range-diff kullanırken de tabanı akılda tutmak gerekir. Bu araç, main..previous ve main..current gibi iki aralığı karşılaştırır.
  • Branch'lere dair kişisel görüşlerimi yeniden okuyunca unuttuğum birkaç şeyi tekrar öğrenmiş oldum.