İçeriğe geç
academia.sh

Ders 13 / 15

Çatallama ve Klonlama

İki katkı modelinde yukarı deponun yanıtladığı soru tümleştirme biçimine bağlıdır: 15 işlemeyle 5, 12 işlemeyle 3, 3 işlemeyle 2 soru yanıtlanır ve çatal deposu 12 işlemeyle 5 soru yanıtladığı için üç soru yalnız yukarı deponun sahip olmadığı bir kopyada durur.

İçindekiler

Önceki dersin üç işlemi tek bir varsayımla çalıştı: itme yetkisi vardı. Yerel kopya karşı tarafın dalını değiştirebiliyordu ve tek engel ileri sarılabilirlik koşuluydu. Katkı akışlarının büyük bölümünde bu varsayım geçersizdir. Katkıyı alan depoya yazma yetkisi yoktur ve olmaması bir kısıt değil, sahiplik tanımının kendisidir.

Yetki yoksa katkı nasıl gider? İki yanıt vardır ve ikisi aynı şeyin adları değildir. Bu dersin ölçüsü şudur: iki modelde de aynı on iki işleme üretilir, ama yukarı deponun sonunda elinde kalan tarihçe aynı değildir — ve fark, hangi soruların nerede yanıtlanabildiğini belirler.

Klonlama

Klonlama (clone), bir kopyanın tamamını yeni bir yere almaktır: bütün işlemeler, bütün dallar ve bütün etiketler kopyalanır. Kopya eksiksizdir; klonlanan depo silinse bile klon kendi başına tam bir depodur.

# öğretilen komutlar — örnek döküm, çalıştırılmamıştır

git clone https://ornek.test/kaynak/olcum-aglari.git
cd olcum-aglari
git remote -v

origin  https://ornek.test/kaynak/olcum-aglari.git (fetch)
origin  https://ornek.test/kaynak/olcum-aglari.git (push)

Klonlama üç şeyi birden yapar: kopyayı alır, kaynağa origin adıyla bir uzak depo tanımı yazar ve varsayılan dalı bu tanıma bağlı olarak kurar. Önceki iki dersin elle yaptığı işleri tek komutta toplar; bu yüzden tanımın nereden geldiği çoğu zaman fark edilmez.

Klonlamaya dayanan katkı modeli doğrudandır: katkıcı yukarı depoyu klonlar, dalını açar, işlemelerini yapar ve dalı doğrudan yukarı depoya iter. Bu model yalnız katkıcının yukarı depoda itme yetkisi varsa çalışır — yani takım içi katkının olağan biçimidir.

Klonun Kapsamı

Klonlamanın eksiksiz olması bir varsayılandır, bir zorunluluk değil. Seçenekler kopyanın kapsamını daraltır ve daraltmanın bedeli ölçünün diliyle okunabilir.

Derinlik sınırı verilen bir klon yalnız son işlemeleri alır; öncesi hiç gelmez. Tek dala sınırlanan bir klon öbür dalların başvurularını hiç yazmaz. İki durumda da tarihçe değiştirilmemiştir — kaynakta olduğu gibi durur; alınmayan yalnız kapsamdır. Birinci dersin ayrımı burada tam olarak geçerlidir: bu bir biçim kaybı değil, kapsam kaybıdır ve kapsam kaybı geri alınabilir. Eksik derinlik sonradan tamamlanabilir, eksik dal sonradan getirilebilir.

Ters yöndeki seçenekler de vardır. Çalışma alanı olmadan alınan bir klon yalnız depo verisini taşır ve sunucu tarafında tutulan kopyaların olağan biçimi budur; başvuruların tamamını birebir kopyalayan bir klon ise uzak izleme başvuruları dâhil her şeyi taşır ve yedek almanın en doğrudan yoludur.

Seçim, kopyanın ne için alındığına bağlıdır. Sürekli tümleştirme için alınan bir kopyanın on yıllık tarihçeye ihtiyacı yoktur; bir kusurun hangi işlemede girdiğini arayan bir kopyanın ise tam tarihçeye ihtiyacı vardır ve sığ bir klonda o arama yapılamaz. Kapsamı daraltmak zaman kazandırır ve kazandığı zamanı, ileride sorulacak bir soruyla öder.

Depo Çatallaması

Depo çatallaması (fork), yukarı deponun sunucu tarafında alınmış ve katkıcıya ait olan bir kopyasıdır. Terim, İşletim Sistemi Kavramları kursunda tanımlanan süreç çatallamasıyla aynı sözcüğü paylaşır ve ayrı bir kavramdır: orada bir sürecin ikiye ayrılması, burada bir deponun ikinci bir sahiplik alanında kopyalanması. Bu yetenek depo platformlarının sağladığı bir sınıf yeteneğidir; ürün adı bu derste geçmez.

Çatalın çözdüğü sorun yetkidir. Katkıcı çatal deposunda tam yetkiye sahiptir: istediği dalı açar, istediği kadar iter, istediğini siler. Yukarı depoda ise hiçbir yazma yetkisi yoktur.

# öğretilen komutlar — örnek döküm, çalıştırılmamıştır

git clone https://ornek.test/katkici/olcum-aglari.git
cd olcum-aglari
git remote add yukari https://ornek.test/kaynak/olcum-aglari.git
git fetch yukari
git remote -v

origin  https://ornek.test/katkici/olcum-aglari.git (fetch)
origin  https://ornek.test/katkici/olcum-aglari.git (push)
yukari  https://ornek.test/kaynak/olcum-aglari.git (fetch)
yukari  https://ornek.test/kaynak/olcum-aglari.git (push)

Çatal modelinde yerel depo iki uzak depo tanımı taşır: çatalın kendisi ve yukarı depo. Bu, birinci dersin ölçtüğü ad alanı sorununu doğrudan doğuran yapıdır — origin/ana ile yukari/ana ayrı başvurulardır ve çatal, yukarı depo ilerledikçe geride kalır. Çatalın güncel tutulması, yukarı depodan getirip çatala itmekten ibarettir ve bu iş katkıcıya aittir; kendiliğinden olmaz.

Güncelleme ihmal edildiğinde önceki dersin ölçtüğü ayrışma tablosu doğrudan devreye girer. Çatalın ana dalı ile yukarı deponun ana dalı ayrıştıkça ortak taban geriler ve katkı dalı, yukarı depoda artık bulunmayan bir tabana yaslanmış olur. Bu, birleştirme çakışmasının en öngörülebilir kaynağıdır: çakışma katkının içeriğinden değil, tabanın eskimesinden doğar.

Ölçümün Varsayımları

  • UD13 — Aynı on iki işlemelik gelişim iki modelde de aynı biçimde üretilir; modeller arasındaki fark üretimde değil, işlemelerin hangi kopyada durduğundadır.
  • UD14 — Klonlama modelinde katkıcı dalları doğrudan yukarı depoya iter; ayrı bir kopya yoktur ve ölçümde çatal sütunu 0 yazılır.
  • UD15 — Çatal deposu dalları geliştirildikleri gibi taşır: dal kaydı yerinde, zaman korunmuş, sıkıştırma uygulanmamış. Bu, katkıcının kendi kopyasında gördüğü hâldir.
  • UD16 — Yukarı depoya geçiş dört tümleştirme biçiminden biriyle yapılır ve biçim ölçüme girer; biçimlerin tanımı Birleştirme konusundaki tanımın aynısıdır ve burada değiştirilmez.
  • UD17 — “Yalnız çatalda” sütunu, çatal deposunun yanıtladığı sorulardan yukarı deponun yanıtlayamadıklarını sayar; klonlama satırında ayrı kopya bulunmadığı için bu küme boştur.
  • UD18 — Üçüncü tablo yapısaldır ve tarihçeden değil, iki modelin tanımından okunur: yukarı depodaki katkı dalı sayısı, katkıcının tanımlaması gereken uzak depo sayısı ve itme yetkisinin hangi depoda bulunduğu.

Ölçüm

"""İki katkı modeli: klonlama ve depo çatallaması.

Bölüm 1 - yukarı deponun taşıdığı tarihçe ve yanıtladığı soru.
Bölüm 2 - yalnızca çatalda yanıtlanabilen sorular.
Bölüm 3 - iki modelin yapısal farkı: başvuru ve tanım sayısı.
"""
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 tumlestir(kayit, bicim):
    """Her tümleştirme biçimi ayrı bir tarihçe üretir."""
    t = []
    if bicim == "birlestirme islemesi":
        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})
    elif bicim == "yeniden temellendirme":
        for dal in DALLAR:
            for k in [x for x in kayit if x["dal"] == dal]:
                t.append({**k, "dal_kaydi": None, "zaman_korundu": False})
    elif bicim == "sikistirma":
        for dal in DALLAR:
            grup = [x for x in kayit if x["dal"] == dal]
            t.append({"dal": dal, "sira": 0,
                      "dosya": sorted({x["dosya"] for x in grup}),
                      "kusurlu": any(x["kusurlu"] for x in grup),
                      "zaman": max(x["zaman"] for x in grup),
                      "dal_kaydi": dal, "zaman_korundu": False, "sikisik": len(grup)})
    elif bicim == "ileri sarma":
        for k in sorted(kayit, key=lambda x: x["zaman"]):
            t.append({**k, "dal_kaydi": None, "zaman_korundu": True})
    return t


def catal(kayit):
    """Çatal deposunun taşıdığı hâl: dallar geliştirildikleri gibi durur."""
    return [{**k, "dal_kaydi": k["dal"], "zaman_korundu": True}
            for dal in DALLAR for k in kayit if k["dal"] == dal]


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))


def yanitlanan(t):
    return {ad for ad, f in SORULAR if f(t)}


MODELLER = (("klonlama", False, "birlestirme islemesi"),
            ("çatallama", True, "birlestirme islemesi"),
            ("çatallama", True, "yeniden temellendirme"),
            ("çatallama", True, "sikistirma"),
            ("çatallama", True, "ileri sarma"))

kayit = gelisim()
c = catal(kayit)
print(f"gerçek gelişim {len(kayit)} işleme; çatal deposu {len(c)} işleme taşır ve "
      f"{len(yanitlanan(c))} soru yanıtlar")
print()
print("model      tümleştirme biçimi      çatal  yukarı  yukarının yanıtı  "
      "yalnız çatalda  yukarıda kaybolan")
for model, ayri, bicim in MODELLER:
    t = tumlestir(kayit, bicim)
    yukari = yanitlanan(t)
    ayrik = yanitlanan(c) - yukari if ayri else set()
    okunur = sum(1 for x in t if not x.get("birlesme") and not x.get("sikisik"))
    print(f"  {model:9s} {bicim:22s} {len(c) if ayri else 0:5d} {len(t):7d}"
          f" {len(yukari):17d} {len(ayrik):15d} {len(kayit) - okunur:18d}")

print()
for model, ayri, bicim in MODELLER:
    if not ayri:
        continue
    ayrik = sorted(yanitlanan(c) - yanitlanan(tumlestir(kayit, bicim)))
    if ayrik:
        print(f"  {bicim:22s} yalnız çatalda: {', '.join(ayrik)}")

print()
print("model      yukarıdaki katkı dalı  katkıcının uzak depo tanımı  itme yetkisi")
print(f"  {'klonlama':9s} {len(DALLAR):21d} {1:28d}  yukarı depo")
print(f"  {'çatallama':9s} {0:21d} {2:28d}  çatal")
gerçek gelişim 12 işleme; çatal deposu 12 işleme taşır ve 5 soru yanıtlar

model      tümleştirme biçimi      çatal  yukarı  yukarının yanıtı  yalnız çatalda  yukarıda kaybolan
  klonlama  birlestirme islemesi       0      15                 5               0                  0
  çatallama birlestirme islemesi      12      15                 5               0                  0
  çatallama yeniden temellendirme     12      12                 3               2                  0
  çatallama sikistirma                12       3                 2               3                 12
  çatallama ileri sarma               12      12                 3               2                  0

  yeniden temellendirme  yalnız çatalda: gerçek sıra, özellik gruplaması
  sikistirma             yalnız çatalda: dosya izi, gerçek sıra, kusurun yalıtımı
  ileri sarma            yalnız çatalda: dalın bütünlüğü, özellik gruplaması

model      yukarıdaki katkı dalı  katkıcının uzak depo tanımı  itme yetkisi
  klonlama                      3                            1  yukarı depo
  çatallama                     0                            2  çatal

Yukarı Deponun Yanıtlayabildiği

İlk iki satır aynı sayıyı veriyor: klonlama modeli de çatallama modeli de, tümleştirme birleştirme işlemesiyle yapıldığında yukarı depoya 15 işleme ve 5 soru bırakıyor.

Bu sonuç dersin ilk düzeltmesidir. Çatallama tek başına yukarı deponun bilgisini azaltmaz. Katkının ayrı bir kopyadan gelmiş olması tarihçeye hiçbir iz bırakmaz; yukarı depoya giren şey işlemelerin kendisidir ve o işlemeler çatalda da yukarıda da aynı işlemelerdir. İki modeli ayıran şey yetkidir, kayıt değil.

Kalan üç satır asıl değişkeni gösteriyor. Yukarı deponun yanıtladığı soru 5’ten 3’e ve 2’ye iniyor ve inişin nedeni her seferinde aynı: seçilen tümleştirme biçimi. Birleştirme konusunun ölçtüğü sayılar burada bire bir tekrar ediyor, çünkü ölçülen şey aynı tarihçedir; değişen tek şey tarihçenin hangi depoda durduğudur.

Sıkıştırma satırı ayrı durur. Yukarı depo 3 işleme taşıyor, 2 soru yanıtlıyor ve yukarıda kaybolan sütunu 12 yazıyor: gerçek gelişimin tamamı yukarı depoda ayrı okunabilir olmaktan çıkmış. Öbür üç satırda bu sütun 0’dır — biçimler bilgi kaybettirse bile işlemeyi ayrı ayrı okunabilir bırakırlar.

Yalnız Çatalda Duran Yanıt

İkinci tablo dersin asıl bulgusudur. Çatal deposu on iki işlemeyi geliştirildikleri gibi taşıyor ve 5 soru yanıtlıyor. Yukarı depo, tümleştirme biçimine göre 5, 3 ya da 2 yanıtlıyor. Aradaki fark boşlukta durmuyor: o sorular yanıtlanabilir durumda, ama yanıtı yukarı depoda değil, çatalda.

Sıkıştırma satırında bu fark üçe çıkıyor. “Kusurun yalıtımı”, “gerçek sıra” ve “dosya izi” soruları çatalın on iki işlemesine sorulduğunda yanıtlanıyor; yukarı deponun üç işlemesine sorulduğunda yanıtlanmıyor. Yeniden temellendirme ve ileri sarma satırlarında fark ikidir ve farklı sorulardır — ilki “özellik gruplaması” ile “gerçek sıra”yı, ikincisi “özellik gruplaması” ile “dalın bütünlüğü”nü çatalda bırakır.

Buradan çıkan sonuç bir uyarıdır. Yukarı deponun yanıtlayamadığı bir soru, sahibi olmadığı bir kopyada yanıtlanıyor olabilir. Çatal deposu katkıcıya aittir: silinebilir, yeniden adlandırılabilir, erişimi kapatılabilir. Bunların hiçbiri yukarı depoya haber vermez ve hiçbiri yukarı deponun kaydını bozmaz — yalnız, eksik yanıtın bulunabileceği yeri ortadan kaldırır.

Bu, birinci derste ölçülen kapsam kaybının kalıcı hâle gelen biçimidir. Orada eksik dallar getirilebiliyordu ve kayıp geri alınabilirdi. Burada eksik olan şey yukarı depoya hiç girmemiştir ve girebileceği tek yer kapanabilir.

Yapısal Fark

Üçüncü tablo iki modelin tarihçeden okunmayan farkını veriyor.

Klonlama modelinde katkıcının üç dalı yukarı depoda durur. Bu, dal adlarının yukarı deponun ad alanına girmesi demektir: adlandırma düzeni yukarı depoda uygulanmak zorundadır, terk edilmiş dallar yukarı depoda birikir ve temizlik yukarı deponun işidir. Katkıcı tek bir uzak depo tanımı taşır ve itme yetkisi doğrudan yukarı depodadır.

Çatallama modelinde yukarı depoda katkı dalı hiç bulunmaz. Dallar çatalda açılır, çatalda birikir ve çatalda silinir; yukarı depoya yalnız tümleştirmenin sonucu geçer. Katkıcı iki uzak depo tanımı taşımak zorundadır ve bunun bedeli birinci derste ölçülmüştü: paylaşılan kısa adlar ve yalın adın her zaman yerele düşmesi.

İki modelin seçimi bu yüzden bir tarihçe kararı değil, bir sahiplik kararıdır. Yukarı depo kimin yazabileceğine karar verir; tarihçenin ne kaydedeceğine ise tümleştirme biçimi karar verir. İkisi bağımsızdır ve karıştırılmaları, çatallamanın kendisine bilgi kaybı yüklemek gibi bir yanlış okumaya yol açar.

Özet

  • Klonlama bir kopyanın tamamını alır ve kaynağa bir uzak depo tanımı yazar; depo çatallaması ise yukarı deponun katkıcıya ait ikinci bir kopyasıdır ve İşletim Sistemi Kavramları kursunda tanımlanan süreç çatallamasından ayrı bir kavramdır.
  • İki model de birleştirme işlemesi biçimiyle yukarı depoya 15 işleme ve 5 soru bırakır: çatallama tek başına yukarı deponun bilgisini azaltmaz.
  • Yukarı deponun yanıtladığı soruyu belirleyen şey tümleştirme biçimidir: 15/5, 12/3, 3/2, 12/3; sıkıştırmada gerçek gelişimin 12 işlemesi yukarıda ayrı okunabilir olmaktan çıkar.
  • Çatal deposu 12 işleme taşır ve 5 soru yanıtlar; sıkıştırmada 3 soru yalnız çatalda yanıtlanabilir kalır ve çatal yukarı deponun sahip olmadığı bir kopyadır.
  • Yapısal fark tarihçeden okunmaz: klonlama modelinde katkı dalları yukarı depoda durur ve katkıcı bir tanım taşır; çatallama modelinde yukarıda katkı dalı bulunmaz ve katkıcı iki tanım taşır.

Sonraki Adım

Çatal modelinde katkıcının yukarı depoya itme yetkisi yok; buna rağmen on iki işleme bir biçimde yukarıya geçti. Geçişi yapan şey bir komut değil, bir akıştır: öneri sunulur, üzerinde konuşulur, sonunda biri onu ana dala alır. Sonraki ders bu döngünün mekaniğini kurar ve akışın seçtiği tümleştirme biçiminin tarihçeye kaç soru bıraktığını ölçer. Ölçüm ayrıca akış sırasında alınan kararlardan kaçının tarihçede iz bıraktığını sayar; yanıt beklenenden küçüktür.

İlerlemeni kaydetmek ve not almak için Giriş yap

Notlarım

Not almak için giriş yapmalısın.

Aramak için yazmaya başlayın.

↑↓ Esc gezin · aç · kapat