---
title: 'Çoklu Çalışma Ağacı'
source: 'https://academia.sh/tr/kurslar/ileri-git/coklu-calisma-agaci'
course: 'İleri Git'
language: tr
updated: '2026-08-17T18:10:42+00:00'
license: 'CC BY-SA 4.0'
---

# Çoklu Çalışma Ağacı

Ek çalışma ağacı nesne deposunu paylaşır ve 0 nesne kopyalar: bin işlemelik tarihçede dört dal için klon düzeni 22560 nesne yazarken ağaç düzeni 5640'ta kalır, kazanılan 16920 nesnenin 11466'sı ikilidir.

Önceki ders klon bedelini üçte bire indirdi ama bedeli ortadan kaldırmadı: tabloda hâlâ
**klon** yazıyordu ve klon her yapıldığında yeniden ödeniyordu. Bu, bir varsayımı da
beraberinde taşır — aynı depoda iki dal üzerinde birlikte çalışmak için ikinci bir kopya
gerektiği varsayımını.

Varsayım doğru değildir. Deponun iki bileşeni vardır ve ayrı ayrı çoğaltılabilirler: bir
**nesne deposu** ve bir **çalışma ağacı**. Klon ikisini birden kopyalar. Bu dersin sorusu
şudur: nesne deposu tek bırakılıp çalışma ağacı çoğaltılırsa, dal başına klonla
karşılaştırıldığında kaç nesne kopyalanmamış olur?

## Bir Nesne Deposu, Birden Çok Ağaç

**Çalışma ağacı (worktree)**, deponun bir işlemesinin dosya sistemine yazılmış hâlidir.
**Çoklu çalışma ağacı**, aynı nesne deposuna bağlı birden çok çalışma ağacı kurmayı
sağlayan düzendir. Ek ağaç bir dizin olarak açılır, içine deponun dizini değil ana depoyu
gösteren küçük bir dosya konur ve ağaç o andan itibaren nesnelerini ana depodan okur.

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

git worktree add ../agac-rapor rapor
git worktree add --detach ../agac-inceleme <işleme-kimliği>
git worktree list
git worktree remove ../agac-rapor
git worktree prune
```

`add` yeni dizini açar ve verilen dalı orada çıkarır. `--detach` bir dalı değil doğrudan bir
işlemeyi çıkarır; ağaç ayrık HEAD durumunda durur ve bu, geçici bir inceleme için istenen
durumdur. `list` bütün ağaçları ve her birinin hangi dalda olduğunu bildirir. `remove` ağacı
kaldırır, `prune` ise dizini elle silinmiş ağaçların yönetim kaydını temizler.

Bir kısıt baştan bilinmelidir: **bir dal aynı anda yalnız bir ağaçta çıkarılabilir.** Aynı
dalı ikinci bir ağaçta çıkarmaya çalışmak reddedilir. Kısıt keyfî değildir — iki ağaç aynı
dala işleme yazsaydı, dalın hangi ucu gösterdiği ağaca göre değişirdi ve başvuru tekliğini
kaybederdi.

## Neyin Paylaşıldığı

Ayrım tek cümleyle kurulur: **tarihçeye ait olan paylaşılır, çalışmaya ait olan ağaca
özeldir.**

Paylaşılan taraf nesne deposu ve başvurulardır. Bir ağaçta yazılan işleme nesne olarak
deponun içine düşer ve o andan itibaren öbür ağaçlardan **erişilebilir** — hiçbir aktarım
gerekmez. Dallar, etiketler ve referans günlüğü de ortaktır.

Ağaca özel taraf çalışma durumudur: `HEAD` başvurusu, hazırlık alanı ve çalışma alanındaki
dosyalar. Her ağaç kendi `HEAD`'ini tutar, dolayısıyla ayrı bir dalda durabilir; her ağaç
kendi hazırlık alanını tutar, dolayısıyla birinde hazırlanmış bir değişiklik öbüründe
görünmez. Kaydedilmemiş bir değişiklik ağacın içinde kalır ve paylaşılmaz.

Yapılandırma ikisinin arasında durur. Deponun yapılandırma dosyası ortaktır ve bir ağaçta
yapılan değişiklik hepsini etkiler; bir ayarı yalnız bir ağaca özel kılmak ayrıca
açılması gereken bir seçenektir. Depo öznitelikleri de ortaktır — sonraki dersin konusu olan
o dosya işlenen bir dosyadır ve tarihçeye aittir, dolayısıyla bütün ağaçlarda aynı kuralı
uygular.

Bu ayrım ölçümün kurgusunu doğrudan verir: ek bir ağaç **nesne kopyalamaz**, yalnız
yönetim kaydı yazar ve çalışma alanına dosyaları çıkarır. Klon ise nesne deposunun tamamını
kopyalar.

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

- **BD14** — Ölçüm ortak kurgunun dört ölçeğini kullanır. Aynı iş, aynı sayıda dal üzerinde,
  iki ayrı düzende yapılır; üretilen işleme ve nesne kümesi ikisinde de aynıdır.
- **BD15** — Klon düzeninde her dal için ayrı bir klon açılır ve her klon nesne deposunun
  **tamamını** kopyalar; kısmi klon ve sığ klon bu ölçümde kullanılmaz.
- **BD16** — Ağaç düzeninde nesne deposu tektir; ek ağaç **0 nesne** kopyalar. Yazdığı tek
  şey ağaç başına **3** yönetim kaydıdır ve bu kayıtlar nesne değildir, ayrı sayılır.
- **BD17** — Çalışma alanına çıkarılan dosyalar iki düzende de aynıdır; dört dal her iki
  düzende de dört dosya kümesi materyalize eder. Bu yüzden ölçüm dışıdır.
- **BD18** — "Kopyalanmayan ikili", kazanılan nesnenin ikili gövdelerden gelen payıdır;
  önceki dersin nesne türü ayrımıyla aynı sayımdır.
- **BD19** — Birinci ve ikinci bölümün birimi **dokunulan nesnedir**. Üçüncü bölümün birimi
  **adımdır** ve bir adım, bir dalın ucunu bir kopyadan öbürüne taşıyan tek bir getirmedir.

## Ölçüm

```python
"""Coklu calisma agaci: nesne paylasiminin dal basina klona gore kazandirdigi.

Bolum 1 - dort agac, dort olcekte: klon duzeni ve agac duzeni nesnesi.
Bolum 2 - agac sayisi buyurken kazanc (1000 islemelik tarihce).
Bolum 3 - bir agacta yazilan islemeye obur agactan erisim: birim adim.
"""
TOHUM = 20260814
DOSYALAR = ("olcum.py", "rapor.py", "kimlik.py", "ayar.py", "belge.md")
OLCEKLER = (50, 200, 1000, 4000)
AGACLAR = (1, 2, 4, 8)
YONETIM_KAYDI = 3   # ek agac basina yazilan yonetim kaydi; nesne kopyalamaz


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 klon_duzeni(t, agac):
    """Dal basina klon: her dal kendi nesne deposunu kopyalar."""
    return agac * klon_bedeli(t)


def agac_duzeni(t, agac):
    """Coklu calisma agaci: tek nesne deposu, ek agaclar nesne kopyalamaz."""
    return klon_bedeli(t)


def erisim_adimi(agac, duzen):
    """Bir agacta yazilan islemeye obur agaclardan erisim: getirme adimi."""
    return 0 if duzen == "agac" else agac - 1


print("isleme  klon nesnesi  4 klon nesnesi  4 agac nesnesi  kazanilan nesne"
      "  kopyalanmayan ikili")
for n in OLCEKLER:
    t = tarihce(n)
    k, a = klon_duzeni(t, 4), agac_duzeni(t, 4)
    ikili = 3 * (klon_bedeli(t) - klon_bedeli(t, False))
    print(f"{n:6d} {klon_bedeli(t):13d} {k:15d} {a:15d} {k - a:16d} {ikili:20d}")
print()
t = tarihce(1000)
print("agac  klon duzeni nesne  agac duzeni nesne  kazanilan nesne  ek agac basina nesne"
      "  yonetim kaydi")
for agac in AGACLAR:
    k, a = klon_duzeni(t, agac), agac_duzeni(t, agac)
    ek = (k - klon_bedeli(t)) // (agac - 1) if agac > 1 else 0
    print(f"{agac:4d} {k:18d} {a:18d} {k - a:16d} {ek:21d} "
          f"{(agac - 1) * YONETIM_KAYDI:14d}")
print()
print("agac  klon duzeninde getirme adimi  agac duzeninde getirme adimi")
for agac in AGACLAR:
    print(f"{agac:4d} {erisim_adimi(agac, 'klon'):29d} "
          f"{erisim_adimi(agac, 'agac'):29d}")
print()
print(f"tek nesne deposu {klon_bedeli(t)} nesne; dort agac ayni depoyu paylasiyor, "
      f"ek agaclarin kopyaladigi nesne {agac_duzeni(t, 4) - klon_bedeli(t)}")
print(f"ayni is dort klonla yapilsaydi kopyalanan nesne "
      f"{klon_duzeni(t, 4) - klon_bedeli(t)}")
```

```
isleme  klon nesnesi  4 klon nesnesi  4 agac nesnesi  kazanilan nesne  kopyalanmayan ikili
    50           380            1520             380             1140                  882
   200           920            3680             920             2760                 1638
  1000          5640           22560            5640            16920                11466
  4000         22600           90400           22600            67800                45990

agac  klon duzeni nesne  agac duzeni nesne  kazanilan nesne  ek agac basina nesne  yonetim kaydi
   1               5640               5640                0                     0              0
   2              11280               5640             5640                  5640              3
   4              22560               5640            16920                  5640              9
   8              45120               5640            39480                  5640             21

agac  klon duzeninde getirme adimi  agac duzeninde getirme adimi
   1                             0                             0
   2                             1                             0
   4                             3                             0
   8                             7                             0

tek nesne deposu 5640 nesne; dort agac ayni depoyu paylasiyor, ek agaclarin kopyaladigi nesne 0
ayni is dort klonla yapilsaydi kopyalanan nesne 16920
```

## Paylaşımın Kazandırdığı

Birinci tablonun birimi **dokunulan nesnedir**. Bin işlemelik tarihçede dört dal üzerinde
çalışmak, klon düzeninde **22560** nesne yazdırıyor; ağaç düzeninde toplam **5640**'ta
kalıyor. Kazanılan nesne **16920** — üç klonun tamamı. Dört bin işlemede aynı hesap **67800**
nesne veriyor.

Kazancın nereden geldiği son sütunda yazılı. Bin işlemede kazanılan **16920** nesnenin
**11466**'sı ikili gövdelerden geliyor; önceki dersin **0,6777**'lik payı buraya da aynen
düşüyor. Bir depoda ikili varlık ne kadar çoksa, ikinci bir klon açmanın bedeli o kadar
büyüktür — ve o bedelin tamamı, paylaşılan bir nesne deposuyla **hiç ödenmez**.

Küçük ölçeklerde de örüntü aynı ama büyüklükler yanıltıcı olabilir. Elli işlemelik tarihçede
kazanç **1140** nesnedir; bu, dört bin işlemedeki **67800**'ün yanında küçük görünür ama iki
düzen arasındaki oran her satırda birebir aynıdır. Kazanç doğrudan `(ağaç − 1) × klon`
çarpımıdır; ölçek yalnız çarpanı büyütür, ilişkiyi değiştirmez. Bu ölçekte ölçülebilen en
küçük fark **1/50**'dir ve tablodaki hiçbir sayı o çözünürlüğün altında bir iddiaya
dayanmıyor.

İkinci tablo aynı şeyi ağaç sayısıyla veriyor ve orta sütun sabit kalıyor: iki ağaç, dört
ağaç, sekiz ağaç — hepsinde **5640**. Ek ağaç başına kopyalanan nesne her satırda **0**'dır;
sağdaki **5640**, klon düzeninin ek kopya başına ödediğidir. Ağaç düzeninde ödenen tek şey
sağ sondaki yönetim kaydıdır: sekiz ağaç için **21** kayıt. Bunlar nesne değildir ve
tarihçeye girmezler.

Buradan çıkan ölçüt tek cümledir: **çalışma ağacı sayısı nesne deposunu büyütmez.** Klon
düzeninde bedel ağaç sayısıyla doğrusal büyür, ağaç düzeninde sabittir. Bu, kursta ölçülen
bedeller arasında ölçekten **tamamen** bağımsız olan tek örüntüdür: ikili arama ölçekle yavaş
büyüyordu, yeniden yazma oranı sabitti ama toplamı büyüyordu; burada ek kopyanın nesne bedeli
her ölçekte ve her ağaç sayısında **sıfırdır**.

## Görünürlük ve Getirme Adımı

Üçüncü tablonun birimi **adımdır** ve ölçtüğü şey nesne değil, erişimdir.

Klon düzeninde bir dala yazılan işleme, o klonun nesne deposunda durur. Öbür kopyaların ona
erişmesi için bir getirme gerekir; dört kopyalı bir düzende bir işlemenin hepsine ulaşması
**3** adımdır, sekiz kopyalıda **7**. Ağaç düzeninde bu sayı her satırda **0**'dır — işleme
zaten ortak nesne deposundadır ve öbür ağaç onu yazıldığı anda görür.

Bu, düzenin nesne sayısından bağımsız ikinci kazancıdır ve pratikte daha çok fark eder. Bir
ağaçta bir düzeltme yazılıp öbür ağaçta hemen sınanabilir; kiraz toplama, karşılaştırma ve
birleştirme işlemleri ağaçlar arasında **ağa çıkmadan** yapılır. Klon düzeninde aynı işler bir
uzak depo turu ister.

Sınır da aynı yerden gelir. Ortak nesne deposu, ortak bir hata yüzeyi demektir: bir ağaçta
yapılan çöp toplama bütün ağaçları ilgilendirir ve bir ağaçta bozulan depo hepsini birden
etkiler. Klon düzeninde kopyalar birbirinden yalıtılmıştır ve bu yalıtım, ödenen **16920**
nesnenin karşılığında alınan tek şeydir.

## Üçüncü Düzen: Tek Ağaçta Geçiş

Ölçüm iki düzeni karşılaştırdı ama pratikte en yaygın olanı üçüncüsüdür: tek çalışma ağacı ve
dallar arasında geçiş. Bu düzen **0** ek nesne kopyalar — ağaç düzeniyle aynı — ve **0**
getirme adımı ister. Nesne birimiyle bakıldığında en ucuz düzendir.

Ödediği bedel başka bir yerdedir. Her geçiş çalışma alanındaki dosyaları yeniden yazar;
kaydedilmemiş bir değişiklik varsa geçiş ya engellenir ya da değişiklik taşınır. Dallanma ve
İşbirliği kursunda bu durum tek tek sayılmıştı: hangi değişikliğin taşındığı, hangisinin
engellendiği ve hangisinin geride kaldığı orada ölçüldü, burada tekrarlanmıyor. Zula, bu
engeli aşmanın standart yoludur — kaydedilmemiş değişikliği bir kenara alır ve geçişten sonra
geri açar.

Çoklu çalışma ağacının çözdüğü şey tam olarak budur: **geçiş yoktur.** İki dal aynı anda,
iki ayrı dizinde açıktır; birinde bir sınama sürerken öbüründe düzenleme yapılabilir. Zula
gerekmez, çünkü kaydedilmemiş değişikliğin yerini bırakması gerekmez.

Buna karşılık her ağaç kendi çalışma durumunu materyalize eder ve bu yalnız dosyalarla
sınırlı değildir. Bağımlılık dizinleri, derleme çıktıları ve önbellekler ağaç başına yeniden
oluşur; bunlar tarihçeye ait olmadıkları için ölçümün dışındadır ama diskte gerçekten yer
kaplarlar ve dört ağaçlı bir düzende dört kez üretilirler. Nesne birimiyle kazanılan
**16920**, bu maliyeti kapsamaz. İki düzen arasındaki seçim bu yüzden tek sayıdan çıkmaz:
ölçülen nesne kazancı gerçek ve büyüktür, ölçülmeyen çalışma durumu ise ağaç sayısıyla
büyür.

## Ağacın Kaldırılması ve Kurtarma

Bir çalışma ağacı silindiğinde nesneler silinmez — nesneler ağaca ait değildi. Kaybolabilecek
tek şey **o ağaçta kaydedilmemiş** olandır: çalışma alanındaki değişiklikler ve hazırlık
alanının içeriği. `remove` komutu ağaçta kaydedilmemiş değişiklik varsa reddeder; dizinin
elle silinmesi hiçbir şey sormaz. Bu iki yol arasındaki fark, uyarının olup olmamasıdır.

İkinci kayıp yolu daha sessizdir. Ayrık HEAD durumundaki bir ağaçta yazılan işleme hiçbir dala
bağlı değildir; ağaç kaldırıldığında o işleme erişilemez hâle gelir ve çöp toplama penceresi
kapandığında düşer. **Kurtarma yolu:** referans günlüğü ortaktır, dolayısıyla işlemenin ucu
pencere kapanmadan başka bir ağaçtan okunabilir ve bir dala bağlanabilir. Daha ucuz yolu, o
ağacı `--detach` ile değil bir dal adıyla açmaktır — dal bir başvurudur ve başvuru, ağacın
ömründen bağımsızdır.

Çıkarılabilir bir ortamda ya da geçici olarak bağlanan bir dizinde duran ağaç için ayrı bir
önlem vardır: ağaç **kilitlenir**. Kilitli bir ağacın yönetim kaydı, dizin erişilemez olduğunda
bile temizlenmez; aksi hâlde temizleme işlemi ağacı yok sayar ve o ağaçtaki dal başka bir yerde
çıkarılabilir hâle gelir. Kilit, kaybı değil **yanlış tanıyı** önler.

Üçüncüsü yönetim kaydının kendisidir: dizini elle silinmiş bir ağacın kaydı depoda kalır ve o
dalı başka bir ağaçta çıkarmayı engellemeye devam eder. `prune` bu kayıtları temizler ve
hiçbir nesneye dokunmaz.

## Özet

- Depo iki bileşendir: **nesne deposu** ve **çalışma ağacı**. Klon ikisini birden kopyalar;
  çoklu çalışma ağacı yalnız ikincisini çoğaltır.
- Nesne deposu, dallar, etiketler ve referans günlüğü paylaşılır; `HEAD`, hazırlık alanı ve
  çalışma alanı ağaca özeldir. Bir dal aynı anda yalnız bir ağaçta çıkarılabilir.
- Bin işlemelik tarihçede dört dal için klon düzeni **22560** nesne yazar, ağaç düzeni
  **5640**'ta kalır; kazanılan **16920** nesnenin **11466**'sı ikili gövdelerden gelir.
- Ek ağaç başına kopyalanan nesne her ölçekte **0**'dır; ağaç düzeninde ödenen tek şey ağaç
  başına **3** yönetim kaydıdır ve nesne deposu ağaç sayısıyla büyümez.
- Adım biriminde: bir işlemenin bütün kopyalara ulaşması klon düzeninde **3** ve **7** getirme
  ister, ağaç düzeninde **0**; karşılığında kaybedilen şey kopyalar arasındaki yalıtımdır.

## Sonraki Adım

Ölçüm bir varsayımı ölçüm dışı bıraktı: çalışma alanına çıkarılan dosyaların iki düzende de
aynı olduğu varsayımını. Bu, dosyaların **nasıl** yazıldığının bir tercih olmadığını
söylüyordu — oysa çıkarma sırasında dosyaya uygulanan bir dönüşüm katmanı vardır ve nesne
deposundaki damla ile çalışma alanındaki dosya birbirinin aynısı olmak zorunda değildir.
Sonraki ders bu katmanı ölçer: satır sonu dönüşümü ayarlanmadığında hangi işleme, hangi
dosyada, gerçekten hiçbir şey değiştirmediği hâlde yeni bir nesne yazar?
