---
title: 'Değişiklik İsteği Akışı'
source: 'https://academia.sh/tr/kurslar/dallanma-ve-isbirligi/degisiklik-istegi-akisi'
course: 'Dallanma ve İşbirliği'
language: tr
updated: '2026-08-17T18:10:45+00:00'
license: 'CC BY-SA 4.0'
---

# Değişiklik İsteği Akışı

Akışın seçtiği tümleştirme biçimi tarihçeye 5, 3, 2 ve 3 soru bırakır; üç istekte alınan 11 kararın 4'ü işleme mesajına yazılır, 7'si hiçbir biçimde tarihçeye girmez ve sıkıştırmada yazılanların da hepsi ayrı okunabilir olmaktan çıkar.

Önceki ders çatal modelinde katkıcının yukarı depoya itme yetkisi bulunmadığını ölçtü. Buna
rağmen on iki işleme bir biçimde yukarıya geçti. Geçişi yapan şey bir komut değildir: yetkisi
olmayan biri hiçbir komutla karşı tarafın dalını değiştiremez. Geçişi yapan şey bir **akıştır**
ve akışın son adımını yetkisi olan biri çalıştırır.

Bu ders akışın mekaniğini kurar: öneri nasıl sunulur, döngü nasıl döner, tümleştirme kararı
nerede verilir. **İnceleme ekseninin kendisi — bir değişikliğin anlam, gerçekleştirim, test ve
belge açısından nasıl incelendiği — ve inceleme kültürü bu dersin konusu değildir**; bunlar
Kod İnceleme ve Ekip Süreci kursunda kurulur. Burada ölçülen tek şey, akışın tarihçeye ne
bıraktığıdır.

## Akışın Döngüsü

**Değişiklik isteği (pull request)**, bir dalın başka bir dala alınması için yapılan biçimsel
öneridir. Depo platformlarının sağladığı bir sınıf yeteneğidir; ürün adı bu derste geçmez ve
akışın mekaniği ürüne bağlı değildir.

Döngü dört adımdır. **Öneri:** katkıcı dalını itki noktasına iter ve isteği açar; istek iki
uç adı taşır — kaynak dal ve hedef dal. **Tartışma:** öneri okunur, sorular sorulur, kararlar
alınır. **Düzeltme:** katkıcı dalını değiştirir ve yeniden iter; istek kendiliğinden
güncellenir, çünkü istek bir dosya kopyası değil, **iki dalın adına yapılmış bir göndermedir**.
**Tümleştirme:** yetkili biri isteği kapatır ve dalı hedefe alır.

Döngünün iki adımı arasına otomatik denetimler girebilir: öneri her itildiğinde bir hat
çalışır ve sonucu isteğe iliştirir. Hattın kendisi bu kursun konusu değildir ve Sürekli
Tümleştirme ve Teslimat kursunda kurulur; buradan görülen tek şey, denetim sonucunun da
tartışma alanında durduğu ve tarihçeye girmediğidir.

Dördüncü adımın bir seçim taşıdığı çoğu zaman gözden kaçar. Tümleştirmeyi yapan kişi, dört
tümleştirme biçiminden birini seçer ve bu seçim tarihçeye ne kalacağını belirler. Akışın
kendisi tarafsız değildir: hangi biçimin varsayılan olduğu, deponun aylar sonra hangi soruları
yanıtlayabileceğini belirler.

## Öneri Bir İletidir

İsteğin bir depo platformu olmadan da karşılığı vardır ve bu karşılık akışın ne olduğunu
doğrudan gösterir.

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

git request-pull yukari/ana https://ornek.test/katkici/olcum-aglari.git olcum

The following changes since commit a1b2c3d:
  Ana dala ölçüm dizinini ekle
are available in the Git repository at:
  https://ornek.test/katkici/olcum-aglari.git olcum
for you to fetch changes up to d4e5f6a:
  Ölçüm eşiğini yapılandırmadan oku

 olcum.py |  22 ++++++++
 ayar.py  |   6 +--
 2 files changed, 25 insertions(+), 3 deletions(-)
```

Çıktı üç şey taşıyor: ortak tabanın adı, katkının bulunduğu adres ve dal, ve dal ucunun adı.
İçerik taşımıyor. İstek bir kopya değil, **nereden getirileceğinin tarifidir**; alan taraf
getirir, inceler ve karar verir. Depo platformlarının sunduğu istek de aynı şeydir, üstüne bir
tartışma alanı eklenmiştir.

## Tartışma ve Düzeltme

Tartışmadan doğan düzeltmenin iki yolu vardır ve tarihçeye etkileri ayrıdır.

Birinci yol dala **yeni işleme eklemektir**. Düzeltme ayrı bir işleme olur, ayrı bir mesaj
taşır ve tarihçe döngünün döndüğünü kaydeder. Ölçümün "işleme mesajına yazılan karar" sütunu
bu yolu sayar.

İkinci yol dalı **yeniden yazmaktır**: düzeltme, kusuru getiren işlemenin içine sokulur ve dal
yeniden itilir. Katkı dalı yalnız katkıcıya ait olduğu için bu, paylaşılan dalda yeniden
temellendirmenin taşıdığı riski taşımaz — ama tarihçe artık düzeltmenin yapıldığını değil,
yalnız son hâli gösterir. Bu ders zorlayıcı itmenin tam biçimini yazmaz; yazılması gereken tek
şey şudur: karşı taraftaki dal ezilir ve ezilen hâl başka bir kopyada bulunmuyorsa geri
alınamaz. Katkı dalında bu bilinçli bir tercihtir, hedef dalda değildir.

İki yol arasındaki seçim bir okunaklılık–yanıtlanabilirlik ödünleşimidir ve Birleştirme
konusunun ikinci iddiasının akış içindeki karşılığıdır: temiz görünen dal, döngünün kaydını
taşımayan daldır.

## Hedef Dal İlerlerken

Tartışma sürerken hedef dal durmaz. Başka istekler tümleştirilir ve önerinin yaslandığı taban
geriler. İsteğin gösterdiği fark bu yüzden iki ayrı biçimde hesaplanabilir.

Birinci biçim, iki dal ucunu doğrudan karşılaştırır ve hedef dalda bu arada olan her şeyi de
farka katar. İkinci biçim, iki dalın **ortak tabanını** bulur ve katkı dalını yalnız o
tabandan bugüne karşılaştırır; böylece farkta yalnız katkıcının yaptığı iş görünür. Akışların
büyük bölümü ikincisini gösterir ve bu, üçüncü dersteki eskiyen taban gözleminin doğrudan
sonucudur: taban gerilemiş olsa bile öneri okunur kalır.

İkisi arasındaki seçim çakışma anında görünür hâle gelir. Ortak tabana göre temiz duran bir
öneri, hedef dalın son hâliyle çakışabilir; akış bunu ancak tümleştirmeyi denediğinde
öğrenir. Bu yüzden birçok akış, tümleştirmeden önce katkı dalının **güncel tabana taşınmasını**
ister ve bu istek döngüye fazladan bir tur ekler.

İsteğin kapanışı da tek biçimli değildir. Tümleştirilerek kapanan bir istek tarihçeye iz
bırakır; tümleştirilmeden kapanan bir istek hiçbir iz bırakmaz. İkinci durumda öneri, tartışma
ve alınan kararların tamamı yalnız akışın kendi kaydında kalır — depoda hiçbir karşılığı
yoktur. Ölçüm bu dersi yalnız kapanan ve tümleştirilen istekler üzerinden kurar; kapatılan
isteklerin kaybı tanım gereği tamdır.

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

- **UD19** — Üç dalın her biri bir değişiklik isteğidir ve dörder işleme önerir; gelişim
  kurgusu değişmez, üstüne bir akış katmanı eklenir.
- **UD20** — Tartışma turu ve alınan karar sayısı kurgudan üretilir; kâhin biziz, çünkü akışı
  biz kurduk. Kararın içeriği ölçüme girmez, yalnız **nereye yazıldığı** girer.
- **UD21** — Bir karar ancak bir işleme mesajına yazıldıysa tarihçeye girer. Tartışma alanının
  kendisi deponun dışındadır ve ölçüm onu tarihçe saymaz.
- **UD22** — Yazılmış bir karar, yazıldığı işleme tümleştirmeden sonra **ayrı okunabiliyorsa**
  okunur kalır; sıkıştırılmış bir grupta ayrı okunabilirlik yoktur.
- **UD23** — "Gönderme yeri", akışın istek numarasını yazabileceği işlemedir: birleştirme
  işlemesi ya da sıkıştırma işlemesi. Yeniden temellendirme ve ileri sarma böyle bir işleme
  üretmez.
- **UD24** — Dört tümleştirme biçiminin tanımı Birleştirme konusundaki tanımın aynısıdır ve
  burada değiştirilmez; değişen tek şey, biçimi seçenin akış olmasıdır.

## Ölçüm

```python
"""Değişiklik isteği akışı: döngüden tarihçeye ne geçiyor.

Bölüm 1 - üç istek, tartışma turu ve alınan karar.
Bölüm 2 - akışın seçtiği tümleştirme biçiminin bıraktığı soru ve karar izi.
"""
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 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))
BICIMLER = ("birlestirme islemesi", "yeniden temellendirme", "sikistirma", "ileri sarma")


def akis(kayit):
    """Her dal bir değişiklik isteği: öneri, tartışma turu ve alınan kararlar."""
    r, istekler = uretec(TOHUM + 8), []
    for dal in DALLAR:
        tur = 1 + r(3)
        kararlar = [{"dal": dal, "tur": 1 + r(tur), "mesaja_yazildi": r(3) == 0}
                    for _ in range(2 + r(3))]
        istekler.append({"dal": dal, "onerilen": sum(1 for x in kayit if x["dal"] == dal),
                         "tur": tur, "kararlar": kararlar})
    return istekler


def okunur_kalan(t, kararlar):
    """Bir karar, yazıldığı işleme ayrı okunabiliyorsa tarihçede okunur kalır."""
    ayri = {x["dal"] for x in t if not x.get("birlesme") and not x.get("sikisik")}
    return sum(1 for k in kararlar if k["mesaja_yazildi"] and k["dal"] in ayri)


def gonderme_yeri(t):
    """Akışın istek göndermesini koyabileceği işleme: birleşme ya da sıkıştırma."""
    return sum(1 for x in t if x.get("birlesme") or x.get("sikisik"))


kayit = gelisim()
istekler = akis(kayit)
kararlar = [k for i in istekler for k in i["kararlar"]]
yazilan = sum(k["mesaja_yazildi"] for k in kararlar)

print(f"değişiklik isteği {len(istekler)} | önerilen işleme "
      f"{sum(i['onerilen'] for i in istekler)} | tartışma turu "
      f"{sum(i['tur'] for i in istekler)} | alınan karar {len(kararlar)} | "
      f"işleme mesajına yazılan {yazilan}")
for i in istekler:
    print(f"  {i['dal']:7s} önerilen {i['onerilen']}  tur {i['tur']}  "
          f"karar {len(i['kararlar'])}  mesaja yazılan "
          f"{sum(k['mesaja_yazildi'] for k in i['kararlar'])}")

print()
print("akışın seçtiği biçim    işleme  yanıtlanan soru  okunur kalan karar  "
      "gönderme yeri")
for b in BICIMLER:
    t = tumlestir(kayit, b)
    print(f"  {b:22s} {len(t):6d} {sum(f(t) for _, f in SORULAR):16d}"
          f" {okunur_kalan(t, kararlar):19d} {gonderme_yeri(t):14d}")

print()
print(f"tartışmada alınan {len(kararlar)} kararın {len(kararlar) - yazilan} tanesi "
      f"hiçbir biçimde tarihçeye girmez")
```

```
değişiklik isteği 3 | önerilen işleme 12 | tartışma turu 7 | alınan karar 11 | işleme mesajına yazılan 4
  olcum   önerilen 4  tur 3  karar 3  mesaja yazılan 1
  rapor   önerilen 4  tur 3  karar 4  mesaja yazılan 1
  kimlik  önerilen 4  tur 1  karar 4  mesaja yazılan 2

akışın seçtiği biçim    işleme  yanıtlanan soru  okunur kalan karar  gönderme yeri
  birlestirme islemesi       15                5                   4              3
  yeniden temellendirme      12                3                   4              0
  sikistirma                  3                2                   0              3
  ileri sarma                12                3                   4              0

tartışmada alınan 11 kararın 7 tanesi hiçbir biçimde tarihçeye girmez
```

## Akışın Bıraktığı Soru

Tablonun ilk iki sütunu Birleştirme konusunun ölçtüğü sayıları tekrar veriyor: **15/5**,
**12/3**, **3/2**, **12/3**. Tekrar ediyorlar çünkü ölçülen şey aynı tarihçedir. Değişen tek
şey, biçimi seçenin kim olduğudur.

Bu, akışın en sessiz kararıdır. Katkıcı dalını iter, tartışma yürür, sonunda biri tümleştirir
ve o kişi çoğu zaman bir varsayılanı kabul eder. Varsayılan sıkıştırmaysa, deponun ay sonunda
yanıtlayabileceği soru sayısı **5**'ten **2**'ye iner ve bu iniş hiçbir tartışmada
konuşulmamıştır. Ölçünün buradaki katkısı bir kural değil, bir görünürlüktür: seçim
yapılıyor, ve yapılan seçimin bir sayısı var.

Akış bir şeyi de kesin olarak yapamaz. Altıncı soru — çakışmanın nerede çözüldüğü ve hangi
tarafın seçildiği — dört biçimin dördünde de yanıtsızdır. Tartışma alanında çakışmanın nasıl
çözüleceği uzun uzun konuşulmuş olabilir; tarihçe bunu kaydetmez. Akışın varlığı bu boşluğu
kapatmaz, yalnız boşluğun daha büyük görünmesini engeller.

## Kararların Nereye Gittiği

Üst satır akışın hacmini veriyor: **3** istek, **12** önerilen işleme, **7** tartışma turu ve
**11** alınan karar. Kararların **4**'ü bir işleme mesajına yazılmış, **7**'si yazılmamış.

Yazılmayan yedi karar hiçbir tümleştirme biçiminde tarihçeye girmez. Bulundukları tek yer
akışın kendi tartışma kaydıdır ve o kayıt deponun içinde değildir: klonlanan kopyaya gelmez,
getirmeyle taşınmaz, yedeklenen depoda bulunmaz. Kursun en pratik sonucu Birleştirme
konusunda çakışma kararı için yazılmıştı ve burada tam olarak tekrar ediyor — **gerekçe işleme
mesajına yazılmazsa hiçbir yerde yoktur**, ve bu kez "hiçbir yer" deponun dışında bir yerdir.

"Okunur kalan karar" sütunu ikinci kaybı gösteriyor. Yazılmış **4** karar, üç biçimde **4**
olarak kalıyor; sıkıştırmada **0**'a iniyor. Sıkıştırma yazılmış gerekçeleri silmez, onları
ayrı okunabilir olmaktan çıkarır: on iki işlemenin mesajı üç işlemenin mesajına iner ve hangi
gerekçenin hangi değişikliğe ait olduğu artık okunamaz. Doğru davranan katkıcı bile bu kayıptan
korunmuş değildir.

Son sütun ters yönde bir gözlem veriyor. Akışın istek göndermesini yazabileceği bir işleme
yalnız iki biçimde vardır: birleştirme işlemesi ve sıkıştırma işlemesi, ikisinde de **3**.
Yeniden temellendirme ve ileri sarma böyle bir işleme üretmez ve gönderme sayısı **0**'dır. Bu
biçimlerde tarihçeden akışa geri dönmenin hiçbir yolu yoktur: işleme mesajlarında istek
numarası bulunmuyorsa, aylar sonra bir işlemenin hangi tartışmadan çıktığı sorulduğunda yanıt
yoktur.

## Özet

- Değişiklik isteği bir kopya değil, iki dalın adına yapılmış bir göndermedir; katkıcı dalını
  güncellediğinde istek kendiliğinden güncellenir.
- Akışın son adımı bir tümleştirme biçimi seçer ve tarihçeye **5**, **3**, **2** ya da **3**
  soru bırakır; seçim çoğu zaman bir varsayılandır ve tartışılmaz.
- Üç istekte alınan **11** kararın **4**'ü işleme mesajına yazılır; kalan **7** hiçbir biçimde
  tarihçeye girmez ve yalnız deponun dışındaki tartışma kaydında durur.
- Sıkıştırma yazılmış **4** gerekçeyi **0**'a indirir: mesajlar silinmez, ayrı okunabilir
  olmaktan çıkar.
- Akışa geri dönmeyi sağlayan gönderme yalnız birleştirme ve sıkıştırma işlemelerine
  yazılabilir; yeniden temellendirme ve ileri sarmada böyle bir işleme yoktur ve gönderme
  sayısı **0**'dır.

## Sonraki Adım

Bu dersin akışı bir depo platformu varsaydı: ortak bir adres, bir tartışma alanı ve tümleştirme
düğmesine basacak bir yetki. Katkının bunların hiçbiri olmadan gittiği bir biçim daha vardır ve
sürüm kontrolünün en eski katkı biçimi budur: değişikliğin **dosya olarak** gönderilmesi.
Sonraki ders yamayı ölçer — hangi üstveriyi taşıdığını, hangisini taşımadığını, ve taşımadığı
alanın altı sorunun neresine düştüğünü.
