Ders 11 / 15
Uzak Depo Tanımlama
Uzak depo tanımı bir adı bir adrese bağlar ve tarihçeye dokunmaz; üç kopya sırasıyla 5, 10 ve 15 işleme taşır ve 4, 5, 5 soru yanıtlar, iki tanım sonrası yerel kopya 5 işleme ve 4 soruda kalır.
İçindekiler
Önceki ders dal stratejilerini kurdu: uzun ömürlü dal, kısa ömürlü dal ve seçilen stratejinin tarihçeye ne bıraktığı. O tartışmanın tamamı tek bir kopyanın içinde geçti. Dallar aynı depoda açıldı, aynı depoda birleşti; ölçtüğümüz tarihçe tek bir yerde duruyordu ve o yerde duran şey işin tamamıydı.
Dağıtık bir sürüm kontrolünde bu varsayım ayakta durmaz. Tarihçe tek bir yerde değil, birden çok kopyada yaşar; kopyalar birbirinden habersiz ilerler ve hiçbiri kendiliğinden ötekinin işlemelerini bilmez. Bu dersin sorusu, kopyaların nasıl senkronlandığı değil — o sonraki dersin konusu. Bu dersin sorusu daha önce gelir: bir kopya öbürünü nasıl adlandırır, ve adlandırma tarihçeye ne ekler?
Kopya ve Uzak Depo
Sürüm Kontrolüne Giriş kursundaki “Merkezî ve Dağıtık Modeller” dersi ayrımı kurmuştu: dağıtık bir modelde her kopya tam bir depodur. Kopyanın kendi çalışma alanı, kendi hazırlık alanı, kendi dalları ve kendi tarihçesi vardır. Hiçbir kopya yapısı gereği ötekinden üstün değildir; “merkez” bir uzlaşımdır, bir araç özelliği değil.
Uzak depo (remote), bir depoda tanımlı olan ve başka bir kopyanın adresine bağlanmış addır. Bu ayrımı baştan koymak gerekir: karşı taraftaki kopya uzak depo değildir; uzak depo, o kopyaya bu depoda verilen yerel addır. Aynı kopya iki ayrı depoda iki ayrı adla tanımlanabilir ve bu bir tutarsızlık değildir, çünkü ad yereldir.
Tanımın nerede durduğu bu yüzden önemlidir. Uzak depo tanımı deponun yapılandırma dosyasına yazılır, tarihçeye değil. Doğrudan sonucu şudur: bir kopyayı alan başkası senin uzak depo adlarını almaz — kendi tanımlarını kendi yapar. Tanım paylaşılan bir veri değil, kişisel bir yönlendirme tablosudur.
Tanımlama Ne Yapar
Tanım, alt komutlarla yönetilir. Aşağıdaki blok örnek dökümtür; çalıştırılmamıştır ve adresler kurgudur.
# öğretilen komutlar — örnek döküm, çalıştırılmamıştır git remote add koken ornek.test:takim/olcum-aglari.git git remote add yukari https://ornek.test/kaynak/olcum-aglari.git git remote -v koken ornek.test:takim/olcum-aglari.git (fetch) koken ornek.test:takim/olcum-aglari.git (push) yukari https://ornek.test/kaynak/olcum-aglari.git (fetch) yukari https://ornek.test/kaynak/olcum-aglari.git (push)
-v seçeneği her ad için iki satır verir, çünkü getirme ve itme adresleri ayrı ayarlanabilir.
Yalnız okunacak bir kopyanın itme adresi bilerek geçersiz bırakılabilir; o zaman ada yapılan
bir itme denemesi ağa çıkmadan durur.
Kalan alt komutlar aynı tabloyu düzenler: git remote rename adı değiştirir,
git remote set-url adrese bağlı adresi değiştirir, git remote remove tanımı ve ona bağlı
uzak izleme başvurularını siler, git remote show bir adın altındaki dalları listeler.
git remote remove yerel dalları ve işlemeleri silmez; sildiği şey adlar ve o adların altına
yazılmış başvurulardır.
Bir kopyayı ilk kez alırken uzak depo adı elle yazılmaz: klonlama, kaynağa bir varsayılan ad
yazar (origin). Bu dersin ölçümü kopyaların rollerini okunur tutmak için kendi adlarını
kullanıyor: yazma yetkisinin bulunduğu kopyaya koken, yalnız okunan yukarı depoya yukari.
Uzak İzleme Başvuruları
Tanım tek başına bir addır; adın altında ne olduğu ayrı bir başvuru kümesinde tutulur. Yerel
dallar refs/heads altında durur, bir uzak deponun dalları ise refs/remotes/<ad> altında.
İkinci kümedeki başvurulara uzak izleme başvurusu denir.
Uzak izleme başvurusunun kuralı tek cümledir: yerelden yazılmaz. Üzerine işleme yapılmaz, elle ileri alınmaz; yalnız karşı taraftan veri getirildiğinde güncellenir. Bu yüzden uzak izleme başvurusu bir dal değil, karşı tarafın dalının en son görülmüş hâlinin kaydıdır.
# öğretilen komut — örnek döküm, çalıştırılmamıştır git branch -a * olcum remotes/koken/olcum remotes/koken/rapor remotes/yukari/kimlik remotes/yukari/olcum remotes/yukari/rapor
Yıldız yerel dalı işaretler; kalan beş satır iki uzak deponun altındaki başvurulardır. Aynı kısa ad birden çok kez görünüyor ve bu bir kusur değil, ad alanının çalıştığının kanıtıdır.
Ölçümün Varsayımları
- UD1 — Üç kopya aynı kurgudan üretilir:
yerelyalnızolcumdalını,kokenolcumileraporu,yukariüçünü de taşır. Üçü de aynı tümleştirme biçimini — birleştirme işlemesini — kullanır; ölçülen fark biçim değil, taşınan dal kümesidir. - UD2 — Kopyaların ortak dalları ayrışmaz: bir dal iki kopyada da varsa aynı işlemeleri taşır. Ayrışmış kopya sonraki dersin konusudur.
- UD3 — Tanımlama işlemi
uzaklarsözlüğüne bir ad–adres çifti yazar vetarihcelistesine dokunmaz; ölçüm bu iki alanı ayrı ayrı sayar. - UD4 — Adresler kurgudur ve ölçüme girmez; ölçüm adresin biçimine değil, tanımın sayısına bakar.
- UD5 — Altı soru kursun sabitidir ve burada değişmez. Değişen tek şey soruların sorulduğu kopyadır.
- UD6 — Başvuru sayımı yerel dalları ve uzak izleme başvurularını birlikte sayar; kısa ad, başvurunun uzak depo öneki atılmış hâlidir.
Ölçüm
"""Uzak depo tanımlama: ad bir adrese bağlanır, tarihçe taşınmaz. Bölüm 1 - üç kopyanın taşıdığı tarihçe ve yanıtlayabildiği soru. Bölüm 2 - tanımlama işleminin yerel tarihçeye dokunduğu yer. Bölüm 3 - uzak depo adının açtığı ad alanı. """ TOHUM = 20260813 DALLAR = ("olcum", "rapor", "kimlik") DOSYALAR = {"olcum": "olcum.py", "rapor": "rapor.py", "kimlik": "kimlik.py"} KUSURLU = ("rapor", 2) ORTAK_DOSYA = "ayar.py" def uretec(tohum): d = tohum % 2147483646 + 1 def r(n): nonlocal d d = (d * 48271) % 2147483647 return d % n return r def gelisim(): """Gerçek gelişim: üç dal, dörder işleme, biri kusuru getiriyor.""" r, kayit, zaman = uretec(TOHUM), [], 0 for adim in range(1, 5): for dal in DALLAR: zaman += 1 + r(3) dosya = ORTAK_DOSYA if adim == 3 and dal in ("olcum", "rapor") else DOSYALAR[dal] kayit.append({"dal": dal, "sira": adim, "dosya": dosya, "kusurlu": (dal, adim) == KUSURLU, "zaman": zaman}) return kayit def tarihce(kayit, dallar): """Verilen dalları birleştirme işlemesiyle almış bir kopyanın tarihçesi.""" t = [] for dal in dallar: for k in [x for x in kayit if x["dal"] == dal]: t.append({**k, "dal_kaydi": dal, "zaman_korundu": True}) t.append({"dal": dal, "sira": 0, "dosya": None, "kusurlu": False, "zaman": max(x["zaman"] for x in kayit if x["dal"] == dal), "dal_kaydi": dal, "birlesme": True, "zaman_korundu": True}) return t def s1(t): return all(x.get("dal_kaydi") for x in t if not x.get("birlesme")) def s2(t): k = [x for x in t if x["kusurlu"]] return len(k) == 1 and not k[0].get("sikisik") def s3(t): return all(x.get("zaman_korundu") for x in t) def s4(t): return all(isinstance(x["dosya"], str) or x.get("birlesme") for x in t) def s5(t): yerler = {} for i, x in enumerate(t): if x.get("birlesme"): continue yerler.setdefault(x["dal"], []).append(i) return all(y[-1] - y[0] == len(y) - 1 for y in yerler.values()) def s6(t): return any("secilen" in x for x in t) SORULAR = (("özellik gruplaması", s1), ("kusurun yalıtımı", s2), ("gerçek sıra", s3), ("dosya izi", s4), ("dalın bütünlüğü", s5), ("çakışma kararı", s6)) KOPYALAR = {"yerel": ("olcum",), "koken": ("olcum", "rapor"), "yukari": ("olcum", "rapor", "kimlik")} def tanimla(depo, ad, adres): """Uzak depo tanımlama: ada bir adres bağlanır, tarihçeye dokunulmaz.""" depo["uzaklar"][ad] = adres return depo def olc(d): return len(d["tarihce"]), sum(f(d["tarihce"]) for _, f in SORULAR) kayit = gelisim() print(f"gerçek gelişim {len(kayit)} işleme, {len(DALLAR)} dal; " f"kopya {len(KOPYALAR)}") print() print("kopya dal işleme yanıtlanan yanıtlanamayan") for ad, dallar in KOPYALAR.items(): t = tarihce(kayit, dallar) yok = [soru for soru, f in SORULAR if not f(t)] print(f" {ad:6s} {len(dallar):3d} {len(t):7d} {len(SORULAR) - len(yok):11d}" f" {', '.join(yok)}") print() depo = {"tarihce": tarihce(kayit, KOPYALAR["yerel"]), "uzaklar": {}} once = olc(depo) tanimla(depo, "koken", "ornek.test/koken") tanimla(depo, "yukari", "ornek.test/yukari") sonra = olc(depo) print(f"tanımlamadan önce yerel: {once[0]} işleme / {once[1]} soru") print(f"{len(depo['uzaklar'])} tanımdan sonra yerel: {sonra[0]} işleme / {sonra[1]} soru") print() basvuru = [("yerel", dal) for dal in KOPYALAR["yerel"]] basvuru += [(uzak, dal) for uzak in depo["uzaklar"] for dal in KOPYALAR[uzak]] kisa = [dal for _, dal in basvuru] paylasilan = sorted(a for a in set(kisa) if kisa.count(a) > 1) print(f"başvuru {len(basvuru)} | ayrı kısa ad {len(set(kisa))} | " f"birden çok başvurunun paylaştığı kısa ad {len(paylasilan)}") for a in paylasilan: print(f" {a}: " + ", ".join(f"{u}/{d}" for u, d in basvuru if d == a))
gerçek gelişim 12 işleme, 3 dal; kopya 3 kopya dal işleme yanıtlanan yanıtlanamayan yerel 1 5 4 kusurun yalıtımı, çakışma kararı koken 2 10 5 çakışma kararı yukari 3 15 5 çakışma kararı tanımlamadan önce yerel: 5 işleme / 4 soru 2 tanımdan sonra yerel: 5 işleme / 4 soru başvuru 6 | ayrı kısa ad 3 | birden çok başvurunun paylaştığı kısa ad 2 olcum: yerel/olcum, koken/olcum, yukari/olcum rapor: koken/rapor, yukari/rapor
Kopyanın Yanıtlayabildiği
Üst tablo aynı soruyu üç ayrı kopyaya soruyor. yukari on beş işleme taşıyor ve beş soru
yanıtlıyor; koken on işlemeyle aynı beşi yanıtlıyor; yerel beş işlemeyle dört.
Eksik olan soru kusurun yalıtımı ve eksikliğin nedeni burada yeni bir şeydir. Önceki
derslerde bir sorunun yanıtsız kalması, seçilen tümleştirme biçiminin bilgiyi silmesinden
geliyordu: sıkıştırma on iki işlemeyi üçe indiriyor ve kusurlu işlemeyi ayrı okunamaz hâle
getiriyordu. Burada hiçbir şey silinmedi. yerel kopya kusuru yalıtamıyor çünkü kusurlu
işleme onda hiç yok — kusuru rapor dalının ikinci işlemesi getiriyor ve rapor dalı bu
kopyada bulunmuyor.
Bu, kursun ölçüsüne ikinci bir kayıp kaynağı ekler. Tarihçe, biçim yüzünden bilgi kaybedebilir; kopya, kapsam yüzünden bilgi kaybedebilir. İkincisi geri alınabilir bir kayıptır: eksik dallar getirildiğinde soru yeniden yanıtlanır hâle gelir. Biçim kaybı için aynı şey söylenemez.
koken ile yukari arasındaki karşılaştırma ikinci bir şey söylüyor. Beş işleme fark var ve
yanıtlanan soru sayısı aynı. Taşınan işlemenin artması yanıtlanan soruyu artırmaz;
artıran şey, yanıtsız kalan sorunun ihtiyaç duyduğu işlemenin gelmesidir. kimlik dalının
dört işlemesi hiçbir sorunun eksik yanıtını tamamlamıyor, çünkü kusur o dalda değil.
Altıncı soru üç kopyada da yanıtsız. Çakışmanın nerede ve nasıl çözüldüğü hiçbir kopyada yazılı değildir; kopya sayısını artırmak bunu değiştirmez.
Tanımın Ödediği
Orta iki satır dersin adını taşıyan işlemi ölçüyor. Tanımlamadan önce yerel kopya 5 işleme ve 4 soru; iki uzak depo tanımlandıktan sonra yine 5 işleme ve 4 soru.
Bu bir yuvarlama değil, tanımın kendisidir. tanimla işlevi yalnız uzaklar sözlüğüne
dokunuyor; tarihce listesine hiç bakmıyor. Aracın davranışı da budur: uzak depo eklemek
yapılandırmaya iki satır yazar, ağa çıkmaz, tek bir nesne getirmez, tek bir başvuru
oluşturmaz. Adres yanlış yazılmışsa bunu tanımlama anında öğrenmezsin — ilk getirme
denemesinde öğrenirsin.
Buradan pratik bir alışkanlık çıkar: bir uzak depo tanımının doğruluğu ancak karşı tarafla
konuşan bir işlemle sınanır. git remote -v yalnız ne yazdığını gösterir, git remote show
ise karşı tarafa gerçekten bağlanır ve adın altındaki dalları listeler. İkisi ayrı sorulardır.
Ad Alanının Ödettiği
Alt tablo altı başvuru sayıyor ve bunların yalnız üç ayrı kısa adı var. olcum kısa adını
üç başvuru paylaşıyor, rapor kısa adını iki başvuru.
Ad alanı olmasaydı bu altı başvuru üç yuvaya sığmak zorunda kalırdı ve kopyalar birbirinin
kaydını ezerdi. Uzak depo adı tam olarak bu yüzden vardır: koken/olcum ile yukari/olcum
ayrı başvurulardır, ayrı işlemeleri gösterebilirler ve ikisi de yerel olcum dalından
bağımsızdır.
Bedeli belirsizliktir. Bir komuta yalın olcum verildiğinde araç önce yerel dallara bakar;
başvuru orada bulunduğu için karşı tarafın olcumu hiç aranmaz. İki kopyanın olcum dalı
ayrışmışsa ve sen yalın adı yazdıysan, gördüğün şey senin dalındır — karşı tarafınki değil.
Bu, ayrışmayı fark etmeyi geciktiren en sık nedendir. Nitelikli ad yazmak (koken/olcum) bu
belirsizliği ortadan kaldırır ve iki başvurunun ayrı ayrı sorulmasını sağlar.
Ad alanının bir kez daha kanıtlandığı yer yeniden adlandırmadır. git remote rename yalnız
yapılandırmadaki satırı değiştirmez; o adın altındaki bütün uzak izleme başvurularını da yeni
önekle yeniden yazar. Beş başvuru taşıyan bir tanımda beş başvurunun adı değişir ve
işlemelerin hiçbiri kopyalanmaz — çünkü başvuru bir addır, taşıdığı işleme değil.
Birden Çok Uzak Depo Ne Zaman Gerekir
Ölçüm iki uzak depoyla çalıştı ve bu sayı keyfî değil. Birden çok tanım, kopyaların ayrı roller taşıdığı her durumda ortaya çıkar.
Birinci rol ayrımı yetkidir. Yazma yetkisinin bulunduğu kopya ile yalnız okunan kopya
farklıysa iki tanım gerekir: değişiklikler birine itilir, güncellemeler ötekinden getirilir.
Ölçümdeki koken ve yukari tam olarak bu ayrımı taşıyor ve sonraki iki dersin konusu bu
ayrımın açtığı katkı modelidir.
İkinci rol ayrımı eşliktir. Dağıtık modelde bir kopyanın uzak deposu bir sunucu olmak zorunda değildir; takımdaki başka birinin kopyası da tanımlanabilir. Yarım kalmış bir dalı ortak bir kopyaya itmeden incelemek gerektiğinde bu doğrudan yol açılır ve ortadaki kopyaya hiç uğranmaz.
Üçüncü rol ayrımı yedektir. Bir aynanın ayrı adla tanımlanması, aynı dalların iki ayrı başvuru kümesinde tutulmasını sağlar; iki kümenin ayrışması ancak ikisi de tanımlıyken görülebilir.
Üç durumda da tanım sayısının artması yerel tarihçeyi büyütmez. Büyüyen tek şey başvuru ad alanıdır ve alt tablonun gösterdiği paylaşılan kısa ad sorunu her yeni tanımla bir kez daha tekrarlanır. Bu yüzden ad seçimi, tanım sayısı arttıkça daha çok önem kazanır: adlar rolü söylediğinde bir komutun hangi kopyaya gittiği komutun kendisinden okunur.
Özet
- Uzak depo, karşı taraftaki kopya değil, o kopyaya bu depoda verilen addır; tanım yapılandırmada durur, tarihçede durmaz ve kopyayı alan başkasına geçmez.
- Uzak izleme başvuruları
refs/remotes/<ad>altında durur, yerelden yazılmaz ve karşı tarafın dalının en son görülmüş hâlini kaydeder. - Üç kopya 5, 10 ve 15 işleme taşır ve 4, 5, 5 soru yanıtlar;
yerelkopyanın eksik yanıtı biçim kaybından değil kapsam kaybından gelir, çünkü kusurlu işleme o kopyada hiç yoktur. - Taşınan işlemenin artması yanıtlanan soruyu tek başına artırmaz:
kokenileyukariarasında beş işleme fark vardır ve ikisi de aynı beş soruyu yanıtlar. - İki uzak depo tanımı yerel kopyayı 5 işleme ve 4 soruda bırakır; tanımlama sıfır işleme getirir ve adresin doğruluğunu sınamaz.
- Altı başvuru üç ayrı kısa ad taşır; ad alanı bu çakışmayı çözer, karşılığında yalın ad her zaman yerel dala düşer.
Sonraki Adım
Tanım bir addır ve ad tek başına hiçbir işleme getirmiyor. Yerel kopya hâlâ beş işleme taşıyor, karşı taraf on beş taşıyor ve aradaki fark kapanmış değil. Sonraki ders bu farkı kapatan üç işlemi ayırır: hangisi yerel tarihçeye hiç dokunmaz, hangisi ona bir birleştirme işlemesi ekler, hangisi karşı tarafın tarihçesini değiştirir. Üçü aynı ağ bağlantısını kullanır ve üçünün tarihçeye ödettiği bedel aynı değildir.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.