---
title: 'Birleştirme Stratejileri'
source: 'https://academia.sh/tr/kurslar/dallanma-ve-isbirligi/birlestirme-stratejileri'
course: 'Dallanma ve İşbirliği'
language: tr
updated: '2026-08-17T18:10:44+00:00'
license: 'CC BY-SA 4.0'
---

# Birleştirme Stratejileri

Dört tümleştirme biçimi aynı on iki işlemelik gelişimi ana dala alır ve tarihçeye 15, 12, 3 ve 12 işleme bırakır; yanıtladıkları soru sayısı 5, 3, 2 ve 3'tür ve en temiz tarihçe olan sıkıştırma on iki işlemenin hepsini ayrı ayrı okunamaz kılar.

Kursun ölçtüğü tümleştirme biçimlerinden üçü kuruldu: birleştirme işlemesi, ileri sarma ve
yeniden temellendirme. Aralarında kiraz toplama da ölçüldü, ama o bir tümleştirme biçimi
değil, tek bir değişikliği taşıma yoluydu.

Bu ders dördüncü biçimi — bir dalın bütün işlemelerini tek bir işlemede toplayan
sıkıştırmayı — ekler ve dördünü **yan yana** koyar. Sorulan şey artık
bir biçimin ne yaptığı değil, dördünün aynı gelişim üzerinde nasıl sıralandığıdır — ve
sıralamanın iki ölçütte **ters yönde** çıkması bu kursun ikinci iddiasıdır.

## İki Ayrı Karar, Tek Kelime

"Strateji" kelimesi burada iki ayrı şeye işaret eder ve karıştırılması sık görülür.

**Birincisi içerik stratejisidir:** araç iki tarafın dosyalarını hangi yöntemle
birleştirecek. Varsayılan yöntem birinci derste kurulan üçlü birleştirmedir; ata sürümüne
bakar, tek taraflı değişiklikleri alır, iki taraflı olanlarda karar veremez. Aracın ikiden
çok dalı tek seferde birleştiren ayrı bir yöntemi de vardır ve o yöntem çakışma çıktığında
hiçbir şey yapmadan durur. Strateji **seçenekleri** ise çakışma durumunda bir tarafı
kendiliğinden yeğlemeyi sağlar.

**İkincisi biçim kararıdır:** birleşme bittiğinde tarihçeye ne yazılacak. Kapanış işlemesi
mi, yeniden yazılmış bir zincir mi, tek bir toplu işleme mi, yoksa hiçbir şey mi.

İki karar bağımsızdır. Aynı içerik stratejisi dört ayrı biçimle sonuçlanabilir; aynı biçim
ayrı içerik stratejileriyle üretilebilir. Bu kursun ölçtüğü şey **yalnız ikincisidir**,
çünkü kod dördünde de aynıdır.

Bir uyarı ilk karar için geçerlidir. Çakışmada bir tarafı kendiliğinden yeğleyen strateji
seçeneği, ikinci dersteki bütün dosyayı bir taraftan alma kısayolunun tümleştirme
ölçeğindeki hâlidir: çakışmayı çözmez, çözülmüş sayar. Öbür tarafın o satırlardaki
değişikliği sessizce düşer ve tarihçede hiçbir belirti bırakmaz. Üretilmiş dosyalarda
yerindedir; elle yazılmış kodda değildir.

## Dördüncü Biçim: Sıkıştırma

**Sıkıştırma (squash)** dalın işlemelerini ana dala hiç almaz. Aracın yaptığı iş, dalın
toplam değişikliğini çalışma alanına uygulamak ve orada durmaktır; işlemeyi siz yazarsınız
ve tek bir işleme yazılır.

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

$ git merge --squash rapor
Squash commit -- not updating HEAD
Automatic merge went well; stopped before committing as requested

$ git commit -m "rapor: ozet satiri ve alan genisligi"
[ana 6f7a8b9] rapor: ozet satiri ve alan genisligi
 2 files changed, 37 insertions(+), 4 deletions(-)
```

İki satır önemlidir. `not updating HEAD` ifadesi, birleştirme işlemesinin **yazılmadığını**
bildirir: üretilen işlemenin tek öncülü vardır ve dala giden bir kenar yoktur. İkinci
komutun çıktısındaki dosya sayısı ise dalın dört işlemesinin toplamıdır — dört ayrı
değişiklik tek bir yamada birleşmiştir.

Bunun görülmeyen bir sonucu vardır: dalın işlemeleri ana dalın atası olmadığı için, aynı
dal daha sonra olağan yolla birleştirilirse araç onun **hiç** alınmadığını sanır ve bütün
işlemelerini yeniden getirmeye çalışır. Sıkıştırılarak alınan dal, alındıktan sonra
kapatılmalıdır.

Sıkıştırmanın seçilme gerekçesi genellikle şudur: geliştirme sırasında yazılan ara
işlemeler — yarım kalmış denemeler, kendi kendini düzelten adımlar — ana dalın günlüğünü
doldurur. Gerekçe gerçektir, ama ölçüm karşılığında ne verildiğini gösterir. Ara
işlemelerin gürültüsünü azaltmanın iki yolu vardır: onları silmek ya da onları düzgün
yazmak. Birincisi tarihçenin çözünürlüğünü de siler; ikincisi silmez. Sıkıştırma bu iki
yol arasında bir tercihtir, zorunluluk değildir.

Ölçümün varsayımları:

- **BR29** — Dört biçim aynı on iki işlemelik gelişimi ana dala alır ve **aynı kodu**
  üretir; ölçülen yalnız bıraktıkları tarihçedir.
- **BR30** — Sıkıştırma her dalın işlemelerini tek işlemede toplar: dosya alanı tek ad
  değil **ad listesi** olur, kusur alanı grubun herhangi bir işlemesinde kusur varsa doğru
  olur.
- **BR31** — "Ayrı okunabilir işleme", tarihçede tek başına duran ve bir sıkıştırmanın
  içine girmemiş işlemedir. Birleştirme işlemesinin eklediği kapanışlar bu sayıya girmez.
- **BR32** — "Kaybolan", on iki gerçek işlemeden tarihçede ayrı ayrı okunamayanların
  sayısıdır; kod olarak kaybolan hiçbir şey yoktur.
- **BR33** — Altı sorunun tanımı kursun sabitidir ve bu derste değiştirilmez; yalnız dört
  biçim için ayrı ayrı çalıştırılır.
- **BR34** — Çakışma kararı sorusu, ikinci derste ödendiği gibi dört biçimde de yanıtsızdır.
  Bu ders o sonucu değiştirmez, tabloda gösterir.
- **BR35** — Kümenin çözünürlüğü on iki işlemede **1/12**, altı soruda **1/6**.

## Ölçüm

```python
"""Dort tumlestirme bicimi yan yana: isleme sayisi ve yanitlanan soru.

Bolum 1 - dort bicim ayni on iki islemeyi ana dala alir.
Bolum 2 - alti soru dort tarihceye de sorulur.
Bolum 3 - sikistirilmis tarihcenin uc islemesi neyi tasiyor.
"""
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():
    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):
    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 s1_gruplama(t):
    return all(x.get("dal_kaydi") for x in t if not x.get("birlesme"))


def s2_kusur(t):
    kusurlu = [x for x in t if x["kusurlu"]]
    return len(kusurlu) == 1 and not kusurlu[0].get("sikisik")


def s3_sira(t):
    return all(x.get("zaman_korundu") for x in t)


def s4_dosya(t):
    return all(isinstance(x["dosya"], str) or x.get("birlesme") for x in t)


def s5_kapsam(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_cakisma(t):
    return any("secilen" in x for x in t)


SORULAR = (("özellik gruplaması", s1_gruplama), ("kusurun yalıtımı", s2_kusur),
           ("gerçek sıra", s3_sira), ("dosya izi", s4_dosya),
           ("dalın bütünlüğü", s5_kapsam), ("çakışma kararı", s6_cakisma))
BICIMLER = ("birlestirme islemesi", "yeniden temellendirme", "sikistirma",
            "ileri sarma")
kayit = gelisim()
T = {b: tumlestir(kayit, b) for b in BICIMLER}

print(f"gerçek gelişim: {len(kayit)} işleme, {len(DALLAR)} dal, kusurlu "
      f"{sum(1 for k in kayit if k['kusurlu'])}")
print("sorular:", ", ".join(f"s{i}={ad}" for i, (ad, _) in
                            enumerate(SORULAR, 1)))
print()
print(f"{'biçim':<22s} {'işleme':>6s} {'ayrı':>5s} {'kaybolan':>8s}"
      f"  {'s1 s2 s3 s4 s5 s6':<17s} {'yanıtlanan':>10s}")
for b in BICIMLER:
    ayri = sum(1 for x in T[b] if not x.get("birlesme")
               and not x.get("sikisik"))
    im = "  ".join("+" if soru(T[b]) else "-" for _, soru in SORULAR)
    print(f"{b:<22s} {len(T[b]):6d} {ayri:5d} {len(kayit) - ayri:8d}"
          f"  {im:<17s} {sum(s(T[b]) for _, s in SORULAR):10d}")
print()
print("sıkıştırılmış tarihçenin işlemeleri:")
for x in T["sikistirma"]:
    print(f"  {x['dal']:<7s} {x['sikisik']} işleme -> 1 | dosyalar "
          f"{','.join(x['dosya'])} | kusur "
          f"{'var' if x['kusurlu'] else 'yok'}")
```

```
gerçek gelişim: 12 işleme, 3 dal, kusurlu 1
sorular: s1=özellik gruplaması, s2=kusurun yalıtımı, s3=gerçek sıra, s4=dosya izi, s5=dalın bütünlüğü, s6=çakışma kararı

biçim                  işleme  ayrı kaybolan  s1 s2 s3 s4 s5 s6 yanıtlanan
birlestirme islemesi       15    12        0  +  +  +  +  +  -           5
yeniden temellendirme      12    12        0  -  +  -  +  +  -           3
sikistirma                  3     0       12  +  -  -  -  +  -           2
ileri sarma                12    12        0  -  +  +  +  -  -           3

sıkıştırılmış tarihçenin işlemeleri:
  olcum   4 işleme -> 1 | dosyalar ayar.py,olcum.py | kusur yok
  rapor   4 işleme -> 1 | dosyalar ayar.py,rapor.py | kusur var
  kimlik  4 işleme -> 1 | dosyalar kimlik.py | kusur yok
```

## Okunaklılık ile Yanıtlanabilirlik

İşleme sütunu dört biçimi şöyle sıralıyor: **15**, **12**, **3**, **12**. En kısa tarihçe
sıkıştırmanındır — üç dal, üç işleme. En uzunu birleştirme işlemesinindir; on iki işlemenin
üstüne üç kapanış eklenmiştir. Okunaklılık ölçüsü buysa sıralama nettir: sıkıştırma önde,
birleştirme işlemesi sonda.

Yanıtlanan soru sütunu tam tersini veriyor: **5**, **3**, **2**, **3**. En kısa tarihçe en
az soruyu, en uzun tarihçe en çok soruyu yanıtlıyor. İki ölçüt **ters yönde hareket
ediyor** ve bu kursun ikinci iddiası budur.

Kayıp sütunu nedeni gösteriyor. Üç biçimde kaybolan işleme **0**'dır: on iki işlemenin
hepsi tarihçede ayrı ayrı durur, yalnız dizilişleri ayrıdır. Sıkıştırmada kaybolan **12**,
ayrı okunabilir işleme **0**'dır. Bu, tarihçenin on ikide birlik çözünürlüğünü tamamen
bıraktığı anlamına gelir: artık en küçük okunabilir birim bir işleme değil, bir dalın
tamamıdır.

Alt döküm bu kaybın somut hâlini veriyor. `rapor` dalının dört işlemesi tek bir işlemeye
inmiş; o işleme `ayar.py` ile `rapor.py` dosyalarına dokunuyor ve kusur taşıyor. Kusurun
**var** olduğu okunabiliyor, hangi adımdan geldiği okunamıyor. Aynı biçimde dosya izi de
düşüyor: bir işlemenin iki dosyaya birden dokunduğu görülüyor ama `ayar.py` dosyasına
dokunan işlemeyi tek başına bulmak artık olanaksız.

Sıkıştırmanın yanıtladığı **2** soru da öğreticidir: **özellik gruplaması** ve **dalın
bütünlüğü**. İkisi de sıkıştırmanın yapısı gereği yanıtlanır — her işleme zaten bir işin
tamamıdır, dolayısıyla gruplama kusursuz ve bütünlük tanım gereği sağlanmıştır. Sıkıştırma
kaba soruları en iyi yanıtlayan biçimdir; ince soruların hiçbirini yanıtlayamaz.

Takasın iki tarafı eşit ağırlıkta değildir ve bunu görmek seçimi kolaylaştırır. **15**
işlemelik tarihçenin fazlalığı bir **okuma** maliyetidir: günlük çıktısı uzundur. Okuma
maliyeti sonradan azaltılabilir — tarihçeyi süzen, tek çizgiye indirgeyen, tarihe ya da
dosyaya göre daraltan okuma yolları vardır ve hepsi aynı kayıt üzerinde çalışır.
Sıkıştırmanın **12** işlemelik kaybı ise bir **kayıt** kaybıdır ve sonradan geri
getirilemez; hiçbir okuma seçeneği yazılmamış bir işlemeyi gösteremez. Bir taraf
süzülebilir, öbür taraf üretilemez.

Buradan çıkan cümle şudur: **tarihçeyi temizlemek onu ucuzlatmaz, bilgi siler.** Silinen
bilgi kod değildir — dördü de aynı kodu üretir. Silinen, koda **nasıl** varıldığıdır.

## Ölçüte Dayalı Seçim

Dört biçim arasında doğru olan yoktur; sorulacak soruya uygun olan vardır. Ölçüt tek bir
sorudur: **bu tarihçeye aylar sonra ne sorulacak?** Soru bilinmiyorsa varsayılan, en çok
soruyu yanıtlayan biçimdir — çünkü fazladan kayıt sonradan yok sayılabilir, eksik kayıt
sonradan yazılamaz.

**Kusur avı sorulacaksa** kusurun yalıtımı ve dosya izi gerekir. Bunları üç biçim
yanıtlar, sıkıştırma yanıtlamaz. Kusuru ikili aramayla bulan araçlar da aynı çözünürlüğe
dayanır: on iki işlemelik bir aralıkta arama dört adımda biter, üç işlemelik bir aralıkta
iki adımda biter ama bulduğu şey dört değişikliği birden içerir.

**İşin kapsamı sorulacaksa** özellik gruplaması gerekir. Bunu yalnız birleştirme işlemesi
ve sıkıştırma yanıtlar; ikisi de dal kaydını bir biçimde yazar. Yeniden temellendirme ile
ileri sarma bu soruda eşit biçimde sessizdir.

**Zaman sorulacaksa** gerçek sıra gerekir ve bunu yalnız iki biçim yanıtlar: birleştirme
işlemesi ve ileri sarma. Yeniden temellendirme ile sıkıştırma çizgiyi işe göre dizdiği
için zamanı bırakır.

Seçim biçimlerden birine bağlanmak zorunda da değildir. Dal türüne göre ayrı biçim
kullanmak tutarlı bir kuraldır: tek işlemelik düzeltmeler ileri sarmayla alınır, çünkü
orada dal kaydının sonradan sorulması beklenmez; birden çok işlemelik özellik dalları
birleştirme işlemesiyle alınır, çünkü orada iş kapsamı sorulacaktır; dışarıdan gelen ve
ara işlemeleri denetlenmemiş katkılar sıkıştırılarak alınabilir. Kuralın kendisi yazılı
olmalıdır — biçim kararı her seferinde birleştirmeyi yapan kişinin o günkü tercihine
kalırsa tarihçe dört ayrı çözünürlüğün karışımı olur ve hiçbir soruya tutarlı yanıt
vermez.

Aracın bu kararı yerinde tutan ayarları da vardır. Birinci derste geçen ileri sarma
kilitleri bunun en dar hâlidir: bir depo, ileri sarma dışında bir birleşmeyi ya da tersine
ileri sarmayı kendiliğinden reddedecek biçimde ayarlanabilir. Ayar kuralın yerine geçmez,
kuralın unutulmasını engeller.

Fark aralığı **2/6** ile **5/6** arasındadır; kümenin çözünürlüğü **1/6** olduğuna göre
uçlar arasındaki **3/6**'lık fark ölçüm bandının üç katıdır ve rahatça savunulur. Bedel
sütunu ise **3/12**'dir: birleştirme işlemesinin en çok soruyu yanıtlamak için ödediği
şey, on iki işlemeye eklenen üç kapanıştır.

## Özet

- Aracın içerik stratejisi ile tümleştirme biçimi ayrı kararlardır; birincisi dosyaların
  nasıl birleştiğini, ikincisi tarihçeye ne yazıldığını belirler ve bu kurs ikincisini
  ölçer.
- Sıkıştırma dalın işlemelerini ana dala hiç almaz, tek öncüllü tek bir işleme yazar;
  dalın işlemeleri ana dalın atası olmadığı için o dal sonradan yeniden birleştirilmemeli,
  kapatılmalıdır.
- Dört biçim tarihçeye **15**, **12**, **3** ve **12** işleme bırakır; yanıtladıkları soru
  sayısı sırasıyla **5**, **3**, **2** ve **3**'tür.
- Sıkıştırmada kaybolan işleme **12**, ayrı okunabilir işleme **0**'dır; kusurun **var**
  olduğu okunur, hangi adımdan geldiği okunmaz. Tarihçeyi temizlemek bilgi siler.
- Uzun tarihçenin fazlalığı bir okuma maliyetidir ve süzülerek azaltılabilir; sıkıştırmanın
  kaybı bir kayıt kaybıdır ve hiçbir okuma seçeneğiyle geri getirilemez.
- Seçim ölçütü tek sorudur: bu tarihçeye sonradan ne sorulacak. Kusur avı için üç biçim,
  işin kapsamı için iki biçim, gerçek zaman için iki biçim yeterlidir; kural dal türüne
  göre ayrılabilir ama yazılı olmalıdır.

## Sonraki Adım

Bu derste biçim seçimi tek bir birleşme için yapıldı: şu dal ana dala nasıl alınsın.
Ekipler bu kararı her seferinde yeniden vermez; bir kez verip **kural** hâline getirir ve
kural yalnız birleşme anını değil, dalların ne kadar yaşayacağını, kaç tane olacağını ve
ne sıklıkla ana dala döneceğini de belirler. Sonraki ders bu kuralları — uzun ömürlü ve
kısa ömürlü dal düzenlerini — tarihçeye ne bıraktıklarına göre karşılaştırır.
