---
title: 'Depo Öznitelikleri'
source: 'https://academia.sh/tr/kurslar/ileri-git/depo-oznitelikleri'
course: 'İleri Git'
language: tr
updated: '2026-08-17T18:10:42+00:00'
license: 'CC BY-SA 4.0'
---

# Depo Öznitelikleri

Öznitelik dosyası hangi işlemin hangi dosyada nasıl davranacağını belirler: ayarsız bin işlemelik tarihçe 5888 nesne yazar, satır sonu 162 gereksiz nesne üretir ve elli birleştirmenin 43'ü üretilen dosyada çakışarak 86 nesne daha ekler.

Önceki dersin ölçümü bir varsayımı dışarıda bıraktı: çalışma alanına çıkarılan dosyaların iki
düzende de aynı olduğu varsayımını. Bu, dosyanın **nasıl** yazıldığının bir tercih olmadığını
söylüyordu.

Öyle değildir. Nesne deposundaki damla ile çalışma alanındaki dosya birbirinin aynısı olmak
zorunda değildir; arada bir dönüşüm katmanı vardır ve o katman yapılandırılabilir. Katman
ayarsız bırakıldığında sessizce çalışır ve yaptığı iş tarihçeye yazılır. Bu dersin sorusu
şudur: hangi öznitelik hangi işlemi hangi dosyada değiştirir, ve ayarsız durumda **içeriği
değişmediği hâlde** kaç nesne yazılır?

## Öznitelik Dosyası Neyi Belirler

**Depo öznitelikleri (repository attributes)**, dosya desenlerine davranış bağlayan
kurallardır ve `.gitattributes` dosyasında dururlar. Dosya işlenen bir dosyadır: tarihçeye
girer, dallar arasında farklılaşabilir ve klonlayan herkese aynı kuralı taşır. Yapılandırma
dosyasından ayıran yer burasıdır — yapılandırma kişiseldir ve kopyaya özeldir, öznitelik
depoya aittir.

```text
# öznitelik dosyası — örnek döküm, çalıştırılmamıştır

# .gitattributes
*            text=auto
*.py         text eol=lf
*.md         text eol=lf
ayar.py      text merge=ours
sunum.bin    -text -diff
belge.md     diff=metin
```

Her satır bir desen ve ona bağlı niteliklerdir. `text` dosyanın metin sayılacağını ve satır
sonu dönüşümüne girebileceğini bildirir; `text=auto` kararı içeriğe bakarak aracın vermesini
ister. `eol=lf` çalışma alanına yazılırken hangi **satır sonu (line ending)** düzeninin
kullanılacağını sabitler. Başındaki eksi işareti niteliği kaldırır: `-text` dosyanın hiçbir
dönüşüme girmeyeceğini, `-diff` ise karşılaştırmanın metin olarak denenmeyeceğini bildirir.
`merge=ours` ve `diff=metin` ise bir **birleştirme sürücüsüne (merge driver)** ya da bir
karşılaştırma tanımına ad verir.

## Dört İşlem, Dört Ayrı An

Öznitelikler dört ayrı anda devreye girer ve hangisinin ne zaman çalıştığı karışırsa
ölçüm de karışır.

**Çıkarma anı:** damla çalışma alanına yazılırken satır sonu dönüşümü uygulanır. **İşleme
anı:** çalışma alanındaki dosya damlaya çevrilirken ters dönüşüm uygulanır — depoya yazılan
biçim tektir. **Birleştirme anı:** iki yanın değişikliği harmanlanırken hangi sürücünün
kullanılacağı belirlenir. **Karşılaştırma anı:** iki damla arasındaki fark üretilirken metin
sayılıp sayılmayacağı belirlenir.

Beşinci bir an daha vardır ve tarihçeyi hiç ilgilendirmez: deponun bir sürümü arşiv olarak
paketlenirken hangi yolların dışarıda bırakılacağı da bir öznitelikle bildirilir. Kural
paketlemeye bakar, işlemeye değil; dosya tarihçede kalır, yalnız arşive girmez. Bu ders onu
ölçmüyor çünkü nesne birimiyle karşılığı yoktur.

İlk ikisi tarihçeye nesne yazar; son ikisinden yalnız birleştirme yazar. Karşılaştırma
okunabilirliği etkiler, tarihçeyi etkilemez — bu yüzden ölçümde `-diff` satırı sıfır verir ve
bu bir eksiklik değil, doğru sonuçtur.

Satır sonu dönüşümü ayarsızken ne olur? Depoya, yazanın ortamında ne varsa o girer. İki ayrı
satır sonu düzeni kullanan iki ortam aynı dosyaya sırayla dokunduğunda, **içerik hiç
değişmese bile** damla baştan yazılır: bayt dizisi farklıdır, dolayısıyla nesne farklıdır.

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

- **BD20** — Ölçüm ortak kurgunun dört ölçeğini kullanır. Her işlemeye ayrı bir üreteçten iki
  alan eklenir: yazanın satır sonu düzeni ve içeriğin gerçekten değişip değişmediği.
- **BD21** — İşlemelerin **üçte biri** ayrı bir satır sonu düzeni kullanan bir ortamdan gelir;
  **beşte biri** içeriği gerçekten değiştirmez, yalnız dosyaya dokunur.
- **BD22** — Satır sonu ayarı yokken, içeriği değişmemiş bir işleme ancak dosyanın **son
  kaydedilen düzeni** farklıysa yeni damla yazar; her böyle yazım **2 nesnedir**. Ayar
  varsayıldığında bu işlemeler **0 nesne** yazar.
- **BD23** — Her **20** işlemede bir birleştirme yapılır; pencerenin iki yarısı da üretilen
  dosyaya dokunduysa birleştirme çakışması doğar. Elle çözüm bir işleme yazar, **2 nesne**.
- **BD24** — `merge=ours` tanımlandığında çakışma doğmaz ve çözüm işlemesi yazılmaz; sürücü
  üretilen dosyada karşı yanın sürümünü almaz.
- **BD25** — `-text` ve `-diff` ikili varlığa hiçbir nesne eklemez ve hiçbirini çıkarmaz;
  etkileri çıkarma ve karşılaştırma anındadır, tarihçede değil.
- **BD26** — Bedel **dokunulan nesne** birimiyle sayılır. "Ayarsız" sütunu taban, "tam ayarlı"
  sütunu ortak kurgunun klon bedelidir; aradaki fark özniteliğin **yazılmasını engellediği**
  nesnedir.

## Ölçüm

```python
"""Depo oznitelikleri: ayarsiz durumda dogan gereksiz nesne.

Bolum 1 - hangi oznitelik hangi dosyada hangi islemi degistiriyor (1000 isleme).
Bolum 2 - dort olcekte ayarsiz, satir sonu ayarli ve tam ayarli nesne.
"""
TOHUM = 20260814
DOSYALAR = ("olcum.py", "rapor.py", "kimlik.py", "ayar.py", "belge.md")
IKILI_VARLIK = "sunum.bin"
URETILEN = "ayar.py"      # uretilen dosya: birlestirme surucusu buna baglanir
OLCEKLER = (50, 200, 1000, 4000)
BIRLESME_ARALIGI = 20     # her 20 islemede bir birlestirme


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 ortamli(t, tohum):
    """Her islemeye yazanin satir sonu duzeni ve icerigin gercekten degisip
    degismedigi eklenir."""
    r, k = uretec(tohum), []
    for x in t:
        k.append({**x, "crlf": r(3) == 0, "gercek": r(5) != 0})
    return k


def satir_sonu_nesnesi(k, dosya=None):
    """Ayarsizken: icerik ayni oldugu halde satir sonu duzeni degistigi icin
    yeniden yazilan damla. Dosya basina son duzen izlenir."""
    son, gereksiz = {}, 0
    for x in k:
        if x["dosya"] == dosya or dosya is None:
            if not x["gercek"] and son.get(x["dosya"]) not in (None, x["crlf"]):
                gereksiz += 2
        son[x["dosya"]] = x["crlf"]
    return gereksiz


def cakisan_birlesmeler(k):
    """Her aralikta bir birlestirme; iki yan da uretilen dosyaya dokunduysa
    cakisma dogar ve elle cozum bir isleme yazar."""
    sayi = 0
    for bas in range(0, len(k) - BIRLESME_ARALIGI + 1, BIRLESME_ARALIGI):
        pencere = k[bas:bas + BIRLESME_ARALIGI]
        yarim = BIRLESME_ARALIGI // 2
        sol = any(x["dosya"] == URETILEN for x in pencere[:yarim])
        sag = any(x["dosya"] == URETILEN for x in pencere[yarim:])
        sayi += sol and sag
    return sayi


def surucu_nesnesi(k):
    return 2 * cakisan_birlesmeler(k)


K = ortamli(tarihce(1000), TOHUM + 7)
print("dosya       oznitelik        degistirdigi islem        satir sonu nesnesi"
      "  surucu nesnesi")
OZNITELIK = (("olcum.py", "text eol=lf", "cikarma ve isleme"),
             ("rapor.py", "text eol=lf", "cikarma ve isleme"),
             ("kimlik.py", "text eol=lf", "cikarma ve isleme"),
             ("ayar.py", "text merge=ours", "cikarma, isleme, birlestirme"),
             ("belge.md", "text eol=lf", "cikarma ve isleme"),
             (IKILI_VARLIK, "-text -diff", "cikarma ve karsilastirma"))
for dosya, oz, islem in OZNITELIK:
    s = 0 if dosya == IKILI_VARLIK else satir_sonu_nesnesi(K, dosya)
    d = surucu_nesnesi(K) if dosya == URETILEN else 0
    print(f"  {dosya:10s} {oz:16s} {islem:26s} {s:16d} {d:15d}")
print()
print("isleme  ayarsiz nesne  satir sonu ayarli  tam ayarli  gereksiz nesne   oran")
for n in OLCEKLER:
    k = ortamli(tarihce(n), TOHUM + 7)
    tam, s, d = klon_bedeli(k), satir_sonu_nesnesi(k), surucu_nesnesi(k)
    print(f"{n:6d} {tam + s + d:14d} {tam + d:18d} {tam:11d} {s + d:15d} "
          f"{(s + d) / (tam + s + d):6.4f}")
print()
n = 1000
k = ortamli(tarihce(n), TOHUM + 7)
print(f"tarihce {n} isleme; satir sonu yuzunden yeniden yazilan damla "
      f"{satir_sonu_nesnesi(k) // 2}, yazdigi nesne {satir_sonu_nesnesi(k)}")
print(f"birlestirme {n // BIRLESME_ARALIGI}, uretilen dosyada cakisan "
      f"{cakisan_birlesmeler(k)}, elle cozumun yazdigi nesne {surucu_nesnesi(k)}")
```

```
dosya       oznitelik        degistirdigi islem        satir sonu nesnesi  surucu nesnesi
  olcum.py   text eol=lf      cikarma ve isleme                        38               0
  rapor.py   text eol=lf      cikarma ve isleme                        34               0
  kimlik.py  text eol=lf      cikarma ve isleme                        22               0
  ayar.py    text merge=ours  cikarma, isleme, birlestirme               36              86
  belge.md   text eol=lf      cikarma ve isleme                        32               0
  sunum.bin  -text -diff      cikarma ve karsilastirma                  0               0

isleme  ayarsiz nesne  satir sonu ayarli  tam ayarli  gereksiz nesne   oran
    50            390                384         380              10 0.0256
   200            972                938         920              52 0.0535
  1000           5888               5726        5640             248 0.0421
  4000          23578              22912       22600             978 0.0415

tarihce 1000 isleme; satir sonu yuzunden yeniden yazilan damla 81, yazdigi nesne 162
birlestirme 50, uretilen dosyada cakisan 43, elle cozumun yazdigi nesne 86
```

## Hangi Öznitelik Hangi Dosyada

Üst tablo dersin birinci sorusunu yanıtlıyor ve dikkat çeken şey sütunların **birbirinden
bağımsız** olmasıdır.

Satır sonu sütunu beş metin dosyasına dağılıyor: **38**, **34**, **22**, **36** ve **32** —
toplam **162** nesne. Dağılım eşit değil ama nedeni özniteliğin kendisi değil, kurgunun dosya
dağılımı. Öznitelik açısından beş satır aynı kuralı taşıyor; ödenen bedel dosyanın ne sıklıkta
dokunulduğuna göre değişiyor.

Sürücü sütunu tek bir satırda toplanıyor: **86** nesne, yalnız `ayar.py` satırında. Bu, kurgu
gereği üretilen dosyadır — elle yazılmayan, bir araç tarafından üretilip depoya konan bir
dosya. Öbür dört dosyada sürücü sütunu **0**'dır çünkü onlarda çakışma elle çözülmelidir ve
çözüm bir karardır, ayarla değiştirilecek bir şey değildir.

İkili varlık satırı iki sütunda da **0** veriyor. `-text` ve `-diff` nitelikleri gerçek işler
yapar — dönüşümü engeller, okunmaz karşılaştırmayı önler — ama **tarihçeye tek nesne
eklemez ve çıkarmaz**. Ölçünün birimi nesne olduğu için o etkiler burada görünmez. Bu satır,
ölçünün kapsam sınırının bildirimidir.

## Ayarsızlığın Ödettiği

Alt tablonun birimi **dokunulan nesnedir** ve üç sütun aynı tarihçenin üç ayarlama düzeyini
veriyor. Bin işlemelik tarihçe ayarsız **5888** nesne yazıyor; satır sonu ayarlandığında
**5726**'ya, birleştirme sürücüsü de tanımlandığında **5640**'a — yani ortak kurgunun klon
bedeline — iniyor. Gereksiz nesne **248**, oran **0,0421**.

Oran küçüktür ve bu, ölçümün dürüst sonucudur: satır sonu düzensizliği bir depoyu şişirmez.
İki gözlem yine de kayda değer. **Birincisi**, gereksiz nesne oranı dört ölçekte **0,0256**,
**0,0535**, **0,0421** ve **0,0415** çıkıyor; büyük iki ölçekte **0,042** dolayında oturuyor
ve ölçek büyüdükçe azalmıyor. Bu, tarihçenin ömrü boyunca ödenmeye devam eden bir bedeldir.
**İkincisi**, elli işlemelik satırdaki **10** nesne, o ölçekteki **1/50** çözünürlüğün
yanında beş işlemeye karşılık gelir; küçük depoda bu bedelden bir sonuç çıkarılamaz.

Asıl sayı üçüncü satırda duruyor: **50** birleştirmenin **43**'ü üretilen dosyada çakışıyor.
Bu, birleştirmelerin **beşte dördünden** fazlasıdır ve her biri bir kişinin oturup çakışma
işaretlerini elle temizlemesi demektir. Tarihçeye yazdığı **86** nesne bu işin en küçük
parçasıdır; ölçülmeyen kısmı, kırk üç kez verilen ve hiçbirinin bir bilgi taşımadığı karardır.
Dallanma ve İşbirliği kursu çakışma çözümünün tarihçeye yazılmadığını göstermişti — burada
görülen şey, o yazılmayan kararların **kırk üç tanesinin baştan gereksiz** olduğudur.

## Hangi Satır Kazanır

Ölçüm her dosyaya tek bir kural düştüğünü varsaydı. Gerçek bir öznitelik dosyasında bir yola
birden çok desen uyar ve hangisinin kazandığı bilinmeden hiçbir ayarın etkisi öngörülemez.

Kural sırası üç katmanlıdır. **Aynı dosya içinde son eşleşen satır kazanır** — yukarıdan
aşağı okunur ve alttaki üsttekini ezer; bu yüzden genel desenler başa, özel desenler sona
yazılır. **Alt dizindeki öznitelik dosyası üsttekini ezer**, çünkü daha yakındır. Ve deponun
içinde, tarihçeye girmeyen yerel bir öznitelik dosyası daha vardır; o **hepsini ezer** ve
yalnız o kopyada geçerlidir.

Üçüncü katman iki yönlü keskindir. Bir kopyanın davranışını depoyu değiştirmeden ayarlamayı
sağlar; aynı nedenle, bir kopyada beklenmedik bir dönüşüm görüldüğünde bakılacak ilk yer
orasıdır. Öznitelikler depoya aittir demiştik — bu, o yerel katman dışında doğrudur ve
farkın nerede olduğu bilinmezse bir dosyanın neden başka türlü çıktığı hiç anlaşılmaz.

Bir nitelik üç değer alabilir: verilmiş (`text`), kaldırılmış (`-text`) ve **belirtilmemiş**.
Üçüncüsü ikinciyle aynı şey değildir: kaldırılmış bir nitelik kararı kesinleştirir,
belirtilmemiş bir nitelik kararı bir alt katmana ya da aracın kendi öntanımına bırakır.
`text=auto` tam olarak bu üçüncü durumu yönetir — kararı içeriğe bakarak verir ve ikili
sandığı dosyaya dönüşüm uygulamaz.

## Ayarın Sınırı ve Kurtarma

Öznitelik dosyası ileriye dönük çalışır. Bugün yazılan bir `text=auto` satırı, dün yazılmış
damlaları düzeltmez; tarihçedeki **162** nesne yerinde kalır. Ayarın etkisi ilk çıkarmadan
sonra başlar ve depo çalışanların ellerinde zaten çıkarılmış durumdaysa, dosyaların bir kez
yeniden normalize edilmesi gerekir — bu, tarihçede yeni bir işleme olarak görünür ve
tarihçeyi yeniden yazmaz.

Yeniden yazan yol da vardır ve konunun ikinci dersindeki kuralla aynı sınıra girer: geçmişteki
bütün damlaları normalize etmek **tarihçeyi yeniden yazmaktır**, kimlikleri değiştirir,
**geri alınamaz** ve her kopyanın yeniden klonlanmasını gerektirir. Kazancı ölçümde okunuyor —
**162** nesne. Bin işlemelik bir depoda bu, klon bedelinin otuz beşte biri kadardır ve o
kazanç için tarihçeyi yeniden yazmak neredeyse hiçbir durumda haklı çıkmaz.

Ucuz ve geri alınabilir yol şudur: öznitelik dosyası deponun ilk gününde yazılır; sonradan
yazıldıysa tek bir normalizasyon işlemesiyle ileriye dönük düzeltilir; geçmiş olduğu gibi
bırakılır. Yanlış bir öznitelik satırının kendisi ise zararsızdır — dosya işlenen bir dosya
olduğu için satır geri alınabilir, ve dönüşüm bir sonraki çıkarmada eski hâline döner.

## Özet

- Depo öznitelikleri işlenen bir dosyada durur ve depoya aittir; yapılandırmadan farkı budur.
  Dört ayrı anda devreye girerler: çıkarma, işleme, birleştirme ve karşılaştırma.
- Karşılaştırma anı tarihçeye nesne yazmaz; ikili varlık satırı ölçümde iki sütunda da
  **0** verir ve bu, ölçünün kapsam sınırının bildirimidir.
- Satır sonu ayarsızken içeriği değişmemiş **81** işleme yeni damla yazar ve **162** nesne
  üretir; beş metin dosyasına **38 / 34 / 22 / 36 / 32** olarak dağılır.
- Üretilen dosyada birleştirme sürücüsü tanımsızken **50** birleştirmenin **43**'ü çakışır ve
  elle çözüm **86** nesne yazar; `merge=ours` bu çakışmaların tümünü ortadan kaldırır.
- Bin işlemede ayarsız tarihçe **5888**, tam ayarlı tarihçe **5640** nesnedir; gereksiz
  **248** nesnenin oranı **0,0421**'dir ve ölçek büyüdükçe azalmaz.

## Sonraki Adım

Bu konunun dört dersi aynı depoya dört ayrı müdahale yaptı: bağımlı depoyu gömdü, ikili
gövdeyi dışarı taşıdı, çalışma ağacını çoğalttı ve dönüşüm katmanını ayarladı. Dördü de tek
bir soruyu varsaydı — deponun **sınırının** nerede olduğunu. Sonraki ders o varsayımı ölçer:
aynı iş tek bir depoda ve dört ayrı depoda yapılırsa, klon bedeli ile arama adımı nasıl
değişir, ve bileşenler arasında sorulan sorulardan kaçı ikinci düzende yanıtsız kalır?
