---
title: 'Alt Modüller'
source: 'https://academia.sh/tr/kurslar/ileri-git/alt-moduller'
course: 'İleri Git'
language: tr
updated: '2026-08-17T18:10:43+00:00'
license: 'CC BY-SA 4.0'
---

# Alt Modüller

Alt modül ana depoya bir tarihçe değil bir kimlik yazar: üç alt modül bir işlemeyi dört ayrı tarihçeye bağlar, 76 nesnelik 38 işleme 378 alt modül işlemesini içeri alır ve özyinelemeli klon 920 nesneden 4540'a çıkar.

Buraya kadar tarihçe **tek bir deponun** içindeydi. İkili arama, suçlama ve yeniden yazma
ölçüldü; nesne sayısı bu ölçümlerin arka planında durdu — bedeli belirleyen değişkendi ama
ölçülen şeyin kendisi değildi.

Bu konuda arka plan öne geçiyor. Depo büyüdüğünde ve tek bir tarihçeye sığmayan parçalar
taşımaya başladığında sorulan soru değişir: **nesne sayısının kendisi iş olursa ne olur?**
İlk durum, bir deponun başka bir deponun tarihçesini içine alması. Bu dersin sorusu alt
modülün nasıl kurulduğu değil — kurulumu iki komuttan ibarettir. Soru şudur: ana depoya
yazılan tek bir kimlik, o depodaki bir işlemeyi **kaç ayrı tarihçeye** bağlar ve klon bedeli
buna nasıl tepki verir?

## Ana Depo Neyi Kaydeder

**Alt modül (submodule)**, bir deponun çalışma ağacında duran ve kendi tarihçesi olan başka
bir depodur. Ana depo onun dosyalarını kendi nesne deposuna kopyalamaz; kaydettiği tek şey
alt modülün **hangi işlemede** durduğudur. Bu kayda **sabitlenmiş sürüm (pinned version)**
denir ve ana depo ağacında bir dizin girdisi olarak durur.

İki dosya işin tamamıdır. `.gitmodules` alt modülün adını ve nereden getirileceğini bildirir;
ağaç girdisi ise sabitlenmiş sürümün kimliğini tutar. Birincisi işlenen bir metin dosyasıdır,
ikincisi her işlemede yeniden yazılabilen bir alandır.

```text
# öğretilen komutlar ve dosya içeriği — örnek döküm, çalıştırılmamıştır

git submodule add <alt-modül-adresi> bilesenler/olcum-cekirdegi
git submodule update --init --recursive
git clone --recurse-submodules <ana-depo-adresi>

# .gitmodules
[submodule "bilesenler/olcum-cekirdegi"]
	path = bilesenler/olcum-cekirdegi
	url = <alt-modül-adresi>
```

`--recurse-submodules` seçeneği klonlamayı ana depoyla bitirmez: her alt modülü ayrı ayrı
klonlar. Seçeneksiz klon alt modül dizinlerini **boş** bırakır; ana depo tarihçesi eksiksiz
gelir ama çalışma ağacı çalışmaz. `update --init` sonradan aynı işi yapar.

## Sabitlenmiş Sürümün İki Yüzü

Sabitlenmiş sürüm ana depoda **ucuz**, ana depo dışında **pahalıdır** ve dersin bütün gerilimi
buradadır.

Ucuz yüzü: alt modülü ilerletmek ana depoda tek bir işlemedir. Ağaç girdisindeki kimlik
değişir, yeni bir ağaç ve mesajı taşıyan bir damla yazılır — **iki nesne**. Alt modülde o
aralıkta kaç işleme birikmiş olursa olsun, ana depoya yazılan nesne sayısı bundan bağımsızdır.

Pahalı yüzü: o iki nesne, alt modül tarihçesindeki bir işlemeyi ana depo tarihçesine
**bağlar**. Ana depodaki bir işlemeyi yeniden üretmek artık tek bir tarihçeye erişmeyi değil,
ana depo ile her alt modülün tarihçesine birden erişmeyi gerektirir. Üç alt modülü olan bir
depoda, tek bir işlemenin ağacını kurmak için **dört** ayrı tarihçeden **dört** kimlik
okunmalıdır.

Bu ikinci yüz ölçülebilir bir şeydir ve ölçüm iki soruyu ayırır: ana depoda **yazılan** nesne
kaçtır, ve o yazımın **bağladığı** tarihçe ne kadardır.

## Dalı Değil İşlemeyi İzler

Sabitlenmiş sürüm bir **işleme kimliğidir**, bir dal adı değil. Bunun doğrudan bir sonucu var:
alt modül dizini klonlandıktan sonra hiçbir dalın üstünde durmaz — ayrık HEAD durumundadır.
Ayrık HEAD, Dallanma ve İşbirliği kursunda tarihçenin dışına düşen işleme bağlamında
kurulmuştu; burada bir kaza değil, alt modülün **normal** durumudur. Ana depo bir dalı
sabitleyemez, çünkü dal hareket eder ve hareket eden bir başvuru sabitlenmiş sürüm olamaz.

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

git -C bilesenler/olcum-cekirdegi checkout ana
git -C bilesenler/olcum-cekirdegi pull
git add bilesenler/olcum-cekirdegi
git commit -m "Ölçüm çekirdeği sabitlenmiş sürümü ilerletildi"

git submodule update --remote bilesenler/olcum-cekirdegi
git submodule status
```

İlerletme dört adımdır ve dördü de elle yapılır: alt modülde bir dala geçilir, yeni işlemeler
getirilir, **ana depoda** alt modül dizini hazırlık alanına alınır ve işlenir. Üçüncü adım
atlanırsa alt modül dizini yeni bir işlemeyi gösterir ama ana depo hâlâ eskisini kaydeder;
`status` çıktısı bunu bildirir, tarihçe bildirmez. `--remote` seçeneği ilk iki adımı
`.gitmodules` dosyasında yazılı dala göre otomatikleştirir, ama üçüncü adımı **yine yazan
atar**: ana depoya yazılmayan bir ilerletme yoktur.

Bu, alt modülü bir bağımlılık yöneticisinden ayıran yerdir. Bağımlılık yöneticisi bir aralık
bildirir ve çözümü kendisi yapar; alt modül tek bir kimlik bildirir ve çözüm diye bir şey
yoktur. Karşılığında alt modül tam tarihçeyi getirir: sabitlenmiş sürüme kadar olan her işleme
oradadır, okunabilir ve üstünde arama yapılabilir.

## Ölçümün Varsayımları

- **BD1** — Ana depo ortak kurgunun **200** işlemelik ölçeğidir; üç alt modülün her biri aynı
  kurgudan ayrı bir tohumla üretilmiş bağımsız bir tarihçedir. Alt modül tarihçeleri ana
  depoyla hiçbir nesne paylaşmaz.
- **BD2** — Sabitlenmiş sürümü ilerleten ana depo işlemeleri ayrı bir üreteçten seçilir; her
  ilerletme alt modülde **1 ile 20 arası** işleme tüketir ve alt modülün sonunu aşamaz.
- **BD3** — Sabitlenmiş sürümü ilerleten işleme ana depoda **2 nesne** yazar: yeni ağaç ve
  mesajı taşıyan damla. Bu sayı, alt modülde kaç işleme geçildiğinden bağımsızdır.
- **BD4** — "Kapsanan işleme", alt modül tarihçesinde ana deponun ucuna kadar tüketilmiş
  işleme sayısıdır; ana depo tarihçesinde görünmez ama ana deponun ucundaki durumu
  yeniden üretmek için gereklidir.
- **BD5** — "Gereken kimlik", ana depodaki tek bir işlemenin ağacını kurmak için okunması
  gereken kimlik sayısıdır: ana deponun kendi kimliği artı her alt modülün sabitlenmiş
  sürümü.
- **BD6** — Özyinelemeli klon her alt modülün **tam tarihçesini** getirir. Bedel **dokunulan
  nesne** birimiyle sayılır; ağ, saat ve disk ölçümün dışındadır.

## Ölçüm

```python
"""Alt moduller: sabitlenmis surumun bagladigi tarihce ve klon bedeli.

Bolum 1 - her alt modulun ilerletme sayisi ve klon nesnesi.
Bolum 2 - alt modul sayisi arttikca bagli tarihce ve ozyinelemeli klon.
"""
TOHUM = 20260814
DOSYALAR = ("olcum.py", "rapor.py", "kimlik.py", "ayar.py", "belge.md")
ANA_OLCEK = 200
ALT_MODULLER = (("olcum-cekirdegi", 300, TOHUM + 1),
                ("rapor-bicimi", 150, TOHUM + 2),
                ("kimlik-kitapligi", 80, TOHUM + 3))


def uretec(tohum):
    d = tohum % 2147483646 + 1

    def r(n):
        nonlocal d
        d = (d * 48271) % 2147483647
        return d % n
    return r


def tarihce(n, tohum=TOHUM):
    """n islemelik dogrusal tarihce; her isleme bir dosyaya dokunuyor."""
    r, liste = uretec(tohum), []
    for i in range(n):
        dosya = DOSYALAR[r(5)]
        ikili = r(11) == 0
        liste.append({"no": i + 1, "dosya": dosya, "ikili": ikili,
                      "nesne": 2 + (40 if ikili else 0)})
    return liste


def klon_bedeli(t, ikili_dahil=True):
    return sum(x["nesne"] for x in t if ikili_dahil or not x["ikili"])


def sabitlemeler(ana, alt, tohum):
    """Ana depodaki hangi islemeler sabitlenmis surumu ilerletiyor."""
    r, kayit, yer = uretec(tohum), [], 0
    for x in ana:
        ilerlet = r(12) == 0
        adim = 1 + r(20)
        if ilerlet and yer < len(alt):
            yer = min(yer + adim, len(alt))
            kayit.append({"ana_no": x["no"], "sabit": yer})
    return kayit


ana = tarihce(ANA_OLCEK)
print(f"ana depo {len(ana)} isleme, klon nesnesi {klon_bedeli(ana)}, "
      f"ikilisiz {klon_bedeli(ana, False)}")
print()
print("alt modul           isleme  ilerletme  kapsanan isleme  ana depoda nesne"
      "  klon nesnesi")
kayitlar = []
for ad, n, tohum in ALT_MODULLER:
    alt = tarihce(n, tohum)
    s = sabitlemeler(ana, alt, tohum + 100)
    kayitlar.append((ad, alt, s))
    print(f"  {ad:18s} {n:6d} {len(s):10d} {s[-1]['sabit']:16d} "
          f"{len(s) * 2:17d} {klon_bedeli(alt):13d}")
print()
print("alt modul sayisi  bagli tarihce  gereken kimlik  ana klon nesnesi"
      "  ozyinelemeli klon nesnesi   kat")
for k in range(len(ALT_MODULLER) + 1):
    ozyinelemeli = klon_bedeli(ana) + sum(klon_bedeli(a) for _, a, _ in kayitlar[:k])
    print(f"{k:16d} {k + 1:14d} {k + 1:15d} {klon_bedeli(ana):17d} "
          f"{ozyinelemeli:25d} {ozyinelemeli / klon_bedeli(ana):5.2f}")
print()
toplam_ilerletme = sum(len(s) for _, _, s in kayitlar)
toplam_kapsanan = sum(s[-1]["sabit"] for _, _, s in kayitlar)
print(f"sabitlemeyi ilerleten ana depo islemesi {toplam_ilerletme}, "
      f"ana depoya yazdigi nesne {toplam_ilerletme * 2}, "
      f"bagladigi alt modul islemesi {toplam_kapsanan}")
print(f"ana depo tarihcesi {len(ana)} isleme gorunuyor; "
      f"kapsadigi isleme {len(ana) + toplam_kapsanan}")
```

```
ana depo 200 isleme, klon nesnesi 920, ikilisiz 374

alt modul           isleme  ilerletme  kapsanan isleme  ana depoda nesne  klon nesnesi
  olcum-cekirdegi       300         18              161                36          2200
  rapor-bicimi          150         14              137                28           980
  kimlik-kitapligi       80          6               80                12           440

alt modul sayisi  bagli tarihce  gereken kimlik  ana klon nesnesi  ozyinelemeli klon nesnesi   kat
               0              1               1               920                       920  1.00
               1              2               2               920                      3120  3.39
               2              3               3               920                      4100  4.46
               3              4               4               920                      4540  4.93

sabitlemeyi ilerleten ana depo islemesi 38, ana depoya yazdigi nesne 76, bagladigi alt modul islemesi 378
ana depo tarihcesi 200 isleme gorunuyor; kapsadigi isleme 578
```

## Bağlanan Tarihçe

Son iki satır dersin çekirdeğini veriyor. Ana depoda sabitlemeyi ilerleten **38** işleme var
ve bu işlemeler ana depoya toplam **76** nesne yazıyor — iki yüz işlemelik tarihçenin **920**
nesnesinin içinde küçük bir paydır. Aynı 38 işleme, alt modül tarihçelerinden **378** işlemeyi
ana depoya bağlıyor.

Oran doğrudan okunur: ana depoya yazılan her **2** nesne, ortalama **on** alt modül işlemesini
içeri alıyor. Bu, dersin ölçtüğü asimetridir. Ana depo tarihçesine bakan biri **200** işleme
görür; ana deponun ucundaki durumu yeniden üretmek için gereken işleme sayısı **578**'dir.
Görünen tarihçe ile kapsanan tarihçe aynı şey değildir ve aradaki fark ana depoda hiçbir yerde
yazılı değildir.

Bu asimetrinin bir tanı sonucu var. Ana depoda yürütülen bir arama yalnız ana deponun **200**
işlemesini tarar; alt modüllerin **378** kapsanan işlemesi o taramanın dışındadır. Bir kusur
alt modülde girmişse ana depodaki arama onu **bulamaz** — bulabileceği en dar aralık, kusuru
içeri alan sabitleme işlemesidir. Aramanın ikinci turu alt modülün kendi tarihçesinde
yeniden kurulmak zorundadır. Ana depoda daralan aralık iki işleme olsa bile, o iki işlemenin
arasına sıkışmış alt modül işlemesi sayısı **yirmiye** kadar çıkabilir.

İkinci tablonun ilk iki sütunu aynı şeyi kimlik cinsinden söylüyor. Alt modül yokken bir
işlemenin ağacını kurmak **1** kimlik ister ve **1** tarihçeye bakar. Üç alt modülle bu sayı
**4**'e çıkar. Dördü de bulunmak zorundadır: alt modüllerden biri erişilemezse ana depodaki
işleme eksiksiz olarak durur ama **yeniden üretilemez**. Ana deponun tarihçesi bozulmamıştır;
eksik olan başka bir tarihçedir.

## Klon Bedelinin Toplanması

Alt tablonun sağ üç sütunu klon bedelini veriyor ve birim **dokunulan nesnedir**.

Ana depo tek başına **920** nesne. Alt modüller sırasıyla **2200**, **980** ve **440** nesne
getiriyor. Üçü de eklenince özyinelemeli klon **4540** nesneye çıkıyor — ana depo klonunun
**4,93** katı. Ana depo tarihçesi bu sırada bir işleme bile büyümedi.

En büyük katkı ilk alt modülden geliyor ve nedeni tabloda yazılı: **300** işlemelik tarihçesi
ana depodan büyük. Alt modülün boyu ana deponun boyuyla ilgisizdir; ana depo onu sabitleyen
kimliği yazarken alt modülün büyüklüğüne bakmaz. Ana deposu küçük, klon bedeli büyük bir
düzenlemenin önünde hiçbir engel yoktur.

Tablonun sağ sütunundaki kat sayısı doğrusal artmıyor: **3,39**, sonra **4,46**, sonra
**4,93**. Artış her adımda küçülüyor çünkü eklenen alt modüller giderek daha kısa. Sıra ters
olsaydı sayılar başka görünürdü ama son satır aynı kalırdı — toplam, sıradan bağımsızdır.
Kat sayısının kendisi de bir şey söylemiyor; söyleyen, alt modül tarihçelerinin toplamının
ana depo tarihçesinden **üç kattan fazla** olmasıdır. Bu oran, ana depoya bakan hiçbir
ölçümde görünmez.

Özyineleme bir katmanla da sınırlı değildir. Bir alt modülün kendi alt modülü varsa
`--recursive` seçeneği onu da getirir ve bağlı tarihçe sayısı **beşe**, gereken kimlik
sayısı **beşe** çıkar. Ölçüm bunu kurmuyor, ama düzenin kuralı değişmiyor: her katman ana
depoya **iki nesne** yazar ve arkasına kendi tarihçesinin tamamını bağlar.

Buradan iki pratik sonuç çıkar. **Birincisi:** özyinelemeli olmayan klon ana depo tarihçesini
eksiksiz getirir ve alt modüllerin **hiçbir** nesnesini getirmez; bu, tarihçeyi okumak isteyen
biri için doğru seçimdir. **İkincisi:** çalışma ağacına ihtiyacı olan biri özyinelemeli klon
yapmak zorundadır ve tabloda okunan katı öder. Aynı depoda iki ayrı bedel vardır ve hangisinin
ödendiğini kullanılan seçenek belirler.

## Kırılan Bağ ve Kurtarma

Sabitlenmiş sürüm bir kimliktir ve kimlik, işaret ettiği işleme erişilebilir olduğu sürece
geçerlidir. Alt modülün yukarı deposunda tarihçe yeniden yazılırsa — konunun ilk dersinde
ölçülen işlem — eski kimlikler artık hiçbir işlemeyi göstermez. Ana depodaki **38** ilerletme
işlemesinden kaçının kırılacağı, yeniden yazmanın hangi noktadan başladığına bağlıdır.

Bu bir veri kaybı değildir ama **ana depo tarihçesinin geçmiş noktalarını yeniden
üretilemez** hâle getirir ve kaybın kaydı ana depoda tutulmaz. Kurtarma yolu üç adımlıdır.
Alt modülün eski işlemeleri hâlâ bir yerde duruyorsa — bir kopyada, bir yedek dalda ya da
referans günlüğü penceresi kapanmamışsa — o işlemeler ayrı bir başvurudan geri getirilebilir
ve kimlikler yeniden çözülür. Duruyorsa. İkinci yol, ana depoda sabitlenmiş sürümleri yeni
kimliklere taşıyan bir düzeltme işlemesi yazmaktır; bu geçmişi kurtarmaz, yalnız ucu
onarır. Üçüncüsü ve en ucuzu, kaybı hiç doğurmamaktır: alt modül olarak bağlanan bir depoda
tarihçe yeniden yazılmadan önce, o depoyu sabitleyen ana depoların bilinmesi gerekir. Bağın
yönü tek taraflıdır — alt modül kendisini kimin sabitlediğini bilmez.

## Özet

- Alt modül, ana depoya bir tarihçe değil bir **kimlik** yazar; kayıt `.gitmodules` dosyası
  ile ağaç girdisindeki sabitlenmiş sürümden ibarettir.
- Sabitlenmiş sürümü ilerletmek ana depoda **2 nesne** yazar ve bu sayı alt modülde kaç işleme
  geçildiğinden bağımsızdır; ölçümde **76** nesne, **378** alt modül işlemesini bağlar.
- Ana depo tarihçesi **200** işleme görünür; ucundaki durumu yeniden üretmek için gereken
  işleme sayısı **578**'dir ve bu fark ana depoda yazılı değildir.
- Üç alt modülle bir işlemenin ağacını kurmak **4** ayrı tarihçeden **4** kimlik ister;
  biri erişilemezse işleme bozulmaz ama yeniden üretilemez.
- Özyinelemeli klon **920** nesneden **4540** nesneye çıkar — **4,93** kat; özyinelemesiz klon
  ana depo tarihçesini eksiksiz getirir ve alt modülden **0** nesne alır.

## Sonraki Adım

Alt modülde bedeli büyüten şey **işleme sayısıydı**: üç yüz işlemelik bir tarihçe, seksen
işlemelik olandan beş kat fazla nesne getirdi. Bu, nesne sayısının işleme sayısını izlediği
bir durumdur ve sezgiye uyar. Sonraki ders sezginin bozulduğu duruma bakar: aynı tarihçede
işlemelerin **onda birinden azı** toplam nesnenin üçte ikisinden fazlasını üretirse, tarihçeyi
ağırlaştıran şeyin ne olduğu sorusu yeniden sorulmak zorundadır — ve yanıt işleme sayısı
değildir. O durumda depoyu bölmek çare olmaz, çünkü ağırlık işlemelerin dağılımından değil
taşıdıkları nesnenin **türünden** gelir; tarihçeden çıkarılması gereken şey bir depo değil,
bir dosya sınıfıdır.
