6 puan yazan GN⁺ 2023-11-03 | 1 yorum | WhatsApp'ta paylaş
  • Git, uzun süre kullanılsa bile kafa karıştıran çok sayıda yinelenen ve yeniden kullanılan terim içerir; bu yüzden yalnızca komutları ezberlemek gerçek davranışı öngörmek için yeterli değildir
  • HEAD, heads, detached HEAD, ours/theirs, ../... gibi aynı kelime ve semboller, bağlama göre farklı anlamlara dönüşür
  • index, staged, cached ifadelerinin hepsi .git/index ile bağlantılıdır; ancak reset, revert, restore benzer isimlerine rağmen commit geçmişi, çalışma ağacı ve branch işaretçileri üzerinde farklı etkiler yaratır
  • main branch'inin bir remote'u takip etmesi ile origin/main gibi bir remote-tracking branch aynı şey değildir ve checkout branch değiştirme ile dosya geri yüklemeyi tek bir komutta bir araya getirir
  • Git'i anlamak için tek tek komutlardan çok, branch, reference, commit, index ve remote izleme durumunun nasıl birlikte çalıştığını anlatan iç modele bakmak gerekir

HEAD, branch'ler ve detached HEAD

  • Git'te heads branch'leri ifade eder ve dahili olarak branch'ler .git/refs/heads dizininde saklanır
    • Resmî Git sözlüğü branch'i onun üzerindeki tüm commit'ler, head'i ise en son commit olarak ayırır; ancak bunlar aynı şeyi görmenin iki farklı yolu olarak düşünülebilir
  • HEAD, mevcut branch'i işaret eder ve .git/HEAD içinde saklanır
    • head bir branch'tir, HEAD ise mevcut branch'tir” ifadesi Git terminolojisindeki karışıklığı tek başına iyi gösterir
  • detached HEAD state, HEAD'in bir branch yerine doğrudan bir commit ID'yi işaret ettiği durumdur
    • Bir tag checkout edildiğinde, tag bir branch olmadığı için detached HEAD durumuna girilebilir
    • Bu durumda git pull çalışmaz ve git push da özel bir yöntem kullanılmadıkça çalışmaz
    • git commit, git merge, git rebase, git cherry-pick yapılabilir; ancak yeni commit'ler herhangi bir branch'e bağlı olmayacağı için sonradan bulunmaları zorlaşabilir
    • Yeni bir branch oluşturarak veya mevcut bir branch'e geçerek detached HEAD durumundan çıkılabilir

merge ve rebase'de değişen ours ve theirs

  • Çakışma çözümünde git checkout --ours file.txt, dosyanın “ours” tarafını seçer; ancak merge ve rebase'in referans noktaları birbirinden farklıdır
  • merge'de mevcut branch ours, birleştirilmekte olan branch ise theirs olur
    • Örneğin git checkout merge-into-ours sonrasında git merge from-theirs çalıştırılırsa mevcut branch ours olur
  • rebase'de mevcut branch theirs, rebase hedefi olan branch ise ours olur
    • Örneğin git checkout theirs sonrasında git rebase ours çalıştırılırsa hedef branch ours olur
  • Bu fark, git rebase main komutunun dahili olarak mevcut branch'in commit'lerini main branch'inin bir kopyası üzerine tekrar tekrar merge etme biçimiyle ilişkilidir
  • ourstheirs, ours ve theirs terimlerini kısaca açıklar
    • VSCode'daki “current change” ve “incoming change” ifadeleri de aynı nedenle kafa karıştırıcı olabilir

Remote durum mesajları ve fast-forward

  • Your branch is up to date with 'origin/main' ifadesi, mevcut main'in remote'daki en güncel durum olduğu anlamına gelmez
    • Bunun anlamı, son git fetch veya git pull anındaki origin/main ile yerel branch'in aynı olduğudur
    • Son fetch 5 gün önce yapıldıysa, aslında “5 gün önceki duruma göre” günceldir
  • Git, son fetch zamanına ilişkin bilgiyi reflog içinde saklar; ancak durum mesajında “son fetch'e göre” zamanı göstermez
  • can be fast-forwarded, remote branch'in yerel branch'in ilerisinde olduğunu ve yerelde ayrı commit olmadığı için yalnızca işaretçinin ileri taşınabileceğini ifade eder
    • Örneğin main A-B-C, origin/main ise A-B-C-D-E ise, git pull sonrasında ikisi de A-B-C-D-E olur
    • Bu durumda merge çakışması yaşanmaz
  • fast-forward mümkün değilse iki branch birbirinden ayrılmıştır
    • Örneğin main üzerinde origin/main'de olmayan bir X commit'i varsa ve origin/main üzerinde de main'de olmayan D ve E varsa fast-forward mümkün değildir
    • Bu durumda Git, iki branch'in diverged durumda olduğunu ve her birinde farklı sayıda commit bulunduğunu belirtir

Commit seçme sözdizimi: ^, ~, .., ...

  • HEAD^ ve HEAD~ ikisi de 1 önceki commit'i işaret eder
    • HEAD^^^, HEAD~~~, HEAD~3 ifadelerinin hepsi 3 commit önceyi gösterir
  • merge commit gibi birden çok ebeveyni olan commit'lerde HEAD^2, HEAD^3 farklı anlamlara gelir
    • HEAD^ birinci ebeveyndir
    • HEAD^2 ikinci ebeveyndir
    • HEAD^3 üçüncü ebeveyndir
    • HEAD~3, ebeveynin ebeveyninin ebeveyni anlamına geldiği için HEAD^3 ile aynı değildir
  • git log main..test ve git log main...test de birbirinden farklı çalışır
    • main..test, yalnızca test'te bulunan commit'leri gösterir
    • test..main, yalnızca main'de bulunan commit'leri gösterir
    • main...test, iki tarafta da yalnızca kendine özgü olan commit'leri birlikte gösterir
  • git diff içinde .. ve ..., git log'dakinden farklı yorumlanır
    • git diff test..main, test tarafındaki ve main tarafındaki değişikliklerin tamamını içerecek şekilde karşılaştırır
    • git diff test...main, ortak atayı main tarafının ucu ile karşılaştırır ve yalnızca tek taraflı diff gösterir
  • Nokta gösterimindeki karışıklık pain in dots içinde de ayrıca ele alınır

reference, refspec, tree-ish

  • Git'te reference birden fazla anlamda kullanılır
    • main, v0.2 gibi branch ve tag'ler
    • Mevcut branch'i işaret eden HEAD
    • HEAD^^^ gibi commit ID olarak çözümlenen ifadeler
  • Git belgeleri HEAD^^^ gibi ifadeleri teknik olarak “revision parameters” diye adlandırır; ancak günlük kullanımda bunlar da reference gibi ele alınabilir
  • symbolic reference, HEAD örneğinde olduğu gibi başka bir referansı işaret eden referanstır
    • HEAD, Git'in temel komutlarının davranışını güçlü biçimde etkileyen merkezi bir kavramdır
  • .git/config içindeki remote yapılandırmasında refspec bulunur
    • Örneğin: +refs/heads/main:refs/remotes/origin/main
    • Çoğu durumda varsayılan git clone veya git remote add tarafından oluşturulan değer olduğu gibi kullanılır
  • tree-ish, git checkout THING . içindeki THING yerine gelebilecek nesneyi ifade eder
    • commit ID
    • main, HEAD^^, v0.3.2 gibi commit referansları
    • main:./docs gibi bir commit içindeki alt dizin
    • Pratikte bunu çoğu zaman “bir commit veya commit referansı” olarak anlamak yeterlidir

index, staged, cached

  • index, staged, cached ifadelerinin hepsi .git/index ile ilgilidir
    • .git/index, değişiklikler git add ile stage edildiğinde kullanılan dosyadır
  • Aynı şeyi ifade eden birden çok terim farklı komutlara dağılmıştır
    • git diff --cached
    • git rm --cached
    • git diff --staged
    • .git/index
  • Ancak --index ve --cached bayrakları her zaman aynı anlama gelmez
    • Git baş bakımcısı Junio Hamano'nun yazısı ayrıntılı farkları açıklar
  • index, performans gerekçeleriyle untracked files'ı da listeler; fakat genel olarak staging area'nın untracked files içerdiği düşünülmez

reset, revert, restore

  • reset, revert, restore benzer kelimeler olsa da Git'te etkiledikleri şeyler farklıdır
  • git revert COMMIT, mevcut branch üzerinde COMMIT'in tersini yapan yeni bir commit oluşturur
    • COMMIT 3 satır eklediyse yeni commit bu 3 satırı siler
  • git reset --hard COMMIT, mevcut branch'i zorla COMMIT anındaki duruma geri döndürür
    • COMMIT sonrasındaki yeni değişiklikleri sildiği için son derece tehlikeli bir işlemdir
  • git restore --source=COMMIT PATH, PATH altındaki dosyaları COMMIT zamanındaki hâline döndürür
    • Başka dosyaları veya commit geçmişini değiştirmez
  • git reset --hard ile git restore . tek başına kullanıldığında çoğu zaman benzer davranır; ancak git reset --hard COMMIT ile git restore --source COMMIT . tamamen farklı çalışır

track, remote-tracking branch, untracked files

  • Git, track kelimesini üç farklı şekilde kullanır
    • git status içindeki Untracked files:, Git tarafından izlenmeyen ve herhangi bir commit'e dahil edilmeyen dosyaları ifade eder
    • origin/main gibi remote-tracking branch, son git pull veya git fetch anında remote origin üzerindeki main'in işaret ettiği commit ID'yi tutan yerel referanstır
    • “branch foo set up to track remote branch bar from origin” ifadesindeki gibi, yerel bir branch bir remote branch'i takip edecek şekilde yapılandırılabilir
  • main'in remote'u takip eden bir branch olması ile origin/main'in bir remote-tracking branch olması aynı şey değildir
  • main gerçek bir branch olduğu için üzerinde commit oluşturulabilir ve merge yapılabilir
    • .git/config içinde remote main'i takip edecek şekilde ayarlanırsa git pull ve git push daha rahat kullanılabilir
  • origin/main, adına “remote-tracking branch” dense de normal bir branch değildir
    • Üzerine doğrudan commit yapılamaz
    • Yalnızca git pull veya git fetch ile remote'daki en güncel main durumu alındığında güncellenir

checkout, reflog, merge/rebase/cherry-pick

  • git checkout, birbirinden farklı iki işi tek komutta toplar
    • git checkout BRANCH, branch değiştirir
    • git checkout file.txt, file.txt üzerindeki unstaged değişiklikleri atar
  • Git bu karışıklığı azaltmak için işlevleri git switch ve git restore olarak ayırdı; ancak eski checkout hâlâ kullanılabilir
  • reflog, reference log anlamına gelir ve bir reference'ın geçmişte neyi işaret ettiğinin kaydıdır
    • reference; branch, tag ve HEAD'i kapsayan geniş bir terimdir
    • reflog, önemli bir branch'i yanlışlıkla silmek gibi çok kötü Git durumlarından çıkmaya yardımcı olabilir
  • merge, rebase ve cherry-pick commit'leri farklı şekillerde birleştirir
    • merge, iki branch'i birleştiren tek bir yeni commit oluşturur
    • rebase, mevcut branch'in commit'lerini hedef branch'in üzerine tek tek kopyalar
    • cherry-pick, rebase'e benzer; ancak sözdizimi farklıdır ve commit'i mevcut branch'e kopyalar
  • git rebase --onto main otherbranch mybranch, mybranch üzerindeki commit'lerin yalnızca bir kısmını main üzerine taşımak için kullanılabilir
    • Örnek yapıda yalnızca F ve G'yi main üzerine rebase etmek istendiğinde kullanılabilir
    • Üç branch adı içerdiği için hatırlaması zor bir sözdizimidir

commit ve diğer kafa karıştırıcı terimler

  • commit, Git'te hem fiil hem isim olarak kullanılır
    • Fiil: “sık commit yap”
    • İsim: main üzerindeki en son commit
  • Bir Git commit'i üç farklı şekilde görülebilir
    • Tüm dosyaların mevcut durumunun anlık görüntüsü
    • Ebeveyn commit'e göre diff
    • Ondan önceki tüm commit'lerin geçmişi
  • Komutlar commit'i farklı biçimlerde ele alır
    • git show, commit'i diff gibi ele alır
    • git log, commit'i history gibi ele alır
    • git restore, commit'i snapshot gibi ele alır
  • blob, tree, origin, upstream, downstream, fetch ile pull arasındaki ilişki, stash, worktree, subtree, submodule da kafa karıştırıcı Git terimleri arasındadır
  • GitHub terminolojisinde “pull request”, “squash and merge”, “rebase and merge” sık verilen kafa karıştırıcı örneklerdendir

Tekrarlanan karışıklığın üç ekseni

  • Özellikle kafa karıştırıcı Git terimleri üç başlıkta özetlenebilir
    • head bir branch'tir, HEAD ise mevcut branch'tir
    • “remote tracking branch” ile “bir remote'u takip eden branch” birbirinden farklıdır
    • index, staged, cached ifadelerinin hepsi aynı şeyi işaret eder
  • 2012 tarihli the most confusing git terminology yazısı da Git terminolojisinin CVS ve Subversion terimleriyle nasıl bağlantı kurduğunu ele alır
  • Git terminolojisindeki karışıklık bazı özel özelliklerle sınırlı değildir; temel işlevlerin geneline tekrar tekrar yayılır
  • Özellikle branch'lerden söz ederken “tracking” birden çok anlamda kullanıldığı için ilk bakışta aradaki farkı görmek zordur
  • Bazı açıklamaların Git'in az kullanılan köşelerine değindiği ve bu yüzden küçük hatalar içerebileceği notu da düşülür

1 yorum

 
GN⁺ 2023-11-03
Hacker News görüşleri
  • Bu terimlerin çoğunu ezberlemek zordu, ama her şeyin yerine oturmasını sağlayan kilit nokta, Git’teki pek çok şeyin sonuçta commit’i gösteren pointer’lar olmasıydı
    Branch adı, HEAD, etiketlerin hepsi birer pointer’dır. HEAD, şu anda baktığınız commit’i gösterir; my-feature gibi bir branch adı da o branch’in en son commit’ini gösterir. main üzerinde git checkout -b my-feature yaptığınızda main, my-feature ve HEAD hep birlikte main’in en son commit’ini göstermeye başlar
    my-branch üzerinde her commit attığınızda HEAD ve my-branch yeni commit’i gösterecek şekilde ilerler. detached HEAD, HEAD’in gösterdiği commit’i hiçbir branch’in göstermediği durum demektir. Etiket ile branch arasındaki fark ise etiketin belirli bir commit’i gösterip hareket etmemesidir
    Bir diğer kafa karıştırıcı nokta da, birçok komutun tutarsız görünmesinin nedeninin Git’in varsayılan argümanlar kabul etmesi olmasıydı. git checkout file.txt, git checkout HEAD -- file.txt ile aynıdır; my-branch üzerindeyken git rebase main de git rebase main my-branch ile aynıdır. Yalnız ikinci biçim başka branch’lerdeyken de çalıştırılabilir
    Son olarak, her şey birbirine girdiğinde sizi ne kadar garip bir durum olursa olsun oradan çıkarabilecek komut git reflog’dur. HEAD’in işaret ettiği tüm commit’leri gösterir. Yine de Git’in bu karmaşayı kabul edip daha az şaşırtıcı ve daha basit arayüzlü komutlar üretmeye çalışması sevindirici
    • Git’in bu kavram için kullandığı adla söylersek, “commit pointer” aslında refs’tir. reflog adı da buradan gelir
      Ayrıca Git kullanan birçok kişinin pek aklına gelmeyen nokta şu: getirdiğiniz uzak branch veya etiket ref’leri de sonuçta birer ref’tir; yani ref adının kullanılabildiği her yerde onlara da başvurabilirsiniz
      Örneğin “bu branch’te ne varsa umurumda değil, fast-forward da yapma, merge de yapma, rebase de yapma, sadece yerel branch’i uzak içeriğiyle ezip geç” demek istiyorsanız şöyle yapabilirsiniz: git checkout foo, git reset --hard origin/foo
    • Teknik olarak HEAD pointer’ı commit’i doğrudan göstermez; normalde my-branch gibi bir branch pointer’ını gösterir, o branch pointer’ı da commit’i gösterir. detached HEAD durumu bunun istisnasıdır
      my-branch üzerinde commit attığınızda HEAD ve my-branch ikisi birden yeni commit’e taşınmaz; HEAD, my-branch pointer’ını göstermeye devam eder, yalnızca my-branch yeni commit’i gösterecek şekilde ilerler. Tabii HEAD’den my-branch üzerinden commit’e giderseniz yeni commit’e ulaşırsınız
      detached HEAD, HEAD’in branch pointer’ı yerine commit’i doğrudan gösterdiği durumdur. detached HEAD durumunda da HEAD ile branch pointer’ı aynı en son commit’i birlikte gösterebilir. git log --decorate çıktısında normalde görülen (HEAD -> my-branch) yerine en son commit üzerinde (HEAD, my-branch) gibi görünür
    • Bu açıklama güzel. Ama bazen karşılaşılan daha kafa karıştırıcı nokta, etiketlerin iki tür olmasıdır. Etiketlerin çoğu, söylendiği gibi, commit nesnesini gösteren hafif etiketlerdir ve bundan fazlası değildir
      Buna karşılık açıklamalı etiketler mesaj, zaman damgası, SHA vb. içerebilir. Bunlar gerçek Git nesneleridir ve commit nesnelerine oldukça benzer davranırlar, ama genelde yine başka bir Git nesnesine, çoğunlukla bir commit’e referans verirler
    • Benim gibi gereğinden fazla temkinliyseniz, bol çakışmalı zahmetli bir sürece veya birden fazla hamleye başlamadan önce git rev-parse HEAD çalıştırıp çıkan dizgeyi güvenli bir yere kopyalamak da iyi olabilir
      Son durumda, doğru olduğundan emin olduğunuz hâli tam olarak işaretlediğiniz hissi verir. Genelde kaosun birkaç adım içine girdiğiniz bir noktaya değil, son iyi duruma geri dönebilirsiniz. Tabii git gc veya git filter-branch gibi şeyleri dikkatsizce kullanmadığınız varsayımıyla
    • Bu açıklama, Git’in içindeki ağaç yapısının her şeyi yönettiğini de iyi gösteriyor
      Şaka gibi ama aslında değil: Git kullanmak için gerçekten bilgisayar bilimi diploması gerekiyor denmesi bütünüyle yanlış sayılmaz. Git’in varsayılan argümanları çok tutarsız bir kullanım deneyimi yaratıyor, buna katılıyorum
      git checkout ., git reset --hard/soft, git cleanup hepsi aşırı benzer görünüyor ama gerçekte çok farklılar. Yine de Perforce veya SVN’ye kıyasla hâlâ Git’i tercih ederim. Eskiden Mercurial’ı biraz daha çok severdim ama bugün de öyle mi bilmiyorum
      git reflog kraldır ve gerçeği gösterir
  • Git, bir kez daha temelsiz bir teknoloji modasının yardımıyla sürüm kontrol savaşlarını “kazanalı” yaklaşık 10 yıl oldu, ama hâlâ önemsiz olması gereken işlerde zorluk çıkarıyor
    Linus Torvalds’ın, insanların üstüne daha kullanıcı dostu bir katman koymadan Git’i doğrudan kullanmaya başlamasına şaşırdığını yazdığı bir şeyi okuduğumu hatırlıyorum. Sektör biraz öz eleştiri yapabilseydi Git’i seçmenin hata olduğunu kabul eder ve başka bir sürüm kontrol sistemine geçerdi. Sadece metin saklayan bir araç için bu kadar zaman harcamaya değmez
    • Git’i bir metin saklama aracı olarak görmüyorum. Birden fazla kişinin aynı “metin” üzerinde yaptığı değişiklikleri oldukça hassas ve güvenilir biçimde koordine ederken kimsenin ilerlemesini engellemeyen bir araç olarak görüyorum. Bir kez Word ile deneyin, fark çok büyük
      Elbette daha iyi olabilir. Yine de Git’in aldığı nefret bana hep şaşırtıcı geliyor. Git müthiş bir araç ve Word veya Google Docs gibi geliştirici olmayanlar için yapılmış araçların çok ilerisinde
      Belki de Subversion’ın kral olduğu zamanı hatırlayacak kadar yaşlı olduğum içindir
    • Kesinlikle katılıyorum
      Her hafta iş arkadaşlarımın Git yüzünden kafasının karıştığını görüyorum, internette yardım isteyen gönderiler görüyorum, burada olduğu gibi basit olması gereken şeyleri yeniden açıklamaya çalışan başka yazılar görüyorum
      Kod yazarken SVN, TFVC, Perforce vb. sistemlerde kendi yarattığı karmaşayı geri almak için saatlerini harcayan birini hatırlamıyorum
      Araçlar hayatı kolaylaştırmak için vardır. Bunu yapamıyorsa zaman ayırmaya değmez
    • 2013’te bile Git’in kazanacağı hiç de net değildi. darcs, Mercurial, svn, hatta cvs kullananlar bile epey fazlaydı; o dönemin araçları da genelde bunların hepsini destekleyen eklentilere sahipti

Keşke hâlâ böyle bir çeşitlilik olsaydı. Git tek kültürü, Git’in yerini almaya çalışan bir şeyin önce Git’i yeniden uygulamak zorunda olması anlamına da geliyor. Bu yüzden ASCII ya da Scroll Lock tuşu gibi, Git’e neredeyse sonsuza kadar bağlı kalıyoruz.

  • Git iyi nedenlerle kazandı ve öncekilerden açıkça daha iyiydi. Bugünlerde jQuery gibi Git’e sövmek moda olabilir ama ortaya çıktığında net bir gelişmeydi.
  • Benzer bir sorun, neden Git’e kilitlenip kalabileceğimiz hakkında yakın zamanda bir yazı yazdım.
    Asıl endişe, GitHub’ın fazla iyi olması; GitHub, Git’i metin yönetim motorundan ayırıp başka motorlara da izin vermediği sürece Git’e bağlı kalacağız.
    https://trolololo.xyz/github
    https://news.ycombinator.com/item?id=38098109
  • Git terminolojisinde birçok terim, nasıl çalıştığını zaten anladıktan sonra anlamlı geliyor; ama uygulama ayrıntılarını bilmiyorsanız ya da diğer terimlerle yan yana koyunca, neredeyse anlam ifade etmeyen klinik vakalar gibi duruyor.
    Sızdıran soyutlama gibi bir terim.
    • Kısmen doğru, ama bunun bir nedeni de Git’in farklı parçalarının farklı kişiler tarafından yapılıp ayrı ayrı adlandırılması. Linus buna başlangıçta cache diyordu ve bu en bilgisayar bilimi kokan terimdi.
      Sonrasında Junio bunu, dağıtık sürüm kontrol sistemine daha özgü olan index olarak değiştirmiş gibi görünüyor; kullanıcıların çoğu ise buna staging area diyordu. Artık bu terim evrimi, Git’in arayüzünde ve iç yapısında fosil gibi kalmış durumda.
    • Anlamlı değil; bu sadece özensiz adlandırma. İyi isim koymak emek ister ve Git’in ilk geliştiricileri bunu yapmadı.
    • Temel kullanım için işletim sistemi, IDE ve derleyici iç yapısını bilmeniz gerektiğini düşününce, bu fiilen kötü API tasarımı demek.
  • “Your branch is up to date with origin/master” her gün duyduğum en büyük yalan. O yüzden her seferinde doğrudan pull yapıyorum.
    • Teknik olarak doğru. origin/master, origin üzerindeki master değil; en son bilinen origin/masterın işaret ettiği commit demek. Bu değer fetch sırasında güncellenir ve pull bunu otomatik olarak fetch eder.
      ls -l .git/refs/remotes/origin/master çıktısına bakarsanız origin/masterın sistemimdeki bir dosyadan ibaret olduğunu görürsünüz. Ne zaman değiştiğini de görebilirsiniz. Sihirli biçimde güncellenmez.
      git fetch origin yaptığınızda değişiklik varsa zaman damgası ve içerik değişir. Bunu cat .git/refs/remotes/origin/master ile görebilirsiniz.
      Git’in temeli son derece basit; çekirdek veri yapıları ve birkaç işlemi bir gün içinde uygulayabilirsiniz. Bunu bilmek gerçekten değerli. Her nasılsa Git, oldukça basit bir çekirdeğin üstüne çok karmaşık bir kullanıcı arayüzü inşa etmiş.
    • Bu mesaj yalnızca, Git’in açıkça söylenmedikçe internete ya da uzak depoya bağlanıp güncelleme kontrolü yapmadığı anlamına geliyor. Bu özellik başlı başına bence iyi. Sadece mesaj daha açık olabilirdi.
    • Şöyle bir şey olmalıydı: “Your branch is up to date with the local copy of origin/master, last updated on XXXX-XX-XX:XX:XX:XX”
    • Ben yerel master dalını siliyorum. Genelde zaten mastera push edemiyorsunuz ya da her durumda doğrudan master üzerinde çalışmak istemiyorsunuz. O hâlde yerelde değiştirilebilir bir master dalı tutmanın anlamı yok.
      Bu yüzden sadece origin/masterı güncellemek yeterli oluyor ve bunun için fetch kâfi.
    • git fetch && git pull
      3 yıl sonra emekli olup bu bozuk çöplükten elimi eteğimi çekebileceğim günü bekliyorum.
  • Git çıktığından neredeyse beri kullanıyorum ama porcelain kavramını ancak bu hafta öğrendim. git status çıktısını ayrıştıran bir projem var; --porcelain bayrağını ekleyince gerçekten çok yardımcı oldu. Daha kısa ve programların ayrıştırması daha kolay bir çıktı üretiyor.
    Daha kaç komutta makine dostu çıktı olduğunu merak edip git-scm’deki “Git Internals - Plumbing and Porcelain” sayfasına kadar gittim. Kısa özeti şu: Git baştan beri cilalı bir sürüm kontrol sistemi olmaktan çok, sürüm kontrolüyle uğraşan araçlar kümesi olarak yazılmış.
    Git’i ilk dönemlerinden beri kullanan birçok kişi, sürüm kontrol işlerini bu düşük seviye komutlarla yapmayı öğrendi ve bu çalışma şeklini başkalarına da aktardı. Bu, plumbing katmanı. Daha sonra Git daha rafine bir katman oluşturdu ve buna porcelain dendi.
    Hâlâ hangi komutun hangi katmana ait olduğunu tamamen bilmiyorum ama son birkaç yılda önerilen yeni çalışma akışlarını anlamama yardımcı oldu. Kendi çalışma akışımı değiştirirken de daha iyi karar vermemi sağlıyor.
    https://git-scm.com/book/en/v2/Git-Internals-Plumbing-and-Po...
    • Bu, Linus’un iç yapı olan plumbingten memnun ama UI olan porcelain’in elden geçirilmesi gerektiğini düşündüğünün açık bir işareti. Başlangıçta porcelain tamamen plumbing’i çağıran betiklerden ibaretti.
      Ne yazık ki daha hızlı olsun diye bu UI’yi hardcode ettiler ama iyileştirmediler.
  • Julia’nın yazı üslubu gerçekten çok iyi. Kıdemli geliştiriciler için de çok değerli şeyler yazarken, bu alana yeni giren biri için de sıcak ve dışlayıcı olmayan bir ton koruyor.
  • Sanırım “Git Stockholm sendromu”na yakalandım. Bu terimler bana artık o kadar da kafa karıştırıcı gelmiyor ama bunda, başka sistemleri neredeyse hiç öğrenmeden 2011 civarından beri Git’e derinden bağlı olmamın payı büyük.
    Geriye dönüp bakınca, ilk başta kesinlikle aşırı kafa karıştırıcı gelmiş olmalı; ama havalı görünmek için öyle değilmiş gibi davrandım sanırım.
    • Fossil sürüm kontrol sisteminin CLI’ını gördükten sonra bende Stockholm sendromu olduğunu fark ettim. Fazla sezgiseldi.
    • Git kullanmadan önce cvs ve svn kullandım; svn ile karşılaştırınca Git çok daha kolay anlaşılırdı.
    • Benim kullandığım diğer tek sürüm kontrol sistemi Plastic SCM ve Stockholm sendromu olsun ya da olmasın, Git çok daha iyi.
  • Birlikte bakmaya değer: Git staging area, kelimenin tam anlamıyla herkesin uzlaştığı bir terim.

https://news.ycombinator.com/item?id=28143078
“Your branch is up to date with ‘origin/main’” aslında biraz yanıltıcı. main branch’inin güncel olduğu anlamına gelecek şekilde anlaşılabilir, ama gerçekte öyle değil
Yine de buna fazla “teknik olarak konuşursak” yüklemeye gerek yok. İki general problemi burada geçerli değil mi? Gerçekten titiz davranırsanız tam bu anda “güncel” olup olmadığını bilemezsiniz. status öncesinde fetch yapsanız da aynı şey geçerli
O hâlde makul beklenti nedir? Bilgisayarımdaki nesne veritabanındaki ref’in, en son kontrol ettiğim anda uzaktaki başka bir nesne veritabanındaki ref ile aynı olduğunu bilmek kadar bir şey
Basit bir status çağrısı ağ üzerinden fetch yapamaz ya da kullandığınız aracın temel çalışma ilkesini her seferinde size hatırlatamaz. Benim görüşüm bu. Ama şaşırtıcı şekilde StackOverflow yanıtındaki birçok yorum tam olarak bu ikisinin gerekli olduğunu düşünüyor
“is up to date with the origin’s main as of your last fetch 5 days ago” gibi bir ifade daha makul olurdu. Çünkü sadece en son fetch işleminin ne kadar önce yapıldığını söyler
[1] https://stackoverflow.com/questions/27828404/why-does-git-st...
Bir şey daha: ORIG_HEAD’in, FETCH_HEAD gibi “origin’in head’i” ile ilgili olduğunu sanıyordum. Ama değilmiş. Bu “pseudoref”, rebase gibi daha karmaşık yeniden yazımlardan önce bir kayıt noktası olarak kullanılıyor gibi görünüyor ve reflog ortaya çıkmadan önce uygulanmış. Muhtemelen “original head” anlamına geliyor

  • Git’e epey sıcak bakıyorum ama o mesajın ifadesi konusunda yazara katılıyorum. Yalnız önerdiği alternatife katılmıyorum
    “Your branch is up to date with ‘origin/main’” teknik olarak doğru, ama up to date ifadesi üstünkörü okunduğunda iki şeyi ima ediyor. main, origin/main ile aynı ve origin/main de güncel; yani komut sırasında güncellenmiş ya da otomatik olarak güncel tutuluyormuş ve yakın zamanda senkronizasyon başarılı olmuş gibi bir his veriyor
    Bu, bir CPU çevrimi boyunca doğru olması gereken makine tarafından okunacak bir sinyal değil; kullanıcıya gösterilen bir durum mesajı. Ağ teorisine kadar gitmeden de bu yorum makul
    “Up to date”, mekânsal olmaktan çok zamansal olarak yetişmiş olma anlamına daha yakın. Lokal branch konumu, “bu branch neyi işaret ediyor” şeklindeki mekâna daha yakın; uzak ref durumu ise “uzak ref’i en son ne zaman güncelledim” şeklindeki zamana daha yakın. Elbette bu çok öznel ve ikisi de her iki anlamı da taşıyabilir
    Daha iyi ifadeler şunlar olabilir: “Your branch matches origin/main”, “Your branch’s head is the same as origin/main”, “Your branch is pointing to the same commit as origin/main”. Bunlar açıklık ile lafı uzatma arasında bir uzlaşma. Buna, yazarın önerdiği gibi parantez içinde “remote ref last updated 5 days ago” da eklenebilir
  • status çağrısının ağ üzerinden fetch yapmasının sinir bozucu olduğu görüşüne katılmıyorum. Bence ağ işlemleri açıkça belirtilmiş olmalı, örtük olmamalı. git status çalıştırdığımda dosya sistemindeki depomun durumunu bilmek istiyorum
    Başka bir remote’da neler olduğunu öğrenmek istiyorsam kendim fetch yapar, sonra karşılaştırırım
  • Beklenen şey, status komutunun başlatıldığı an itibarıyla en güncel bilgiyi almak. Bilgi terminale yazdırılırken bir yarış durumu olabilir, ama bu çok küçük bir zaman penceresi
    Genel olarak bu, fetch istemek anlamına geliyor. İki general problemi yalnızca remote tarafı için geçerli. Remote, istemcinin veriyi aldığını teyit etmezse bir süre yeniden göndermeyi sürdürebilir. Bu istemcinin sorunu değil
    İstemci sunucudan veriyi alamazsa doğru davranış muhtemelen beklemek, zaman aşımından sonra da hata vermektir; şu anda fetch muhtemelen zaten bunu yapıyordur
  • Git öğrenirken en değerli aşama doğru zihinsel modele sahip olmaktır. Her şey bir grafik
    Bu araç sık sık paylaşılıyor ve burada da çok uygun. Git’in iç modelini ve çeşitli komutların etkisini görselleştiriyor
    https://learngitbranching.js.org/
    Bu araçla 10 dakikada öğrendiklerim, ondan önceki yaklaşık 10 yıllık Git deneyimimden daha fazlaydı. Kesinlikle tavsiye ederim
  • Daha fazlasını eklemek istemem ama Bitbucket ekibinin pull request terimini ortaya atması da bir sorun
    “pull”, uzak değişiklikleri lokal depoya birleştirme eylemi. Kullanıcının gerçekten istediği şey, sunucunun kendi uzak değişikliklerini bir branch’e birleştirmesi. GitLab’daki “merge request” daha doğru bir ifade
    Birinin fetch yaptıktan sonra commit’lerin kaybolduğunu gördüğüne şahit oldum. Depo zaman açısından geriye gittiği için gizlenmişlerdi. Git bu tür ayrıntıları status içinde saklıyor; git-prompt ya da powerline-shell kullanmıyorsanız karanlıkta çalışıyor gibisiniz
    • git-request-pull(1) içinde kalan özgün fikir, hepimizin kernel.org/git ya da redhat.com/git gibi yerlerde kendi Git depolarımızı barındırdığı ve birbirimizden farklı sunucularda, organizasyonlarda ve alan adlarında bulunan depolardan pull yapmalarını e-postayla talep ettiğimiz dönemden geliyor
      GitHub, Git’in request-pull komutundan ilham aldı, ama bunu bir GitHub deposundan başka bir GitHub deposuna birleştirme şeklinde yeniden yorumladı
    • Sunucu açısından bakıldığında kullanıcı remote, sunucu ise lokal taraftır. Dolayısıyla kullanıcı sunucudan kendi tarafına pull yapmasını istemiş olur
      En azından ben hep böyle okudum
    • Git kitabı bu terimin kökenini ve neden mantıklı olduğunu açıklıyor
      Özetle, bu sunucuya yapılan bir istek değil, başka bir kişiye yapılan bir istek. Projeye katkı sunmak istediğiniz değişiklikleri incelemesi için karşı taraftan benim branch’imi pull etmesini istiyorsunuz

[0] https://git-scm.com/book/en/v2/Distributed-Git-Contributing-...

  • “pull request” terimini GitHub yaygınlaştırdı ve bence iyi bir terim. Gerçekte başka bir depodan mı pull yapıldığı, yoksa aynı depo içinde bir “merge request” mi yapıldığı ayrımı pek de ilgi çekici değil. “merge request” daha çok GitLab’e özgü bir terim gibi geliyor
  • Bunu anlamak benim için her zaman en zoru olmuştu. Doğal olarak bunun pull request değil, push request ya da merge request olması gerekmez mi diye düşünüyorum