---
title: 'Ayrık HEAD Durumu'
source: 'https://academia.sh/tr/kurslar/dallanma-ve-isbirligi/ayrik-head-durumu'
course: 'Dallanma ve İşbirliği'
language: tr
updated: '2026-08-17T18:10:43+00:00'
license: 'CC BY-SA 4.0'
---

# Ayrık HEAD Durumu

Ayrık HEAD üstünde yapılan iki işleme hiçbir başvurudan erişilemediğinde tarihçe 15 kayıttan 13'e iner ve altı sorunun 5'i yerine 4'ünü yanıtlar; asıl bedel üç sayım sorgusunun üçünün de eksik yanıtlanması ve tarihçenin bunu bildirmemesidir.

Önceki üç ders `HEAD` ile işleme arasında üç halkalı bir zincir kurdu: `HEAD` bir dal adını,
dal adı bir işleme kimliğini, işleme kendi öncülünü gösterir. Bir dalda çalışmak bu zincirin
tam olmasına dayanır — işleme yapıldığında orta halka ilerler, `HEAD` yerinde kalır ve yeni
işleme bir ada bağlanmış olur.

Orta halka her zaman yerinde değildir. Araç `HEAD`in doğrudan bir işleme kimliğini
gösterdiği bir durum tanır ve buna **ayrık HEAD (detached HEAD)** denir. Bu ders o durumun
nasıl oluştuğunu, orada yapılan işlemenin nereye bağlandığını ve zincirin bir halkası eksik
kaldığında tarihçenin ne kaybettiğini ölçer. Ölçümün asıl sonucu kayıp miktarı değildir;
tarihçenin kaybettiğini **bilmemesidir**.

## HEAD Nasıl Ayrılır

Ayrık durum bir kusur ya da bozulma değildir; aracın belirli bir isteği karşılama biçimidir.
İstek şudur: bir dalın ucunda değil, tarihçenin belirli bir noktasında durmak. Bir işleme
kimliğine, bir etikete ya da bir uzak dal ucuna geçildiğinde `HEAD` bir ada bağlanamaz,
çünkü hedef bir ad değildir.

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

$ git switch --detach 7c3f9d2
HEAD is now at 7c3f9d2 rapor başlığını biçimlendir
$ git status --short --branch
## HEAD (no branch)
$ git symbolic-ref HEAD
fatal: ref HEAD is not a symbolic ref
```

Son satır durumun tanımıdır. İlk derste aynı komut `refs/heads/ana` yanıtını veriyordu:
`HEAD` bir başvuruyu gösteriyordu. Burada gösterecek bir başvuru yok, bu yüzden komut
simgesel bir başvuru bulamıyor. `git status` de aynı şeyi başka sözcüklerle söylüyor.

Durum kasten seçilebilir. Bir hatanın hangi işlemede girdiğini ararken tarihçede ileri geri
gezinmek, eski bir sürümü derleyip sınamak, bir etiketin gösterdiği ağacı incelemek — hepsi
ayrık durumda yapılır ve hiçbiri sorun değildir. Sorun, ayrık durumda **işleme yapmakla**
başlar.

## Ayrık Durumda Yapılan İşleme

Ayrık durumda işleme yapmak engellenmez. İşleme nesnesi yazılır, öncülü doğru bağlanır,
ağacı kaydedilir; içerik bakımından öteki işlemelerden hiçbir farkı yoktur. Değişen tek şey
kimin ilerlediğidir: `HEAD` yeni kimliği doğrudan gösterir ve **hiçbir dal başvurusu
yazılmaz**.

Bunun sonucu ikinci işlemede henüz görünmez, çünkü `HEAD` zinciri hâlâ o işlemeleri tutar.
Sonuç, başka bir dala geçildiği anda doğar. `HEAD` artık başka bir dalı gösterir ve ayrık
durumda yazılan işlemelere hiçbir başvurudan erişilemez. Araç bunu geçiş sırasında bildirir.

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

$ git switch rapor
Warning: you are leaving 2 commits behind, not connected to
any of your branches:

  b71c05e rapor: eşik tablosunu ayara taşı
  a04e9d2 rapor: özet satırını ekle

If you want to keep them by creating a new branch, this may be a good time
to do so with:

 git branch <new-branch-name> b71c05e

Switched to branch 'rapor'
```

Uyarı hem sayıyı hem kimliği veriyor ve çözümü de söylüyor: bir dal yazın. Birinci dersin
ölçüsü bu önerinin bedelini vermişti — bir dal başvurusu **41 bayttır**. İki işlemeyi
tarihçeye bağlamak kırk bir bayt yazmaktır ve bu yüzden çıkış yolu ucuzdur.

Ayrık durumdan çıkmanın üç yolu vardır. `git switch -c ad` bulunduğunuz noktaya bir dal
yazar ve ona geçer; bu, çalışmayı yerinde kurtaran yoldur. `git switch <dal>` bir dala döner
ve ayrık işlemeleri geride bırakır. Üçüncüsü geriye dönüktür: `git branch ad <kimlik>` ile
sonradan da bir başvuru yazılabilir — yeter ki kimlik hâlâ bilinsin.

## Referans Günlüğü

Kimliği bilmenin yolu **referans günlüğüdür (reflog)**. Araç `HEAD`in ve her dal
başvurusunun aldığı **her değeri** yerel bir günlüğe yazar: hangi işlemeye geçildi, hangi
işleme yapıldı, hangi başvuru nereye kaydı. Günlük yereldir ve depoyla birlikte
taşınmaz — kopyalanan bir depo kaynak deponun referans günlüğünü almaz.

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

$ git reflog
b71c05e HEAD@{0}: commit: rapor: eşik tablosunu ayara taşı
a04e9d2 HEAD@{1}: commit: rapor: özet satırını ekle
7c3f9d2 HEAD@{2}: checkout: moving from rapor to 7c3f9d2

$ git branch kurtarma b71c05e
$ git branch --contains b71c05e
  kurtarma
```

`HEAD@{0}` sözdizimi `HEAD`in bir önceki konumlarını adlandırır ve bir işleme kimliği
beklenen her yerde kullanılabilir. Üçüncü satır ayrılmanın kendisini kaydediyor; ilk iki
satır ayrık durumda yapılan iki işlemeyi. Dal yazıldıktan sonra son komut işlemenin artık
bir başvurudan erişilebildiğini doğruluyor.

Referans günlüğünün kendisi bir başvuru değildir ve erişilebilirlik hesabına girmez. Bir
kurtarma aracıdır, bir saklama düzeneği değil: girdilerin ömrü sınırlıdır ve
yapılandırılabilir bir süre sonunda düşerler; erişilemeyen işlemelere ait girdilerin ömrü
ötekilerden kısadır.

## Kurtarılamayan Sınır

Referans günlüğü girdisi düştükten sonra erişilemeyen bir işlemenin kimliğini verecek bir
kayıt kalmaz. Nesne hâlâ veritabanındadır, ama adı yoktur ve aranacak bir yeri de yoktur.

Bir adım sonrası kalıcıdır. Araç, hiçbir başvurudan erişilemeyen nesneleri toplayan bir
bakım komutu taşır; bu komutun budama seçeneği erişilemeyen nesneleri **veritabanından
siler**. Bu ders o çağrıyı çalıştırılabilir biçimde yazmaz, çünkü sonucu **geri alınamaz**:
silinen işlemenin içeriği hiçbir yerden geri getirilemez, referans günlüğü de silinmiş bir
nesneyi geri koyamaz. Bakım komutu ayrıca kimi işlemlerin parçası olarak kendiliğinden de
çalışabilir; erişilemeyen bir işlemeyi "sonra kurtarırım" diye bırakmak bu yüzden güvenli
değildir.

Güvenli alışkanlık tek cümledir: **önce başvuruyu yaz.** Ayrık durumda bir iş yapılacaksa
işe başlamadan bir dal açılır; iş bittikten sonra fark edildiyse referans günlüğü hâlâ
sıcakken bir yedek dal yazılır. Kurtarmanın tüm maliyeti kırk bir bayttır ve bu bayt
yazılmadığı sürece iş tek bir bakım çağrısı uzaklıktadır.

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

- **DL22** — Kurgu ortak tanımın on iki işlemesidir ve `gelisim` değiştirilmez. Ders
  kurgunun tek bir adımını değiştirir: `rapor` işinin **ikinci ve üçüncü** işlemesi ayrık
  HEAD üstünde yapılmıştır ve dal ucuna bağlanmamıştır.
- **DL23** — Erişilebilirlik başvurulardan başlar. Bir işlemeye hiçbir dal başvurusundan
  ulaşılamıyorsa o işleme **tarihçenin dışındadır**; nesne veritabanında durması bunu
  değiştirmez.
- **DL24** — Ölçüm tek bir tümleştirme biçimi kullanır: birleştirme işlemesi. Tanımı ortak
  tanımdan alınır ve değiştirilmez; bu ders biçimleri karşılaştırmaz.
- **DL25** — Altı sorunun tanımı değiştirilmez ve yalnız **erişilebilen** tarihçeye sorulur.
  Soru, kendisine verilmeyen bir işlemeden haberdar olamaz.
- **DL26** — Üç **sayım sorgusu** ayrıca sorulur ve kâhinle karşılaştırılır: `rapor` işine
  ait işleme sayısı, kusuru getiren işleme sayısı, ortak dosyaya dokunan işleme sayısı.
  Kâhin kurguyu bildiği için gerçek sayıyı verir.
- **DL27** — Referans günlüğü bir başvuru **değildir** ve erişilebilirlik hesabına girmez;
  yalnız erişilemeyen bir işlemenin kimliğini bulmaya yarar.
- **DL28** — Kurtarma, düşen işlemeleri bir başvuruya bağlamaktır. Ölçüm kurtarılmış
  tarihçeyi düşenleri geri koyup zaman sırasına dizerek kurar; kurtarma işlemelerin
  içeriğini de sırasını da değiştirmez.
- **DL29** — Kurtarma maliyeti tek bir dal başvurusudur: kırk onaltılık basamak ve bir satır
  sonu, **41 bayt**. Birinci dersin ölçüsü burada aynen geçerlidir.

## Ölçüm

```python
"""Ayrik HEAD: hicbir basvurudan erisilemeyen isleme tarihcenin disindadir.

Bolum 1 - ayrik durumda yapilan iki isleme tarihceden dusuyor.
Bolum 2 - alti soru uc tarihceye soruluyor: hangi soru disarida kaliyor.
Bolum 3 - sayim sorgulari kahinle karsilastiriliyor: yanit var ama eksik.
"""
TOHUM = 20260813
DALLAR = ("olcum", "rapor", "kimlik")
DOSYALAR = {"olcum": "olcum.py", "rapor": "rapor.py", "kimlik": "kimlik.py"}
KUSURLU = ("rapor", 2)
ORTAK_DOSYA = "ayar.py"
AYRIK = ("rapor", (2, 3))     # bu iki isleme ayrik HEAD ustunde yapildi
BASVURU_BAYT = 40 + 1


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


def erisilebilen(kayit, dusen):
    dal, siralar = dusen
    return [k for k in kayit if not (k["dal"] == dal and k["sira"] in siralar)]


def kurtar(kalan, dusenler):
    """Referans gunlugunden bulunan islemeler bir basvuruya baglanir."""
    return sorted(kalan + dusenler, key=lambda x: x["zaman"])


def sorgula(kume):
    """Tarihceye ya da kurguya sorulan uc sayim sorgusu."""
    return {"rapor işine ait işleme": sum(1 for x in kume
                                          if x["dal"] == "rapor"
                                          and not x.get("birlesme")),
            "kusuru getiren işleme": sum(1 for x in kume if x["kusurlu"]),
            "ayar.py'ye dokunan işleme": sum(1 for x in kume
                                             if x["dosya"] == ORTAK_DOSYA)}


kayit = gelisim()
kalan = erisilebilen(kayit, AYRIK)
dusen = [k for k in kayit if k["dal"] == AYRIK[0] and k["sira"] in AYRIK[1]]
TARIHCELER = (("bağlı HEAD", kayit), ("ayrık HEAD", kalan),
              ("kurtarılmış", kurtar(kalan, dusen)))
T = {ad: tumlestir(k, "birlestirme islemesi") for ad, k in TARIHCELER}

print(f"kurgu: {len(kayit)} işleme; ayrık HEAD üstünde yapılan {len(dusen)} "
      f"işleme hiçbir başvurudan erişilemez")
print()
print(f"{'tarihçe':<14s}{'erişilen işleme':>16s}{'tarihçe işlemesi':>17s}"
      f"{'erişilemeyen':>13s}{'yanıtlanan':>11s}")
for ad, k in TARIHCELER:
    print(f"  {ad:<12s}{len(k):16d}{len(T[ad]):17d}"
          f"{len(kayit) - len(k):13d}"
          f"{sum(soru(T[ad]) for _, soru in SORULAR):11d}")
print()
BASLIK = (("bağlı HEAD", 12), ("ayrık HEAD", 12), ("kurtarılmış", 13))
print(f"{'soru':<22s}" + "".join(f"{a:>{w}s}" for a, w in BASLIK))
for ad, soru in SORULAR:
    print(f"  {ad:<20s}" + "".join(
        f"{('evet' if soru(T[a]) else 'hayır'):>{w}s}" for a, w in BASLIK))
print()
kahin = sorgula(kayit)
ayrik, geri = sorgula(T["ayrık HEAD"]), sorgula(T["kurtarılmış"])
print(f"{'sayım sorgusu':<28s}{'kâhin':>7s}{'ayrık HEAD':>12s}{'eksik':>7s}"
      f"{'kurtarılmış':>13s}")
for s in kahin:
    print(f"  {s:<26s}{kahin[s]:7d}{ayrik[s]:12d}{kahin[s] - ayrik[s]:7d}"
          f"{geri[s]:13d}")
print(f"\nüç sorgunun {sum(1 for s in kahin if kahin[s] != ayrik[s])}'ü eksik "
      f"yanıtlanıyor; tarihçe eksik olduğunu bildirmiyor")
print(f"kurtarma maliyeti: {len(dusen)} işlemeyi geri bağlamak için "
      f"1 başvuru, {BASVURU_BAYT} bayt")
```

```
kurgu: 12 işleme; ayrık HEAD üstünde yapılan 2 işleme hiçbir başvurudan erişilemez

tarihçe        erişilen işleme tarihçe işlemesi erişilemeyen yanıtlanan
  bağlı HEAD                12               15            0          5
  ayrık HEAD                10               13            2          4
  kurtarılmış               12               15            0          5

soru                    bağlı HEAD  ayrık HEAD  kurtarılmış
  özellik gruplaması          evet        evet         evet
  kusurun yalıtımı            evet       hayır         evet
  gerçek sıra                 evet        evet         evet
  dosya izi                   evet        evet         evet
  dalın bütünlüğü             evet        evet         evet
  çakışma kararı             hayır       hayır        hayır

sayım sorgusu                 kâhin  ayrık HEAD  eksik  kurtarılmış
  rapor işine ait işleme          4           2      2            4
  kusuru getiren işleme           1           0      1            1
  ayar.py'ye dokunan işleme       2           1      1            2

üç sorgunun 3'ü eksik yanıtlanıyor; tarihçe eksik olduğunu bildirmiyor
kurtarma maliyeti: 2 işlemeyi geri bağlamak için 1 başvuru, 41 bayt
```

## Sayıların Okunması

Üst tablo kaybın büyüklüğünü veriyor. Erişilen işleme **12**'den **10**'a, tarihçedeki kayıt
**15**'ten **13**'e iniyor; erişilemeyen **2**. Yanıtlanan soru **5**'ten **4**'e düşüyor.
On iki işlemelik kümede kayıp **2/12**, altı soruluk kümede **1/6** — ikisi de kümelerin
çözünürlüğünde ve savunulabilir.

Orta tablo hangi sorunun düştüğünü söylüyor ve yanıt tektir: **kusurun yalıtımı**. Kusuru
getiren işleme `rapor` işinin ikincisiydi ve ayrık durumda yapılanlardan biriydi. Tarihçe
artık kusurlu bir işleme görmüyor; soru "kusuru getiren işleme tek başına bulunabiliyor mu"
diye sorulduğunda yanıt hayır oluyor. Bu, kaybın **bildirilen** yüzüdür: tarihçe bir soruyu
yanıtlayamadığını söylüyor.

Öteki beş satırın hiçbiri değişmiyor ve dersin asıl sonucu buradan çıkıyor. **Özellik
gruplaması** üç durumda da evet; kalan on işlemenin hepsi bir dal kaydı taşıyor ve tarihçe
kendi içinde tutarlı. **Dosya izi** de üç durumda da evet; kalan her işleme bir dosya adı
taşıyor. Tarihçe eksik olduğunun farkında değildir, çünkü eksiklik ancak dışarıdan bir
ölçüyle görülür.

Alt tablo o dış ölçüyü koyuyor. Üç sayım sorgusunun **3**'ü de eksik yanıtlanıyor. `rapor`
işine ait işleme sayısı **4** yerine **2** çıkıyor — grup okunabiliyor ama yarısı eksik.
Kusuru getiren işleme **1** yerine **0** çıkıyor. Ortak dosyaya dokunan işleme **2** yerine
**1** çıkıyor — dosya izi sorusu evet diyor, verdiği iz yarım. Hiçbir satırda bir hata
iletisi yok; üç yanıt da makul görünüyor ve üçü de yanlış.

İki tür kaybın ayrımı budur. Bir soru düştüğünde tarihçe hayır der ve okuyan bunu bilir.
Bir işleme düştüğünde tarihçe evet demeyi sürdürür ve okuyan yanlış bir sayıyla kalır.
Yanıtlanan soru sayısındaki **1/6**'lık düşüş, gerçek kaybın yalnız görünen kısmıdır.

Son iki satır kurtarmayı ölçüyor. Düşen iki işleme bir başvuruya bağlandığında erişilen
işleme **12**'ye, tarihçe **15**'e, yanıtlanan soru **5**'e dönüyor ve üç sayım sorgusu
kâhinle birebir uyuşuyor. Kurtarmanın maliyeti **41 bayttır**. Birinci dersin ölçüsü tam
tersini de söylemişti: bir başvuruyu **yazmak** kırk bir bayttı, dolayısıyla o başvuruyu
yazmamak da kırk bir baytlık bir eksiklikti. Ayrık durumun tüm hikâyesi yazılmayan bu kırk
bir bayttır.

## Özet

- Ayrık HEAD, `HEAD`in bir dal adı yerine doğrudan bir işleme kimliğini gösterdiği durumdur;
  `git symbolic-ref HEAD` başarısız olur ve durum bir kusur değil, bir konumlanma biçimidir.
- Ayrık durumda yapılan işleme normal biçimde yazılır ama hiçbir dal başvurusu ilerlemez;
  başka bir dala geçildiğinde o işlemelere hiçbir başvurudan erişilemez.
- Erişilemeyen **2** işleme tarihçeyi **15** kayıttan **13**'e indirir ve yanıtlanan soruyu
  **5**'ten **4**'e düşürür; düşen tek soru **kusurun yalıtımıdır**.
- Asıl bedel üç sayım sorgusunun **3**'ünün de eksik yanıtlanmasıdır: tarihçe evet demeyi
  sürdürür, verdiği sayılar **4** yerine **2**, **1** yerine **0**, **2** yerine **1**'dir.
- Referans günlüğü `HEAD`in geçmiş konumlarını tutar ve kurtarmayı **41 bayta** indirir;
  günlük girdisi düştükten sonra nesne toplama kaybı kalıcı kılar ve geri alınamaz.

## Sonraki Adım

Bu konu dallanmanın açılış tarafını bitirdi. Dal açmak bir addır ve **123** bayt yazar;
adı düzenli koymak tarihçenin birinci sorusuna kaydın tek başına veremediğini ekler; adın
hiç yazılmaması ise iki işlemeyi tarihçenin dışına düşürür. Üç ölçüm de aynı yöne bakıyor:
bir işlemeler kümesini bir işe bağlayan şey başvurudur.

Geriye çatallanmanın öteki ucu kalıyor. Üç dal açıldı, on iki işleme yazıldı ve her biri
kendi ucunda duruyor; bir noktada bu uçların ana dala alınması gerekir. Sonraki konu
birleşmenin tarihçeye ne yazdığını sorar: araç iki ucu kapatırken yeni bir kayıt üretir mi,
üretmezse ne kaybolur, ve kapatma biçimi altı sorunun kaçını yanıtlanabilir bırakır. Kurs
buradan itibaren bu ölçünün üstünde yürür.
