---
title: 'Sürüm Kontrolüne Giriş'
source: 'https://academia.sh/tr/kurslar/surum-kontrolune-giris'
language: tr
updated: '2026-08-17T04:42:51+00:00'
license: 'CC BY-SA 4.0'
lessons: 15
outcomes:
    - 'Depo, çalışma alanı, hazırlık alanı ve işleme (commit) kavramlarını ayırır.'
    - 'Değişiklik tarihçesini okur ve iki sürüm arasındaki farkı inceler.'
    - 'İstenmeyen değişiklikleri güvenli biçimde geri alır.'
---

# Sürüm Kontrolüne Giriş

Deponun nesne modelinden başlayarak çalışma dizini, hazırlık alanı ve işleme döngüsünü kuran; tarihçeyi okumayı ve istenmeyen değişiklikleri geri almayı öğreten başlangıç kursu.

## Sürüm Kontrolü Kavramı

Sürüm kontrolünün çözdüğü problem, merkezî ile dağıtık tasarımların farkı ve bir deponun oluşturulup yapılandırılması.

### Sürüm Kontrolü Nedir

Source: https://academia.sh/tr/kurslar/surum-kontrolune-giris/surum-kontrolu-nedir

Sürüm kontrolünün çözdüğü problem; tarihçe, geri alınabilirlik ve işbirliği sözleri; anlık görüntü ile fark tabanlı saklamanın karşılaştırılması.

Programlama Temelleri kursunda bir programın nasıl yazıldığı ele alındı; bu kurs, yazılan
programın zaman içinde nasıl değiştiğiyle ilgilenir. Bir dosya bir kez yazılıp bırakılmaz:
düzeltilir, genişletilir, bozulur, geri alınır. Bu değişim dizisini kayıt altına almadan
çalışmak, yalnızca son hâli bilinen bir program üretir.

Bu ders sürüm kontrolünün çözdüğü problemi tanımlar ve çözümün taşıdığı üç sözü ayırır.
Komutlar bir sonraki konuda başlar; burada kurulan model, kursun geri kalanında kullanılacak
sözcük dağarcığıdır.

#### Elle Sürüm Yönetimi ve Sınırları

Kayıt tutmanın en dolaysız yolu kopyalamaktır: dosyanın bir sürümü çalışmaya başlamadan
önce yedeklenir, sonraki sürüm ayrı bir adla saklanır. Sonuçta şuna benzer bir dizin oluşur:

```
ara.sh
ara-yedek.sh
ara-calisan.sh
ara-son.sh
ara-son-2.sh
```

Bu düzenin dört ayrı kusuru vardır ve dördü de yapısaldır:

1. **Sıra bilgisi yoktur.** Dosya adları hangi sürümün hangisinden türediğini söylemez.
   `ara-son.sh` ile `ara-calisan.sh` arasındaki ilişki yalnızca yazan kişinin belleğindedir.
2. **Gerekçe kaydı yoktur.** Bir satırın neden değiştiği hiçbir yerde yazmaz. Altı ay sonra
   aynı satıra bakan kişi, değişikliğin bir düzeltme mi yoksa deneme mi olduğunu bilemez.
3. **Değişiklik bütünlüğü yoktur.** Bir düzeltme çoğu zaman birden çok dosyaya dokunur.
   Dosya başına kopyalama, bu dosyaların hangi anda birlikte tutarlı olduğunu kaydetmez.
4. **Eşzamanlı çalışma tanımsızdır.** İki kişi aynı dosyanın kopyalarını ayrı ayrı
   değiştirirse, iki kopyayı birleştirmenin kuralı yoktur; biri diğerini ezer.

**Sürüm kontrol sistemi (version control system)**, bu dört kusuru gidermek üzere tasarlanmış
bir kayıt düzenidir. Değişiklikleri dosya dosya değil, **işleme (commit)** adı verilen
bütünler hâlinde saklar; her işlemeye bir gerekçe metni, bir yazar ve bir öncül bağlar.

#### Üç Söz

Sürüm kontrolünün sunduğu güvenceler üç başlıkta toplanır.

**Tarihçe.** Her işleme, o andaki proje durumunun tamamını temsil eder ve kendisinden önceki
işlemeye bağlanır. Bu bağ zinciri, "bu satır ne zaman, kim tarafından, hangi gerekçeyle
yazıldı" sorusunu yanıtlanabilir kılar. Kod okumanın önemli bir bölümü bu sorunun
yanıtlanmasıyla geçer.

**Geri alınabilirlik.** Kayıt altına alınmış her durum yeniden elde edilebilir. Bu, cesur
değişiklik yapmayı ucuzlatır: bir denemenin bedeli, denemeyi geri almanın maliyetidir.
Maliyet düşükse deneme sayısı artar. Kursun üçüncü konusu bu geri alma araçlarına ayrılmıştır.

**İşbirliği.** Birden çok kişinin aynı proje üzerinde çalışması, değişikliklerin
birleştirilmesini gerektirir. Sürüm kontrol sistemi, her değişikliğin hangi ortak atadan
türediğini bildiği için birleştirmeyi kurallı bir işleme dönüştürür. Bu kursta işbirliği
yalnızca tasarım kararlarının gerekçesi olarak geçecek; uygulaması Dallanma ve İşbirliği
kursunun konusudur.

#### Anlık Görüntü mü, Fark mı

Bir sistemin tarihçeyi nasıl sakladığı, sunabileceği işlemleri belirler. İki temel tasarım
vardır.

**Fark tabanlı saklama.** Sistem, ilk sürümü tam olarak saklar; sonraki her sürüm için
yalnızca önceki sürümden farkı kaydeder. Depolama açısından ekonomiktir. Bedeli, herhangi bir
sürümü elde etmek için baştan başlayıp farkları sırayla uygulamaktır: $k$. sürüme erişmenin
maliyeti $O(k)$'dir.

**Anlık görüntü (snapshot) tabanlı saklama.** Sistem, her kayıt anında projenin tüm dosya
ağacının bir görüntüsünü saklar. Bir sürüme erişmek doğrudan o görüntüye bakmaktır: $O(1)$.
İlk bakışta savurgan görünür — her kayıtta tüm dosyalar yeniden mi yazılacaktır?

Savurganlığı ortadan kaldıran şey **içerik adresli depolama (content-addressed storage)**
fikridir. Her dosya içeriği, içeriğinden hesaplanan bir karma (hash) değeriyle adlandırılır
ve bu adla saklanır. Aynı içerik iki kez saklanmaz; değişmeyen dosyalar ardışık anlık
görüntülerde aynı nesneyi paylaşır. Veri Yapıları kursunda karma fonksiyonlarının çığ etkisi
ve çakışma olasılığı incelenmişti; burada aynı fonksiyonlar bir kimlik üreticisi olarak
kullanılır.

Böylece anlık görüntü modeli, fark modelinin depolama avantajını büyük ölçüde korurken sürüme
erişimi sabit maliyete indirir. Bu kursta anlatılan sistem — `git` — anlık görüntü modelini
kullanır.

#### Tarihçenin Biçimi

Tarihçe basit bir liste değildir. Her işleme bir öncül işlemeye bağlanır; bir işlemenin
birden çok ardılı olabilir (aynı noktadan iki ayrı yön denenmiştir) ve bir işlemenin birden
çok öncülü olabilir (iki yön birleştirilmiştir). Bağlar geçmişe doğru yönlüdür ve bir işleme
kendi atası olamaz.

Bu üç özellik, tarihçenin bir **yönlü çevrimsiz çizge** olduğunu söyler. Veri Yapıları
kursunda bu yapı tanımlanmış, Algoritmalar kursunda topolojik sıralaması ele alınmıştı.
Buradaki karşılıklar birebirdir:

| Çizge kavramı | Tarihçedeki karşılığı |
|---|---|
| Düğüm | Bir işleme |
| Kenar | İşlemeden öncülüne bağ |
| Çevrimsizlik | Bir işleme kendi atası olamaz |
| Topolojik sıra | Tarihçenin okunabilir bir sırayla listelenmesi |
| Ortak ata | İki yönün ayrıldığı işleme |

Bir tarihçe listesinin "en yeniden en eskiye" sıralanması, çizgenin topolojik sıralarından
biridir. Dallanma olmayan bir tarihçede bu sıra tektir; dallanma varsa birden çok geçerli
sıra bulunur ve sistem hangisini göstereceğini seçmek zorundadır.

```
(A) ← (B) ← (C) ← (D)        dallanmasız tarihçe: tek zincir

            ┌── (C) ← (D)
(A) ← (B) ←─┤                dallanmış tarihçe: iki yön
            └── (E)
```

Oklar geçmişe doğrudur: her düğüm kendi öncülünü gösterir. Bir işleme yazıldıktan sonra
içeriği değişmez; tarihçe yalnızca uçlarından büyür. Bu **değiştirilemezlik**, geri alma
araçlarının nasıl çalıştığını anlamanın anahtarıdır ve üçüncü konuda tekrar karşımıza
çıkacaktır.

#### Yedekleme ile Aynı Şey Değildir

İki düzen de "eski hâli geri getirme" sözü verdiği için karıştırılır; verdikleri söz farklıdır.

**Yedekleme**, bir zaman noktasındaki durumu kurtarmak için tutulur. Amacı veri kaybını
önlemektir; kimin neyi neden değiştirdiğini kaydetmez, iki kişinin çalışmasını birleştirme
kuralı sunmaz. Yedeğin değeri, gereken anda **son** durumu geri verebilmesindedir.

**Sürüm kontrolü**, durumların dizisini ve her adımın gerekçesini tutar. Kurtarma yalnızca bir
sonucudur; asıl ürettiği bilgi, değişimin kendisidir.

İkisi birbirinin yerine geçmez. Bir depo yalnızca bir makinede duruyorsa, o makinenin
kaybolması tarihçeyi de götürür; sürüm kontrolü kullanmak yedeklemeyi gereksizleştirmez.
Bir sonraki ders, dağıtık modelin bu riski nasıl dağıttığını gösterecek.

Ayrım, **neyin kaydedileceği** sorusunu da belirler. Depoya giren şey, insan tarafından
yazılmış ve gerekçesi olan içeriktir: kaynak dosyalar, yapılandırma, belgeler. Derleme
çıktıları ve indirilen bağımlılıklar kaynaklarından yeniden üretilebildiği için tarihçede yer
tutmaları gereksizdir; gizli anahtarlar ise tarihçeye bir kez girdiğinde kalıcı olduğu için
hiç girmemelidir. Bu ayrımın uygulaması, Yoksayma Kuralları dersinin konusudur.

#### Kursun Örnek Deposu

Kurs boyunca tek bir örnek proje kullanılacaktır: `sozluk` adlı küçük bir çalışma. İçinde üç
dosya bulunur — bir açıklama belgesi, satır satır terim tutan bir metin dosyası ve bu dosyada
arama yapan bir kabuk betiği. Proje sıfırdan kurulacak, her ders tarihçeyi bir adım
ilerletecek, üçüncü konudaki dersler aynı depoda kasıtlı hatalar yapıp bunları geri alacaktır.

Örneğin küçük olması bilinçlidir: dosya sayısı azaldıkça, nesne veritabanının içeriğini
doğrudan inceleyip modeli gözle doğrulamak mümkün hâle gelir. Kursun amacı komut listesi
ezberletmek değil, bu modeli kurmaktır; komutlar modelden türetilebildiği ölçüde
akılda kalır.

#### Özet

- Elle kopyalayarak sürüm tutmak sıra, gerekçe, değişiklik bütünlüğü ve eşzamanlılık
  bilgisini kaybettirir.
- Sürüm kontrol sistemi değişiklikleri dosya başına değil, işleme adı verilen bütünler
  hâlinde saklar.
- Üç temel söz vardır: tarihçe, geri alınabilirlik ve işbirliği.
- Fark tabanlı saklama depolamada, anlık görüntü tabanlı saklama erişimde ucuzdur; içerik
  adresli depolama ikinci modelin depolama maliyetini düşürür.
- Tarihçe bir yönlü çevrimsiz çizgedir; düğümler işlemeler, kenarlar öncül bağlarıdır.
- Yedekleme son durumu kurtarır, sürüm kontrolü durumların dizisini ve gerekçesini tutar;
  ikisi birbirinin yerine geçmez.

#### Sonraki Adım

Sürüm kontrolünün ne olduğu tanımlandı; ancak tarihçenin nerede tutulduğu sorusu açık kaldı.
Tek bir sunucuda mı, yoksa her katılımcının makinesinde eksiksiz bir kopya hâlinde mi? Bu
seçim, sistemin hangi işlemleri ağ bağlantısı olmadan yapabileceğini ve bir arıza durumunda
neyin kaybolacağını belirler. Sonraki ders bu iki tasarımı ve sonuçlarını karşılaştıracak.

### Merkezî ve Dağıtık Modeller

Source: https://academia.sh/tr/kurslar/surum-kontrolune-giris/merkezi-ve-dagitik-modeller

Tarihçenin tek sunucuda ya da her kopyada tutulmasının tasarım sonuçları; sürüm kimliğinin artan sayı yerine içerik karmasıyla üretilmesinin gerekçesi.

Önceki ders tarihçeyi bir yönlü çevrimsiz çizge olarak tanımladı ama bu çizgenin nerede
durduğunu söylemedi. Tek bir sunucuda mı tutulur, yoksa her katılımcının makinesinde eksiksiz
bir kopyası mı bulunur? Bu soru bir uygulama ayrıntısı değildir: yanıt, sistemin hangi
işlemleri ağ bağlantısı olmadan yapabileceğini, sürüm kimliklerinin nasıl üretileceğini ve
bir arıza anında neyin kaybolacağını belirler.

#### Merkezî Model

**Merkezî sürüm kontrolünde (centralized version control)** tarihçenin tek bir yetkili
kopyası vardır ve bir sunucuda durur. Katılımcıların makinesinde yalnızca **çalışma kopyası**
bulunur: dosyaların belirli bir sürümdeki hâli, artı hangi sürümden alındığını söyleyen küçük
bir kayıt. Tarihçenin kendisi yerelde yoktur.

Bu düzende her işlem sunucuya gider:

- Yeni bir işleme yazmak sunucuya bağlanmayı gerektirir.
- Geçmiş bir sürümü görmek için sunucudan istenir.
- İki sürüm arasındaki fark sunucuda hesaplanır ya da eksik veri sunucudan çekilir.

Karşılığında elde edilen şey basit bir doğruluk kaynağıdır. "Projenin şu anki hâli" sorusunun
tek bir yanıtı vardır ve o yanıt sunucudadır. Erişim denetimi de tek noktada uygulanır:
belirli dizinlere yazma yetkisi sunucu tarafından sınırlanabilir.

#### Dağıtık Model

**Dağıtık sürüm kontrolünde (distributed version control)** her kopya eksiksizdir. Bir depo
alındığında yalnızca son sürüm değil, tarihçenin tamamı — tüm işlemeler, tüm anlık görüntüler
— yerel makineye yazılır. Katılımcının elinde çalışma kopyası değil, tam bir **depo
(repository)** vardır.

Sonuç, işlem kümesinin ikiye ayrılmasıdır:

| İşlem | Merkezî | Dağıtık |
|---|---|---|
| İşleme yazmak | Sunucu gerekir | Yerelde yapılır |
| Tarihçeyi listelemek | Sunucu gerekir | Yerelde yapılır |
| İki sürümün farkını almak | Sunucu gerekir | Yerelde yapılır |
| Geçmiş bir sürüme dönmek | Sunucu gerekir | Yerelde yapılır |
| Başkasının işini almak | Sunucu gerekir | Ağ gerekir |
| Kendi işini paylaşmak | Sunucu gerekir | Ağ gerekir |

Ağ yalnızca son iki satırda gereklidir. Bu ayrım, bu kursun bütün derslerinin ağ bağlantısı
olmadan yapılabilmesinin nedenidir: kurs boyunca kurulacak depo yerelde kalacak ve tek başına
işlevsel olacaktır. **Uzak depo (remote)** kavramı Dallanma ve İşbirliği kursunun konusudur.

#### Kimlik Sorunu

İki modelin en öğretici farkı, bir sürümün nasıl adlandırıldığındadır.

Merkezî modelde sunucu tek yetkilidir; sürümleri artan bir sayıyla numaralandırabilir. Sürüm
7'den sonra sürüm 8 gelir ve bu sayıyı kimin vereceği tartışmasızdır. Sayı hem kimlik hem de
sıra bilgisi taşır: 8, 7'den sonradır.

Dağıtık modelde böyle bir yetkili yoktur. İki kişi birbirinden habersiz olarak aynı öncülün
üzerine birer işleme yazarsa, ikisi de "sıradaki sayı" olarak aynı değeri seçerdi. Sonuçta
aynı kimliği taşıyan iki farklı işleme oluşur ve tarihçe tutarsızlaşır. Artan sayı, merkezî
bir sayaç gerektirir.

Çözüm, kimliği dış bir sayaçtan değil, içeriğin kendisinden türetmektir. Bir işlemenin kimliği,
işlemenin bütün bileşenleri — anlık görüntüsü, öncülünün kimliği, yazarı, zamanı, mesajı —
üzerinden hesaplanan bir karma değeridir. Bu seçimin üç sonucu vardır:

1. **Kimlik üretimi eşgüdüm gerektirmez.** Herkes kendi işlemesinin kimliğini yerelde
   hesaplar; çakışma olasılığı karma fonksiyonunun çakışma direncine indirgenir.
2. **Kimlik, içeriğin bütünlük denetimidir.** Bir işlemenin herhangi bir baytı değişirse
   kimliği de değişir. Depodaki bir bozulma sessiz kalmaz.
3. **Kimlik sıra bilgisi taşımaz.** Bir karma değeri, başka bir karma değerinden "sonra"
   değildir. Sıra yalnızca öncül bağlarından, yani çizgenin kendisinden okunur.

Üçüncü sonuç, önceki dersteki topolojik sıra tartışmasını gerekli kılan şeydir: tarihçeyi
sıralamak, kimlikleri karşılaştırmakla değil, çizgeyi gezerek yapılır.

Kimliğin içerikten türetilmesi bir noktayı daha kesinleştirir: öncülün kimliği hesaba
girdiğine göre, geçmişteki bir işlemenin değiştirilmesi ondan sonraki bütün işlemelerin
kimliğini değiştirir. Tarihçe, ucundan geriye doğru birbirine mühürlenmiştir. Üçüncü konudaki
"işlemeyi değiştirme" ve "sıfırlama" derslerinde bu mühürlemenin sonuçları görülecektir.

#### Karma Fonksiyonundan Beklenen

Kimliğin içerikten türetilmesi, kullanılan karma fonksiyonuna belirli bir yük bindirir. Veri
Yapıları kursunda karma fonksiyonları sözlük yapılarının dağılım aracı olarak incelenmişti;
orada çakışma bir başarım sorunuydu, çözümü de zincirleme ya da açık adreslemeydi. Burada
çakışmanın çözümü yoktur: iki farklı içerik aynı kimliği üretirse depo, birini diğerinin
yerine koyabilir.

Bu nedenle beklenen özellik dağılım değil, **çakışma direncidir**: farklı iki içerik bulup
aynı kimliği üretmenin hesaplama açısından yapılabilir olmaması. Sıradan sağlama toplamları bu
özelliği taşımaz; kriptografik karma fonksiyonları taşımak üzere tasarlanır.

Özelliğin zamana bağlı olduğuna dikkat edilmelidir: bir karma fonksiyonuna karşı çakışma
üretme yöntemi bulunduğunda, o fonksiyona dayanan depoların daha güçlü bir fonksiyona
geçirilmesi gerekir. Depo biçiminin sürüm alanı taşıması ve nesne kimliği uzunluğunun biçime
bağlı olması, tam olarak bu geçişi mümkün kılmak içindir. Bu kursta gösterilen kimlikler
kırk onaltılık karakterden oluşur; başka bir karma fonksiyonu kullanan bir depoda uzunluk
farklıdır, model aynıdır.

#### Yedeklilik ve Arıza

Merkezî modelde sunucu tek hata noktasıdır. Sunucu erişilemezse yazma işlemleri durur;
sunucudaki veri kaybolursa ve yedeği yoksa tarihçe kaybolur. Çalışma kopyalarında yalnızca
son sürüm bulunduğu için geçmiş geri getirilemez.

Dağıtık modelde her kopya tam bir yedektir. Merkezî bir sunucu kullanılıyor olsa bile — ki
uygulamada çoğunlukla kullanılır — o sunucu bir eşgüdüm noktasıdır, tek nüsha değildir.
Tarihçenin kaybolması için bütün kopyaların kaybolması gerekir.

Buna karşılık dağıtık model iki bedel getirir:

- **Depolama.** Her katılımcı tarihçenin tamamını tutar. Uzun ömürlü ve büyük dosyalar içeren
  projelerde bu maliyet belirginleşir; tarihçeye giren büyük bir ikili dosya, sonradan
  silinse bile bütün kopyalarda kalır.
- **Erişim denetimi.** Tarihçenin tamamı her kopyada bulunduğuna göre, "bu dizini yalnızca
  belirli kişiler görsün" kısıtı depo düzeyinde uygulanamaz. Denetim, paylaşımın yapıldığı
  noktaya taşınır.

İkinci maddenin pratik sonucu, gizli bilgilerin bir depoya hiçbir zaman girmemesi gerektiğidir.
Bir parola işlendikten sonra silinse bile tarihçede durmaya devam eder ve deponun her
kopyasına yayılmıştır. Yoksayma kuralları dersi bu konuyu yeniden ele alacaktır.

#### Model Seçimi Neyi Belirler

İki model arasındaki seçim, aracın hangi işlemleri ucuz kıldığını belirler. Dağıtık modelde
işleme yazmak ağ gerektirmediği için ucuzdur; ucuz olduğu için sık yapılır; sık yapıldığı için
her işleme küçük ve tek amaçlı olabilir. Bir sonraki konuda anlatılacak "atomik işleme"
alışkanlığı, doğrudan bu maliyet yapısının sonucudur.

Aynı biçimde, tarihçenin tamamı yerelde bulunduğu için geçmişi sorgulamak ucuzdur. Bir satırın
hangi işlemede değiştiğini bulmak ağ gecikmesi içermez; bu da geçmişe bakmayı sıradan bir
okuma alışkanlığı hâline getirir.

#### Özet

- Merkezî modelde tarihçe tek sunucuda tutulur; katılımcıların elinde yalnızca çalışma
  kopyası bulunur.
- Dağıtık modelde her kopya tarihçenin tamamını içerir; ağ yalnızca paylaşım için gereklidir.
- Merkezî model artan sayıyla sürüm numarası verebilir; dağıtık modelde bunun için merkezî
  bir sayaç yoktur.
- Bu nedenle dağıtık sistemler kimliği içerikten türetir; kimlik aynı zamanda bütünlük
  denetimi sağlar ama sıra bilgisi taşımaz.
- Dağıtık modelin bedelleri depolama ve depo düzeyinde erişim denetiminin uygulanamamasıdır.

#### Sonraki Adım

Modelin sözcük dağarcığı tamamlandı. Sıradaki adım, bu modelin somut karşılığını kurmaktır:
boş bir dizini depoya dönüştürmek, oluşan `.git` dizininin içinde ne bulunduğunu görmek ve
yazarın kimliğini hangi yapılandırma katmanının belirlediğini anlamak. Sonraki ders kursun
örnek deposunu sıfırdan oluşturacak.

### Depo Oluşturma ve Yapılandırma

Source: https://academia.sh/tr/kurslar/surum-kontrolune-giris/depo-olusturma-ve-yapilandirma

Boş bir dizinin depoya dönüştürülmesi, `.git` dizininin içeriği ve sistem, kullanıcı ile depo düzeyindeki yapılandırma katmanlarının önceliği.

Önceki iki ders modeli kurdu: tarihçe bir yönlü çevrimsiz çizgedir ve dağıtık bir sistemde bu
çizgenin tamamı yerelde durur. Bu ders modeli somutlaştırır — kursun örnek deposu olan
`sozluk` projesi oluşturulur ve deponun disk üzerindeki karşılığı incelenir.

Yapılandırmayla başlamak gerekir, çünkü bir işlemenin yazarı yapılandırmadan okunur ve
yazar bilgisi işlemenin kimliğine girer.

#### Üç Yapılandırma Katmanı

Ayarlar üç ayrı dosyada tutulur ve dar kapsamlı olan geniş olanı örter:

| Katman | Kapsam | Seçenek |
|---|---|---|
| Sistem | Makinedeki tüm kullanıcılar | `--system` |
| Kullanıcı | Bir kullanıcının tüm depoları | `--global` |
| Depo | Yalnızca içinde bulunulan depo | `--local` |

Aynı anahtar birden çok katmanda tanımlıysa depo düzeyindeki değer geçerlidir. Bu, "genel
olarak şu kimlikle çalışırım, ama şu depoda başka bir kimlik kullanırım" ayrımını mümkün kılar.

Kullanıcı düzeyinde üç ayar yapılır:

```bash
git config --global user.name "Deniz Kaya"
git config --global user.email "deniz@ornek.test"
git config --global init.defaultBranch main
```

İlk ikisi işlemelerin yazar alanını doldurur; ikisi tanımlı değilse işleme yazma denemesi
hatayla durur. Üçüncüsü, yeni oluşturulan depoların ilk dalının adını belirler. **Dal
(branch)** kavramı Dallanma ve İşbirliği kursunun konusudur; burada yalnızca çıktılarda
görünecek bir ad olarak geçecektir.

Ayarların yazıldığı yer okunabilir:

```bash
git config --list --global
```

```
user.name=Deniz Kaya
user.email=deniz@ornek.test
init.defaultbranch=main
```

Anahtar adlarının bölüm ve ad kısımlarının büyük/küçük harf duyarsız olduğuna dikkat edin:
`init.defaultBranch` yazıldı, `init.defaultbranch` olarak listelendi. Değerler ise harfi
harfine korunur.

#### Tarihi Sabitlemek

Bir işlemenin kimliği yalnızca içeriğinden değil, yazarından ve tarihinden de hesaplanır;
aynı dosya farklı bir anda işlenirse farklı bir karma değeri çıkar. Bu kursta çıktılarınızın bu
derslerdekiyle aynı olması için yazar ve işleyen tarihini sabitleyen iki ortam değişkeni
verilir:

```bash
export GIT_AUTHOR_DATE="2024-03-04 09:12:00 +0300"
export GIT_COMMITTER_DATE="2024-03-04 09:12:00 +0300"
```

Değişkenler yalnızca açık olan terminal oturumunda geçerlidir. Sonraki derslerde işlemeler
farklı günlere yayıldığı için her işlemeden önce tarih bir kez daha yazılır; sabitlemeyi
bırakırsanız her şey çalışır, yalnızca karma değerleri ve tarihler derste görünenlerden
ayrışır.

#### Depoyu Oluşturmak

Depo, var olan bir dizin içinde kurulur:

```bash
mkdir sozluk
cd sozluk
git init
```

Komut tek satırlık bir onay yazar: `Initialized empty Git repository in` ifadesinin ardından
oluşturulan `.git` dizininin tam yolu gelir. Yol, komutun çalıştırıldığı dizine bağlı olduğu
için her sistemde farklıdır.

Bu andan sonra dizin bir depodur. Dizinin görünür içeriği değişmemiştir; eklenen tek şey
`.git` adlı gizli bir alt dizindir. Depo, o alt dizinin kendisidir: `.git` silinirse dosyalar
kalır, tarihçe gider.

#### `.git` Dizininin İçeriği

```bash
ls .git
```

```
branches
config
description
HEAD
hooks
info
objects
refs
```

Sekiz girdiden dördü bu kurs boyunca sürekli kullanılacaktır:

- **`objects`** — nesne veritabanı. Önceki derste anlatılan içerik adresli depolama burada
  gerçekleşir: dosya içerikleri, dizin görüntüleri ve işlemeler bu dizinde karma değerlerine
  göre adlandırılmış dosyalar hâlinde durur. Yeni bir depoda boştur.
- **`refs`** — insan tarafından okunabilir adları nesne kimliklerine bağlayan başvurular.
  `refs/heads` dal uçlarını, `refs/tags` etiketleri tutar. İkisi de başlangıçta boştur.
- **`HEAD`** — o an üzerinde çalışılan başvuruyu gösteren tek satırlık dosya.
- **`config`** — deponun kendi yapılandırması; üç katmanın en dar olanı.

Kalan dördü daha seyrek kullanılır: `hooks` belirli olaylarda çalıştırılacak betikleri, `info`
depoya özel yardımcı dosyaları, `description` yalnızca bazı sunucu arayüzlerinin okuduğu bir
tanım metnini tutar; `branches` ise eski bir düzenin kalıntısıdır ve bu kursta kullanılmaz.
Bu liste Linux'ta, GNU `ls` ve UTF-8 yerel ayarıyla alınmıştır: sıra yerel ayara bağlıdır
(`LC_COLLATE=C` ile `HEAD` başa gelir) ve girdi sayısı git sürümüne göre değişebilir. Sizin
çıktınız bu listeden küçük farklar gösterebilir; dört temel girdi her yerde vardır.

`HEAD` dosyası doğrudan okunabilir:

```bash
cat .git/HEAD
```

```
ref: refs/heads/main
```

İçerik bir nesne kimliği değil, bir başvuruya yapılan başvurudur. Henüz hiçbir işleme
yazılmadığı için `refs/heads/main` dosyası da yoktur; `HEAD` var olmayan bir hedefi gösterir.
Bu geçici tutarsızlık, ilk işleme yazıldığında giderilecektir.

#### Deponun Kendi Yapılandırması

```bash
cat .git/config
```

```
[core]
	repositoryformatversion = 0
	filemode = true
	bare = false
	logallrefupdates = true
```

Bu değerler depo oluşturulurken sistemden okunarak yazılır. `repositoryformatversion` depo
biçiminin sürümünü, `bare` deponun çalışma dizini olup olmadığını, `logallrefupdates`
başvuru değişikliklerinin günlüğe yazılıp yazılmayacağını belirtir. Yukarıdaki çıktı bir Linux
sisteminden alınmıştır; dosya adlarında büyük/küçük harf ayrımı yapmayan dosya sistemlerinde
(macOS ve Windows'un olağan yapılandırmaları) buraya `ignorecase = true` satırı da yazılır,
macOS üzerinde ayrıca `precomposeunicode = true` eklenir.

Depo düzeyine bir ayar yazmak için komut deponun içinden, `--local` seçeneğiyle çalıştırılır:

```bash
git config --local user.email "deniz@baska-kurum.ornek"
```

Bu satır yalnızca `sozluk` deposundaki işlemeleri etkiler; kullanıcı düzeyindeki değer diğer
depolarda geçerli kalır. Katmanların nasıl örtüştüğü böylece görülmüş oldu; bu kursta
işlemelerin tümü tek bir kimlikle yazılacağı için depo düzeyindeki ayarı hemen kaldırın:

```bash
git config --local --unset user.email
```

#### Deponun Kökü Nasıl Bulunur

Komutlar deponun kök dizininden çalıştırılmak zorunda değildir. Bir komut çalıştırıldığında,
içinde bulunulan dizinden başlanarak yukarı doğru `.git` aranır; bulunan ilk `.git` deponun
kökünü belirler.

Denemek için deponun içinde iki boş dizin açılır ve en alttakine girilir:

```bash
mkdir -p gecici/alt
cd gecici/alt
git rev-parse --show-toplevel
```

{/* mask: (?<=/tmp/ders-)[a-z0-9_]+ */}
```
/tmp/ders-p9bhqa2r/sozluk
```

Çıktı, deponun kök dizininin tam yoludur; kendi makinenizde yolun başı farklı olacaktır
(buradaki `/tmp/ders-…` kısmı bu dersin ölçüldüğü geçici dizindir). Alt bir dizinden
çalıştırıldığında da aynı değer döner; kökün neresi olduğu bulunulan yere göre değişmez.
Kök ile bulunulan yer arasındaki göreli yol ayrıca sorulabilir:

```bash
git rev-parse --show-prefix
```

```
gecici/alt/
```

Denemeden sonra köke dönülür ve boş dizinler silinir:

```bash
cd ../..
rmdir gecici/alt gecici
```

Arama yukarı doğru olduğu için, bir deponun içinde ikinci bir `git init` çalıştırmak beklenen
sonucu vermez: yeni bir `.git` oluşur ve o alt ağaç dıştaki depodan kopar. İç içe depo
gerektiren durumlar için ayrı düzenekler vardır; bu kursta tek bir depo kullanılacaktır.

Depo dışında çalıştırılan komut açık bir hata verir:

```
fatal: not a git repository (or any of the parent directories): .git
```

#### Bir Değerin Kaynağını Bulmak

Beklenmedik bir ayarın hangi katmandan geldiği doğrudan sorulabilir:

```bash
git config --list --show-origin --global
```

{/* mask: (?<=/tmp/ders-)[a-z0-9_]+ */}
```
file:/tmp/ders-p9bhqa2r/.ev/.gitconfig	user.name=Deniz Kaya
file:/tmp/ders-p9bhqa2r/.ev/.gitconfig	user.email=deniz@ornek.test
file:/tmp/ders-p9bhqa2r/.ev/.gitconfig	init.defaultbranch=main
```

Her satırın başında değerin okunduğu dosya yazar; buradaki yol dersin ölçüldüğü geçici
ev dizinidir, sizin çıktınızda kendi ev dizininizin `.gitconfig` dosyası görünür. Katman seçeneği
kaldırılırsa üç katmanın tamamı birleştirilmiş hâlde listelenir ve aynı anahtarın birden çok
satırda görünmesi mümkündür; bu durumda geçerli olan **son** satırdır.

Tek bir anahtarın geçerli değeri şöyle sorulur:

```bash
git config user.name
```

```
Deniz Kaya
```

#### İlk Durum

```bash
git status
```

```
On branch main

No commits yet

nothing to commit (create/copy files and use "git add" to track)
```

Üç satır üç ayrı bilgi verir. Birincisi, `HEAD` dosyasının gösterdiği başvurunun adıdır.
İkincisi, `refs/heads/main` başvurusunun henüz bir nesneye bağlanmadığını söyler. Üçüncüsü,
çalışma dizininde kayda alınacak hiçbir şey bulunmadığını bildirir.

`git status` bu kursun en sık çalıştırılacak komutudur. Her seferinde aynı soruyu yanıtlar:
çalışma dizini, hazırlık alanı ve son işleme arasında hangi farklar var? Sonraki konu bu üç
bölgeyi tek tek tanımlayacaktır.

#### Özet

- Yapılandırma sistem, kullanıcı ve depo katmanlarında tutulur; dar kapsam geniş kapsamı örter.
- `user.name` ve `user.email` tanımlı değilse işleme yazılamaz; bu değerler işlemenin
  kimliğine girer.
- `git init`, var olan bir dizinde `.git` alt dizinini oluşturur; depo o alt dizindir.
- `.git/objects` nesne veritabanını, `.git/refs` adlandırılmış başvuruları, `.git/HEAD` o an
  çalışılan başvuruyu tutar.
- `--show-origin`, bir ayarın hangi dosyadan geldiğini gösterir.

#### Sonraki Adım

Depo kuruldu ama boş. Bir dosya oluşturulduğunda ne olur — dosya doğrudan tarihçeye mi girer,
yoksa arada bir aşama mı vardır? Sonraki ders, çalışma dizini ile nesne veritabanı arasında
duran hazırlık alanını tanımlayacak ve bu alanın `.git` içindeki karşılığını gösterecek.

## Temel Döngü

Üç bölgeli model, atomik işleme alışkanlığı, işleme mesajı yazımı, tarihçe okuma, fark inceleme ve yoksayma kuralları.

### Çalışma Dizini ve Hazırlık Alanı

Source: https://academia.sh/tr/kurslar/surum-kontrolune-giris/calisma-dizini-ve-hazirlik-alani

Üç bölgeli modelin tanımı, `git add` komutunun nesne veritabanına ve hazırlık alanı dosyasına yaptığı iki ayrı yazma, blob nesnesi ve içerik adresli depolamanın gözle doğrulanması.

Depo kuruldu ve boş. Bir dosya oluşturulduğunda ne olacağı sorusu açık kaldı: dosya doğrudan
tarihçeye mi girer? Yanıt hayırdır. Çalışma dizini ile tarihçe arasında üçüncü bir bölge
vardır ve bu bölge, `git` ile çalışmayı diğer birçok sürüm kontrol aracından ayıran temel
tasarım kararıdır.

Bu ders o bölgeyi tanımlar, disk üzerindeki karşılığını gösterir ve bir dosya içeriğinin
nesne veritabanında nasıl adlandırıldığını hesap yaparak doğrular.

#### Üç Bölge

```
  çalışma dizini          hazırlık alanı           nesne veritabanı
  (dosyalar)              (.git/index)             (.git/objects)
        │                       │                          │
        │──── git add ─────────>│                          │
        │                       │──── git commit ─────────>│
```

**Çalışma dizini (working directory)**, dosyaların düzenlenebilir hâlidir — metin
düzenleyicisinin gördüğü şey. **Hazırlık alanı (staging area)**, bir sonraki işlemeye
girecek içeriğin toplandığı ara bölgedir. **Nesne veritabanı**, kalıcı kayıtların tutulduğu
yerdir.

Ara bölgenin varlığı bir kolaylık değil, bir yetkidir: işlemenin içeriği, çalışma dizininin o
anki hâline mahkûm olmaktan çıkar. Çalışma dizininde beş dosya değişmişse bunlardan ikisi
hazırlık alanına alınıp ayrı bir işleme olarak kaydedilebilir. Sonraki derste anlatılacak
atomik işleme alışkanlığı bu yetkiye dayanır.

#### İlk Dosyalar

Örnek depoya iki dosya eklenir. Dosyalar terminalden oluşturulur: `cat > dosya <<'SON'`
satırı, `SON` yazan satıra kadar olan metni dosyaya yazar; tırnak içindeki `'SON'` kabuğun
metne dokunmamasını sağlar. Birincisi projeyi tanıtan `README.md`:

```bash
cat > README.md <<'SON'
# Sözlük

Bilgisayar bilimi terimlerinin Türkçe karşılıklarını tutan küçük bir liste.

## Biçim

`terimler.txt` dosyasında her satır şu biçimdedir:

    turkce | english
SON
```

İkincisi terim listesinin kendisi, `terimler.txt`:

```bash
cat > terimler.txt <<'SON'
yığıt | stack
kuyruk | queue
çizge | graph
SON
```

Depo bu dosyalardan haberdar değildir:

```bash
git status
```

```
On branch main

No commits yet

Untracked files:
  (use "git add <file>..." to include in what will be committed)
	README.md
	terimler.txt

nothing added to commit but untracked files present (use "git add" to track)
```

**İzlenmeyen (untracked)** dosya, hazırlık alanında kaydı bulunmayan dosyadır. Depo onu
görür ama izlemez; içeriği değişse bile bildirmez.

#### `git add` İki İş Yapar

```bash
git add README.md
git status --short
```

```
A  README.md
?? terimler.txt
```

Kısa gösterimde her satırın başında iki sütun bulunur. **Birinci sütun hazırlık alanı ile son
işleme arasındaki farkı**, **ikinci sütun çalışma dizini ile hazırlık alanı arasındaki farkı**
gösterir. `A` "eklendi", `M` "değiştirildi", `D` "silindi", `??` "izlenmiyor" anlamına gelir.
`A` birinci sütunda ve ikinci sütun boş olduğuna göre: dosya hazırlık alanına alınmış ve
çalışma dizinindeki hâliyle aynıdır.

Komut iki ayrı yazma yaptı. Birincisi nesne veritabanına:

```bash
find .git/objects -type f
```

```
.git/objects/49/daf9067744c72d7f5427d163f983c326ff37b5
```

Dosyanın içeriği, henüz hiçbir işleme yazılmamış olmasına rağmen kalıcı olarak saklandı. Bu
nesne bir **blob**'dur: yalnızca bayt dizisi tutan, dosya adı ve izin bilgisi içermeyen nesne
türü. Adı, içeriğinden hesaplanmıştır; dizin adı karma değerinin ilk iki karakteri, dosya adı
kalanıdır.

İkinci yazma hazırlık alanınadır:

```bash
git ls-files -s
```

```
100644 49daf9067744c72d7f5427d163f983c326ff37b5 0	README.md
```

Bu satır hazırlık alanının bir girdisidir: dosya kipi, blob kimliği, aşama numarası ve yol.
Dosya kipi `100644` sıradan dosyayı, `100755` çalıştırılabilir dosyayı belirtir. Aşama
numarası birleştirme çakışmalarında kullanılır ve olağan durumda sıfırdır.

İkinci dosya da eklenir:

```bash
git add terimler.txt
git ls-files -s
```

```
100644 49daf9067744c72d7f5427d163f983c326ff37b5 0	README.md
100644 9b9ef7052d54292add1ed75823a454c1fe66e3bb 0	terimler.txt
```

#### Hazırlığa Alma Biçimleri

Dosyaları tek tek yazmak dışında toplu biçimler de vardır ve kapsamları farklıdır:

| Yazım | Kapsam |
|---|---|
| `git add <yol>` | Verilen yol |
| `git add .` | Bulunulan dizin ve altı |
| `git add -A` | Deponun tamamı, bulunulan dizinden bağımsız |
| `git add -p` | Değişikliklerin parça parça seçilmesi |

İlk iki biçim arasındaki fark alt dizinlerde belirginleşir. Kök dizinde bir dosya silinmiş,
`yeni` adlı alt dizinde bir dosya oluşturulmuş olsun. Bu durumu `sozluk` deposunu bozmadan
denemek için yanında atılabilir bir depo açılır; silinecek dosyanın izlenen bir dosya
olabilmesi için içine bir işleme de yazılır:

```bash
git init -q ../deneme
cd ../deneme
cp ../sozluk/terimler.txt .
git add terimler.txt
git commit -q -m "Deneme deposunun ilk işlemesi"
rm terimler.txt
mkdir yeni
echo "merhaba" > yeni/a.txt
```

Şimdi alt dizine girip komutu oradan çalıştırın. Alt dizinden çalıştırılan komut silmeyi
kapsamaz:

```bash
cd yeni
git add .
git status --short
```

```
 D ../terimler.txt
A  a.txt
```

Silme işareti ikinci sütunda kaldı: hazırlık alanına alınmadı. Kökten çalıştırılan `-A` biçimi
her ikisini de alır (kısa gösterimde yollar bulunulan dizine göre yazıldığından önce köke
çıkılır):

```bash
cd ..
git add -A
git status --short
```

```
D  terimler.txt
A  yeni/a.txt
```

Deneme bitti; atılabilir depo silinir ve `sozluk` dizinine dönülür:

```bash
cd ../sozluk
rm -rf ../deneme
```

Dördüncü biçim, tek bir dosyadaki değişikliklerin bir bölümünü hazırlık alanına almayı sağlar:
komut, farkın her parçasını sırayla sunar ve her biri için alınıp alınmayacağını sorar. Hazırlık
alanının verdiği seçme yetkisi burada dosya düzeyinden satır düzeyine iner; bir dosyada
birbirinden bağımsız iki düzeltme yapılmışsa bunlar ayrı işlemelere bölünebilir.

#### Hazırlık Alanı Bir Dosyadır

Hazırlık alanı soyut bir kavram değil, `.git/index` adlı ikili bir dosyadır. İngilizce
belgelerde *index* adıyla anılır. İçinde, izlenen her yol için bir girdi bulunur: yol adı,
kip, blob kimliği ve dosya sisteminden okunan bazı ön bellek alanları.

Bu son alanlar `git status` komutunun hızını belirler. Çalışma dizinindeki her dosyanın
içeriğini yeniden karma değerinden geçirmek yerine, dosyanın boyutu ve değişiklik zamanı
hazırlık alanındaki kayıtla karşılaştırılır; ikisi de aynıysa dosya değişmemiş sayılır.
Kayıt sayısı arttıkça bu ön belleğin değeri artar.

Hazırlık alanının tuttuğu şeyin **düzenlenmiş bir dosya listesi** olduğuna dikkat edin: hangi
yolun hangi içeriğe bağlı olduğunu söyler. Bu yapı, bir sonraki derste anlatılacak ağaç
nesnesinin doğrudan öncülüdür.

#### Kimlik Nereden Geliyor

Blob kimliği, dosya içeriğinin ham karma değeri değildir. Nesnenin önüne türünü ve uzunluğunu
bildiren bir başlık eklenir, karma değeri bu bütün üzerinden hesaplanır. Başlığın biçimi
şudur: nesne türü, bir boşluk, bayt cinsinden uzunluk ve bir sıfır baytı.

Bu hesap dışarıdan yapılabilir. Sekiz baytlık bir içerik ele alalım:

```bash
printf 'merhaba\n' | git hash-object --stdin
```

```
e995d8e1c89654fd0a6453c2da61fb6e9da262e6
```

Aynı değer, başlık elle eklenerek ve genel amaçlı bir karma aracıyla da elde edilir:

```bash
printf 'blob 8\0merhaba\n' | shasum
```

```
e995d8e1c89654fd0a6453c2da61fb6e9da262e6  -
```

İki değer aynıdır. `shasum` komutu SHA-1 özetini üretir; GNU araç kümesinde aynı iş `sha1sum`
ile yapılır.

Bu hesabın iki sonucu vardır. Birincisi, aynı içerik iki farklı adla saklansa bile tek bir
nesne oluşturur; kimlik dosya adına değil içeriğe bağlıdır. İkincisi, nesnenin bir baytı
değişirse kimliği tanınmaz biçimde değişir — Veri Yapıları kursunda tanımlanan çığ etkisi.

Nesnenin türü ve boyutu doğrudan sorulabilir:

```bash
git cat-file -t 49daf9067744c72d7f5427d163f983c326ff37b5
git cat-file -s 49daf9067744c72d7f5427d163f983c326ff37b5
```

```
blob
187
```

Bu kimlik `README.md` dosyasının o andaki içeriğine aittir; kendi deponuzda dosyayı harfi
harfine aynı yazmadığınız sürece farklı bir değer göreceksiniz. Kurs boyunca gösterilen bütün
nesne kimlikleri aynı kuralla üretilmiştir.

#### Özet

- Çalışma dizini düzenlenen dosyaları, hazırlık alanı bir sonraki işlemeye girecek içeriği,
  nesne veritabanı kalıcı kayıtları tutar.
- `git add` iki iş yapar: içeriği blob olarak nesne veritabanına yazar ve yolu blob kimliğine
  bağlayan bir girdiyi hazırlık alanına koyar.
- Hazırlık alanı `.git/index` dosyasıdır; yol, kip ve blob kimliğinden oluşan girdileri tutar.
- Blob kimliği, tür ve uzunluk başlığı eklenmiş içeriğin karma değeridir; içerik aynıysa
  kimlik de aynıdır.
- Kısa durum gösteriminde birinci sütun hazırlık alanını, ikinci sütun çalışma dizinini anlatır.

#### Sonraki Adım

Hazırlık alanında iki girdi var ama tarihçe hâlâ boş; `git log` çalıştırılsa yanıt
alınamazdı. Sonraki ders hazırlık alanının içeriğini kalıcı bir kayda dönüştürecek, bu
sırada oluşan ağaç ve işleme nesnelerini açıp inceleyecek ve bir işlemenin ne zaman "tek bir
iş" sayıldığını tanımlayacak.

### Değişiklikleri İşleme

Source: https://academia.sh/tr/kurslar/surum-kontrolune-giris/degisiklikleri-isleme

Hazırlık alanının kalıcı kayda dönüşmesi; ağaç ve işleme nesnelerinin içeriği, dört nesne türü, başvuruların rolü ve atomik işleme alışkanlığı.

Hazırlık alanında iki girdi bulunuyor, ancak tarihçe hâlâ boş. Bu ders o iki girdiyi kalıcı
bir kayda dönüştürür ve kayıt sırasında oluşan nesneleri tek tek açar. Sonunda, bir işlemenin
neden "tek bir iş" içermesi gerektiği tartışılacaktır.

#### İlk İşleme

Önceki dersteki `GIT_AUTHOR_DATE` ve `GIT_COMMITTER_DATE` değişkenleri açık oturumda hâlâ
tanımlıdır; yeni bir terminal açtıysanız onları aynı değerlerle yeniden yazın.

```bash
git commit -m "Terim listesini ve biçim belgesini ekle"
```

```
[main (root-commit) 13d31bf] Terim listesini ve biçim belgesini ekle
 2 files changed, 12 insertions(+)
 create mode 100644 README.md
 create mode 100644 terimler.txt
```

Köşeli parantez içindeki `root-commit`, bu işlemenin öncülü olmadığını — çizgenin kaynağı
olduğunu — bildirir. `13d31bf`, işleme kimliğinin kısaltılmış hâlidir. Kimlik yazardan,
zamandan, mesajdan ve içerikten hesaplandığı için kendi deponuzda başka bir değer görürsünüz;
kurs boyunca gösterilen bütün kimlikler için bu geçerlidir.

```bash
git status
```

```
On branch main
nothing to commit, working tree clean
```

Üç bölge de aynı içeriği gösteriyor: çalışma dizini, hazırlık alanı ve son işleme örtüşüyor.

#### İşleme Nesnesinin İçi

İşleme, nesne veritabanında saklanan bir metindir ve doğrudan okunabilir:

```bash
git cat-file -p HEAD
```

```
tree 378e434005c6c42021d4398a15e89149b0fd8671
author Deniz Kaya <deniz@ornek.test> 1709532720 +0300
committer Deniz Kaya <deniz@ornek.test> 1709532720 +0300

Terim listesini ve biçim belgesini ekle
```

Dört bileşen vardır:

- **`tree`** — projenin o andaki tam görüntüsünü tutan ağaç nesnesinin kimliği.
- **`author`** ve **`committer`** — değişikliği yazan ve kaydeden kişi, ardından Unix zaman
  damgası ve saat dilimi kayması. İki alanın neden ayrı olduğu üçüncü konuda görülecektir.
- **Boş satırdan sonraki metin** — işleme mesajı.

Kök işleme dışındaki her işlemede bir de `parent` satırı bulunur. Öncül işlemenin kimliği
metnin içinde yer aldığına göre, kimlik hesabına da girer: geçmişteki bir işlemenin
değiştirilmesi ondan sonraki tüm kimlikleri değiştirir.

#### Ağaç Nesnesi

```bash
git ls-tree HEAD
```

```
100644 blob 49daf9067744c72d7f5427d163f983c326ff37b5	README.md
100644 blob 9b9ef7052d54292add1ed75823a454c1fe66e3bb	terimler.txt
```

**Ağaç nesnesi (tree object)** bir dizinin içeriğini tutar: her satırda kip, girdi türü, nesne
kimliği ve ad bulunur. Girdi türü `blob` ise bir dosya, `tree` ise bir alt dizin söz konusudur.
Alt dizinler kendi ağaç nesnelerine bağlanır; böylece proje dizini, kökü işlemenin gösterdiği
ağaç olan bir ağaç yapısına dönüşür. Veri Yapıları kursundaki terimlerle: iç düğümler ağaç
nesneleri, yapraklar bloblardır.

Blob kimliklerinin hazırlık alanındaki değerlerle aynı olduğuna dikkat edin. `git commit`
yeni blob yazmadı; hazırlık alanının girdilerini bir ağaç nesnesine dönüştürdü ve bu ağacı
işaret eden bir işleme nesnesi oluşturdu.

```bash
find .git/objects -type f | sort
```

```
.git/objects/13/d31bf17fdc8a5292b7fff288de94088d5c1440
.git/objects/37/8e434005c6c42021d4398a15e89149b0fd8671
.git/objects/49/daf9067744c72d7f5427d163f983c326ff37b5
.git/objects/9b/9ef7052d54292add1ed75823a454c1fe66e3bb
```

Dört nesne: iki blob, bir ağaç, bir işleme.

#### Dört Nesne Türü

| Tür | Tuttuğu şey | Neye bağlanır |
|---|---|---|
| blob | Dosya içeriği | — |
| ağaç | Bir dizinin girdileri | Bloblara ve alt ağaçlara |
| işleme | Bir anlık görüntü ve üstverisi | Bir ağaca ve öncül işlemelere |
| etiket | Adlandırılmış bir işaret ve notu | Genellikle bir işlemeye |

Dördü de aynı biçimde saklanır: tür ve uzunluk başlığı, ardından içerik, kimlik ise bu bütünün
karma değeri. Dördüncü tür kursun son dersinde ele alınacaktır.

#### Başvurular

İşleme kimliğinin kırk karakterlik bir karma değeri olması, insanın bu değeri akılda tutmasını
gerektirmez. Başvurular bu boşluğu doldurur:

```bash
cat .git/refs/heads/main
```

```
13d31bf17fdc8a5292b7fff288de94088d5c1440
```

`refs/heads/main` dosyası tek bir satır içerir: bir işleme kimliği. Önceki derste `HEAD`
dosyasının bu başvuruyu gösterdiği görülmüştü. Zincir şudur: `HEAD` → `refs/heads/main` →
işleme → ağaç → bloblar.

```bash
git rev-parse HEAD
```

```
13d31bf17fdc8a5292b7fff288de94088d5c1440
```

`git rev-parse`, bir adı nesne kimliğine çeviren komuttur. `HEAD`, `HEAD~1` (bir önceki
işleme), `main` gibi adların tümü bu yolla çözülür.

#### Atomik İşleme

Örnek projeye arama betiği eklenir. `ara.sh` oluşturulur ve çalıştırma izni verilir:

```bash
cat > ara.sh <<'SON'
#!/bin/sh
# terimler.txt içinde arama yapar.

if [ $# -ne 1 ]; then
    echo "kullanım: ara.sh ARANAN" >&2
    exit 1
fi

grep -- "$1" terimler.txt
SON
chmod +x ara.sh
```

Betik yazılırken `README.md` içindeki biçim örneğinde bir yazım hatası fark edilir ve
`turkce | english` satırı `türkçe | english` olarak düzeltilir:

```bash
sed 's/turkce | english/türkçe | english/' README.md > README.yeni
mv README.yeni README.md
```

Çalışma dizininde artık iki ilgisiz değişiklik vardır:

```bash
git status --short
```

```
 M README.md
?? ara.sh
```

Bu ikisini tek işlemede kaydetmek, tarihçeye "yeni betik ve bir yazım düzeltmesi" biçiminde
bulanık bir kayıt bırakır. **Atomik işleme**, tek bir amaca hizmet eden en küçük tutarlı
değişiklik kümesidir. Ölçütü şudur: işleme geri alındığında geriye tutarlı bir durum kalmalı
ve geri alma, amaçlanandan fazlasını götürmemelidir.

Hazırlık alanı bu ayrımı mümkün kılar. Bu işleme ilkinden bir buçuk saat sonra yapılmış
olsun; tarih değişkenleri yeni saate çekilir (bundan sonra her işlemeden önce bu yapılacaktır):

```bash
export GIT_AUTHOR_DATE="2024-03-04 10:40:00 +0300" GIT_COMMITTER_DATE="2024-03-04 10:40:00 +0300"
git add ara.sh
git commit -m "Terim arama betiği ekle"
```

```
[main 546c174] Terim arama betiği ekle
 1 file changed, 9 insertions(+)
 create mode 100755 ara.sh
```

`create mode 100755` satırı, dosyanın çalıştırma izniyle kaydedildiğini gösterir; izin bilgisi
ağaç nesnesinde tutulur ve tarihçenin parçasıdır.

İkinci değişiklik ayrı kaydedilir. İzlenen dosyalardaki değişiklikler `-a` seçeneğiyle hazırlık
alanına alınmadan doğrudan işlenebilir:

```bash
export GIT_AUTHOR_DATE="2024-03-04 10:52:00 +0300" GIT_COMMITTER_DATE="2024-03-04 10:52:00 +0300"
git commit -a -m "Biçim örneğindeki yazımı düzelt"
```

```
[main 3132c78] Biçim örneğindeki yazımı düzelt
 1 file changed, 1 insertion(+), 1 deletion(-)
```

`-a` seçeneği yalnızca izlenen dosyaları kapsar; izlenmeyen bir dosya bu yolla işlemeye
girmez. Kolaylığı, hazırlık alanının sağladığı seçme yetkisini devre dışı bırakması pahasına
gelir — bu nedenle birden çok konuya dokunulan durumlarda kullanılmamalıdır.

#### Değişmeyen İçerik Yeniden Yazılmaz

```bash
git ls-tree HEAD
```

```
100644 blob c0a6e3d5d4d0a0d117519512a1fb771c8a60bfee	README.md
100755 blob 4bc98c87b25ceac31de2e48015e81a943d2e73c8	ara.sh
100644 blob 9b9ef7052d54292add1ed75823a454c1fe66e3bb	terimler.txt
```

`terimler.txt` blobu ilk işlemedeki değerin aynısıdır: `9b9ef70`. Üç işleme boyunca dosya
değişmediği için tek bir nesne üç ağaç tarafından paylaşılmaktadır. Anlık görüntü modelinin
"her kayıtta tüm dosyalar yeniden yazılır mı" itirazına verilen yanıt budur: aynı içerik aynı
kimliği ürettiğinden, ikinci kez yazılacak bir şey yoktur.

#### Özet

- `git commit`, hazırlık alanının girdilerini bir ağaç nesnesine dönüştürür ve bu ağacı
  gösteren bir işleme nesnesi yazar.
- İşleme nesnesi bir ağaç kimliği, yazar ve işleyen bilgisi, mesaj ve (kök işleme dışında)
  öncül kimliklerini içerir.
- Ağaç nesnesi bir dizinin girdilerini tutar; alt dizinler kendi ağaç nesnelerine bağlanır.
- Dört nesne türü vardır: blob, ağaç, işleme, etiket. Tümü tür ve uzunluk başlıklı içeriğin
  karma değeriyle adlandırılır.
- Atomik işleme, geri alındığında tutarlı bir durum bırakan en küçük değişiklik kümesidir;
  hazırlık alanı bu bölmeyi mümkün kılar.

#### Sonraki Adım

Üç işleme yazıldı ve üçünün de mesajı tek satırlık. Bir düzeltmenin nedeni, denenip
vazgeçilen seçenekler ya da bir kararın gerekçesi tek satıra sığmaz. Sonraki ders, işleme
mesajının yapısını — konu satırı, gövde ve gerekçe — ve bu yapının tarihçeyi okunabilir kılan
kurallarını ele alacak.

### İşleme Mesajı Yazımı

Source: https://academia.sh/tr/kurslar/surum-kontrolune-giris/isleme-mesaji-yazimi

Konu satırı, boş ayırıcı ve gövdeden oluşan mesaj yapısı; gerekçenin kaydedilmesi ve mesaj biçiminin araçlar tarafından nasıl kullanıldığı.

Üç işleme yazıldı ve üçünün de mesajı tek satırdı. Küçük değişikliklerde bu yeterlidir; ancak
bir düzeltmenin nedeni, denenip vazgeçilen seçenekler ya da bir tasarım kararının gerekçesi
tek satıra sığmaz. Bu ders mesajın yapısını tanımlar.

**İşleme mesajı (commit message)** biçimsel bir zorunluluk değil, tarihçenin okunabilirliğini belirleyen tek
serbest metin alanıdır. Bir satırın *ne* yaptığı koddan okunur; *neden* öyle yazıldığı yalnızca
mesajdan okunur.

#### Mesajın Yapısı

Mesaj üç bölümden oluşur:

```
Konu satırı: değişikliğin özeti

Gövde: değişikliğin gerekçesi. Sorunun ne olduğu, neden bu çözümün
seçildiği, hangi seçeneklerin elendiği burada yazılır.

İkinci paragraf gerekirse eklenir.
```

Bölümleri ayıran şey **ilk boş satırdır** ve bu ayırıcı biçimsel bir kuraldır: araçlar ilk
satırı konu, boş satırdan sonrasını gövde olarak okur. Boş satır konmazsa metnin tamamı konu
sayılır ve özet listelerinde tek satıra sıkıştırılır.

#### Konu Satırı

Konu satırı için dört kural yerleşmiştir:

1. **Emir kipinde yazılır.** "Terim listesini sırala", "Sıralandı" ya da "Terim listesini
   sıraladım" değil. Gerekçesi biçimseldir: araçların ürettiği mesajlar da emir kipindedir
   (`Revert "…"`, `Merge …`), böylece tarihçe tek bir dilbilgisi kipiyle okunur. Zihinsel
   testi şudur: konu satırı, "Uygulandığında bu işleme şunu yapar: …" cümlesini tamamlamalıdır.
2. **Elli karakter civarında tutulur.** Kesin bir sınır yoktur; ancak özet listelerinde ve
   dar arayüzlerde satır kırpılır. Elli karaktere sığmayan bir konu satırı çoğu zaman
   işlemenin birden çok iş içerdiğinin göstergesidir.
3. **Nokta ile bitirilmez.** Başlık işlevi görür, cümle değildir.
4. **Neyin değiştiğini söyler, nasılını değil.** Ayrıntı gövdenin işidir.

#### Gövde

Gövdede yanıtlanan soru "ne yapıldı" değil, **"neden yapıldı"**dır. Değişikliğin kendisi zaten
farkta görünür; farkta görünmeyen şey, o değişikliği gerektiren durumdur.

Yararlı bir gövde şunları içerir:

- **Sorunun tanımı.** Hangi davranış yanlıştı ya da hangi ihtiyaç karşılanmıyordu?
- **Çözümün gerekçesi.** Neden bu yol seçildi?
- **Elenen seçenekler.** Denenip vazgeçilen bir yaklaşım varsa, aynı yolun yeniden denenmesini
  önler.
- **Bilinen sınırlar.** Çözümün kapsamadığı durumlar.

Satırlar yetmiş iki karakter civarında elle kırılır. Nedeni, `git log` çıktısının mesaj
gövdesini dört boşluk girintiyle yazmasıdır: seksen sütunluk bir alanda taşmayı önlemek için
gövdenin kendisi daha dar olmalıdır.

#### Örnek

Terim listesine üç terim eklenir ve mesaj yazılır. `git commit` seçenek verilmeden
çalıştırıldığında yapılandırılmış metin düzenleyicisi açılır; kaydedilip kapatıldığında içerik
mesaj olur. Boş bırakılırsa işleme yazılmaz. Burada düzenleyici yerine `-F -` kullanılır: mesaj
standart girdiden okunur, böylece aşağıdaki komut tek başına çalıştırılabilir. Önceki üç
işleme 4 Mart 2024'te yazılmıştı; bu işleme ertesi güne düştüğü için tarih önce güncellenir:

```bash
export GIT_AUTHOR_DATE="2024-03-05 09:05:00 +0300"
export GIT_COMMITTER_DATE="2024-03-05 09:05:00 +0300"
cat >> terimler.txt <<'SON'
ağaç | tree
karma tablosu | hash table
bağlı liste | linked list
SON
git add terimler.txt
git commit -q -F - <<'MSG'
Üç veri yapısı terimi ekle

Ağaç, karma tablosu ve bağlı liste terimleri listede yoktu; bu terimler
sorulduğunda arama betiği boş çıktı veriyordu.

Karşılıklar Veri Yapıları kursunun sözlüğüyle aynı biçimde yazıldı.
MSG
```

`-q` seçeneği işlemenin özet çıktısını bastırır; sonuç aşağıda `git log` ile okunacaktır. Konu
satırı ne yapıldığını söylüyor; gövde, terimlerin *neden* eksik sayıldığını ve karşılıkların
kaynağını kaydediyor. İkisi de koddan çıkarılamayacak bilgilerdir.

İkinci bir örnek, arama betiğindeki bir düzeltmeye aittir. Betiğin `grep` çağrısına `-i`
eklenir ve işleme aynı gün öğleden sonra yazılır:

```bash
export GIT_AUTHOR_DATE="2024-03-05 14:20:00 +0300"
export GIT_COMMITTER_DATE="2024-03-05 14:20:00 +0300"
cat > ara.sh <<'SON'
#!/bin/sh
# terimler.txt içinde arama yapar.

if [ $# -ne 1 ]; then
    echo "kullanım: ara.sh ARANAN" >&2
    exit 1
fi

grep -i -- "$1" terimler.txt
SON
git commit -q -a -F - <<'MSG'
Aramayı büyük/küçük harften bağımsız yap

Terimler listede küçük harfle tutuluyor. Kullanıcı "Yığıt" yazdığında
arama boş dönüyor, terim listede olduğu hâlde bulunamıyordu.

grep çağrısına -i seçeneği eklendi; bu seçenek POSIX'te tanımlıdır ve
ek bağımlılık getirmez.
MSG
```

Bu mesajın kaydettiği bilgi, tek satırlık farkın kendisinden daha değerlidir: `-i` seçeneğinin
neden eklendiği ve neden bir başka çözümün (örneğin listeyi büyük harfe çevirmenin)
seçilmediği yazılıdır.

İki işlemenin mesajında ayrımın araçlar tarafından nasıl kullanıldığı doğrudan görülebilir.
`%s` konu satırını, `%b` gövdeyi verir:

```bash
git log -1 --format='%s' 43370ca
```

```
Üç veri yapısı terimi ekle
```

```bash
git log -1 --format='%b' 43370ca
```

```
Ağaç, karma tablosu ve bağlı liste terimleri listede yoktu; bu terimler
sorulduğunda arama betiği boş çıktı veriyordu.

Karşılıklar Veri Yapıları kursunun sözlüğüyle aynı biçimde yazıldı.
```

#### Ne Yazılmaz

Bazı mesaj kalıpları tarihçeye bilgi eklemez:

- **İçeriği yineleyen konu satırları.** "terimler.txt güncellendi" — farkta zaten görünen
  bilgidir. Dosya adı değil, yapılan iş yazılır.
- **Durum bildiren kalıplar.** "yarım", "geçici", "düzeltme". Bunlar işlemenin ne yaptığını
  söylemez ve tarihçede aranabilir bir iz bırakmaz.
- **Bağlamsız dış numara.** Yalnızca bir kayıt numarası içeren mesaj, o kayıt sistemine
  erişimi olmayan okur için boştur. Numara yazılacaksa gövdeye, sorunun bir cümlelik özetiyle
  birlikte konur.
- **Birden çok işi sayan konu satırları.** "X eklendi ve Y düzeltildi" cümlesindeki "ve",
  işlemenin bölünmesi gerektiğinin işaretidir.

Son madde, işleme mesajının atomik işleme alışkanlığıyla nasıl bağlandığını gösterir: iyi bir
konu satırı yazılamıyorsa sorun çoğu zaman mesajda değil, işlemenin kapsamındadır.

#### Mesajın Verilme Yolları

| Yol | Kullanım |
|---|---|
| `git commit` | Düzenleyici açılır; çok satırlı mesaj için olağan yol |
| `git commit -m "konu"` | Tek satırlık mesaj |
| `git commit -m "konu" -m "gövde"` | Her `-m` bir paragraf olur, aralarına boş satır konur |
| `git commit -F dosya` | Mesaj bir dosyadan okunur |

Düzenleyicide açılan şablonda `#` ile başlayan satırlar bulunur; bunlar mesaja dâhil edilmez
ve o anki durumu özetler. Yazmadan önce bu özeti okumak, yanlış dosyaların hazırlık alanına
alındığını fark etmenin en ucuz yoludur.

#### Sonuç

```bash
git log --oneline
```

```
60e13bd Aramayı büyük/küçük harften bağımsız yap
43370ca Üç veri yapısı terimi ekle
3132c78 Biçim örneğindeki yazımı düzelt
546c174 Terim arama betiği ekle
13d31bf Terim listesini ve biçim belgesini ekle
```

Beş satır, projenin beş adımını okunur biçimde anlatıyor. Bu okunabilirlik doğrudan iki
alışkanlığın sonucudur: her işlemenin tek bir iş içermesi ve her konu satırının o işi emir
kipinde özetlemesi. İkisinden biri bozulduğunda liste değerini yitirir.

#### Mesaj Bir Arama Alanıdır

Mesajlar yalnızca okunmaz, aranır da. Konu ve gövde metni üzerinde süzme yapılabilir:

```bash
git log --oneline --grep="arama"
```

```
60e13bd Aramayı büyük/küçük harften bağımsız yap
43370ca Üç veri yapısı terimi ekle
546c174 Terim arama betiği ekle
```

Arama harfi harfine yapılır; sözcük kökü tanınmaz. Türkçede bu ayrıntı belirginleşir:

```bash
git log --oneline --grep="betik"
```

Komut hiçbir satır döndürmez, oysa tarihçede "Terim arama betiği ekle" işlemesi bulunur.
Neden, ünsüz yumuşamasıdır: "betiği" sözcüğü "betik" dizisini içermez. Kısaltılmış bir örüntü
sonucu verir:

```bash
git log --oneline --grep="beti"
```

```
43370ca Üç veri yapısı terimi ekle
546c174 Terim arama betiği ekle
```

Bu davranış, konu satırlarında değişken ek almayan sözcüklerin tercih edilmesini pratik bir
gereklilik hâline getirir.

#### Özet

- Mesaj, konu satırı ve gövdeden oluşur; ikisini ilk boş satır ayırır ve bu ayrım araçlar
  tarafından kullanılır.
- Konu satırı emir kipinde, elli karakter civarında ve noktasız yazılır.
- Gövde "ne" değil "neden" sorusunu yanıtlar: sorunun tanımı, çözümün gerekçesi, elenen
  seçenekler ve bilinen sınırlar.
- Gövde satırları yetmiş iki karakter civarında kırılır; `git log` çıktısı gövdeyi girintili
  yazar.
- Mesajlar `--grep` ile aranabilir; bu, konu satırlarının tutarlı yazılmasını pratik bir
  gereklilik hâline getirir.

#### Sonraki Adım

Tarihçe beş işlemeye ulaştı ve `git log --oneline` ile listelendi. Ancak listeleme,
tarihçeyi okumanın yalnızca en basit biçimidir: belirli bir dosyaya dokunan işlemeler, belirli
bir metni ekleyen ya da silen işlemeler ve belirli bir zaman aralığı ayrı ayrı sorgulanabilir.
Sonraki ders tarihçe okuma araçlarını ele alacak.

### Tarihçeyi Okuma

Source: https://academia.sh/tr/kurslar/surum-kontrolune-giris/tarihceyi-okuma

Günlük çıktısının biçimlendirilmesi; yol, içerik, yazar ve zamana göre süzme; aralık gösterimi ve işleme çizgesinin doğrudan okunması.

Tarihçe beş işlemeye ulaştı. `git log --oneline` bu beş satırı listelemeye yetiyor; ancak
tarihçe büyüdükçe soru değişir. "Son beş işleme neydi" yerine "bu dosyaya kim dokundu", "bu
satır ne zaman eklendi", "iki sürüm arasında ne oldu" sorulur. Bu ders o soruları yanıtlayan
süzme ve biçimlendirme araçlarını ele alır.

#### Varsayılan Biçim

```bash
git log -1
```

```
commit 60e13bdaf4dd2f895e9b562c4a8ee9ea289d2af7
Author: Deniz Kaya <deniz@ornek.test>
Date:   Tue Mar 5 14:20:00 2024 +0300

    Aramayı büyük/küçük harften bağımsız yap

    Terimler listede küçük harfle tutuluyor. Kullanıcı "Yığıt" yazdığında
    arama boş dönüyor, terim listede olduğu hâlde bulunamıyordu.

    grep çağrısına -i seçeneği eklendi; bu seçenek POSIX'te tanımlıdır ve
    ek bağımlılık getirmez.
```

Varsayılan biçim kimliği tam uzunlukta, yazarı ve tarihi ayrı satırlarda, mesajın tamamını
girintili verir. `-1` seçeneği çıktıyı tek işlemeyle sınırlar; `-n` ile herhangi bir sayı
verilebilir.

Çıktıda görünen kimlik, tarih ve yazar alanları depoya özeldir. Aynı komutları kendi
deponuzda çalıştırdığınızda kimlikler ve tarihler farklı olacaktır; sabit olan çıktının
yapısıdır.

#### Özet Biçimler

```bash
git log --oneline
```

```
60e13bd Aramayı büyük/küçük harften bağımsız yap
43370ca Üç veri yapısı terimi ekle
3132c78 Biçim örneğindeki yazımı düzelt
546c174 Terim arama betiği ekle
13d31bf Terim listesini ve biçim belgesini ekle
```

Kısaltılmış kimlik, kimliğin benzersizliği korunacak kadar uzun tutulur; depo büyüdükçe
uzunluk artabilir. Kısa kimlik, komutlarda tam kimliğin yerine kullanılabilir.

`--graph` seçeneği tarihçenin çizge yapısını sol kenarda çizer:

```bash
git log --oneline --graph
```

```
* 60e13bd Aramayı büyük/küçük harften bağımsız yap
* 43370ca Üç veri yapısı terimi ekle
* 3132c78 Biçim örneğindeki yazımı düzelt
* 546c174 Terim arama betiği ekle
* 13d31bf Terim listesini ve biçim belgesini ekle
```

Bu tarihçede dallanma bulunmadığından çizim tek sütundur. Dallanma varsa sütunlar çoğalır ve
birleşme noktaları görünür hâle gelir; Dallanma ve İşbirliği kursunda bu çıktı okunacaktır.

#### Biçimlendirme Dizgileri

Çıktının alanları tek tek seçilebilir:

```bash
git log --pretty=format:'%h %ad %s' --date=short
```

```
60e13bd 2024-03-05 Aramayı büyük/küçük harften bağımsız yap
43370ca 2024-03-05 Üç veri yapısı terimi ekle
3132c78 2024-03-04 Biçim örneğindeki yazımı düzelt
546c174 2024-03-04 Terim arama betiği ekle
13d31bf 2024-03-04 Terim listesini ve biçim belgesini ekle
```

Sık kullanılan alanlar:

| Dizge | Karşılığı |
|---|---|
| `%H` / `%h` | İşleme kimliği / kısaltılmışı |
| `%T` | Ağaç nesnesinin kimliği |
| `%P` | Öncül işlemelerin kimlikleri |
| `%an` / `%ae` | Yazarın adı / e-postası |
| `%ad` / `%cd` | Yazar tarihi / işleyen tarihi |
| `%s` / `%b` | Konu satırı / gövde |

`--date` seçeneği tarih biçimini belirler: `short` yalnızca günü, `iso` tam zaman damgasını
ve saat dilimini verir.

#### Değişiklik İstatistiği

```bash
git log --oneline --stat
```

```
60e13bd Aramayı büyük/küçük harften bağımsız yap
 ara.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
43370ca Üç veri yapısı terimi ekle
 terimler.txt | 3 +++
 1 file changed, 3 insertions(+)
3132c78 Biçim örneğindeki yazımı düzelt
 README.md | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
546c174 Terim arama betiği ekle
 ara.sh | 9 +++++++++
 1 file changed, 9 insertions(+)
13d31bf Terim listesini ve biçim belgesini ekle
 README.md    | 9 +++++++++
 terimler.txt | 3 +++
 2 files changed, 12 insertions(+)
```

Her işlemenin altında dokunduğu dosyalar ve eklenen/silinen satır sayıları listelenir. Bir
işlemenin `--stat` çıktısı uzunsa, o işleme büyük olasılıkla birden çok işi birleştirmiştir:
istatistik, atomik işleme alışkanlığının denetim aracıdır.

#### Yol Süzmesi

Belirli bir dosyaya dokunan işlemeler:

```bash
git log --oneline -- ara.sh
```

```
60e13bd Aramayı büyük/küçük harften bağımsız yap
546c174 Terim arama betiği ekle
```

İki tireden oluşan ayırıcı, kendisinden sonrasının yol olduğunu bildirir. Ayırıcı olmazsa
`ara.sh` bir başvuru adı olarak yorumlanmaya çalışılır; aynı adı taşıyan bir dal ve bir dosya
bulunduğunda komut belirsizleşir. Ayırıcıyı her zaman yazmak bu belirsizliği ortadan kaldırır.

#### İçerik Süzmesi

Bir metnin tarihçeye ne zaman girdiğini ya da ne zaman çıktığını bulmak için:

```bash
git log --oneline -S 'grep -i'
```

```
60e13bd Aramayı büyük/küçük harften bağımsız yap
```

`-S` seçeneği, verilen dizginin **geçiş sayısını değiştiren** işlemeleri bulur. Yani dizgiyi
içeren işlemeleri değil, dizgiyi ekleyen ya da silen işlemeleri döndürür. Bir davranışın
kaynağını ararken en dolaysız araçtır: aranan şey satırın kendisi değil, satırın doğduğu andır.

#### Yazar ve Zaman Süzmesi

```bash
git log --oneline --since="2024-03-05 00:00"
```

```
60e13bd Aramayı büyük/küçük harften bağımsız yap
43370ca Üç veri yapısı terimi ekle
```

`--since` verilen andan sonrasını, `--until` öncesini seçer. Tarihe saat de eklendiğinde sınır
kesinleşir; yalnızca gün verilen kısa yazımlar farklı yorumlanabilir.

Katkı dağılımı için ayrı bir komut vardır:

```bash
git shortlog -sn HEAD
```

```
     5	Deniz Kaya
```

`-s` yalnızca sayıyı, `-n` sayıya göre azalan sıralamayı ister. Komut bir başvuru verilmediğinde
girdisini standart girdiden okur; bu nedenle betiklerde `HEAD` açıkça yazılmalıdır.

#### Aralık Gösterimi

İki nokta, bir işleme kümesini tanımlar. `A..B`, "B'den erişilebilen ama A'dan erişilemeyen
işlemeler" anlamına gelir:

```bash
git log --oneline HEAD~2..HEAD
```

```
60e13bd Aramayı büyük/küçük harften bağımsız yap
43370ca Üç veri yapısı terimi ekle
```

`HEAD~2` gösterimi "iki öncül geriye" demektir. Tanım çizge üzerinden verilmiştir: erişilebilirlik,
öncül kenarları izleyerek gidilebilen düğümler kümesidir. Bu nedenle aralık gösterimi
dallanmış tarihçelerde de anlamlıdır; iki dalın ayrıştığı noktadan sonrasını sormak aynı
gösterimle yapılır.

#### Tek Bir İşlemeyi Görmek

```bash
git show --stat 43370ca
```

```
commit 43370ca23c4b30992ea9857c6282416de8e0a816
Author: Deniz Kaya <deniz@ornek.test>
Date:   Tue Mar 5 09:05:00 2024 +0300

    Üç veri yapısı terimi ekle

    Ağaç, karma tablosu ve bağlı liste terimleri listede yoktu; bu terimler
    sorulduğunda arama betiği boş çıktı veriyordu.

    Karşılıklar Veri Yapıları kursunun sözlüğüyle aynı biçimde yazıldı.

 terimler.txt | 3 +++
 1 file changed, 3 insertions(+)
```

`git show` bir nesneyi türüne uygun biçimde gösterir: işleme için üstveri ve fark, ağaç için
girdi listesi, blob için ham içerik.

#### Çizgeyi Doğrudan Okumak

Biçimlendirme dizgileri, tarihçenin çizge yapısını çıplak hâlde vermeye de yarar:

```bash
git log --format='%h %T %P'
```

```
60e13bd d23f16ee3533d05e3afd189a11551b6ec89f0898 43370ca23c4b30992ea9857c6282416de8e0a816
43370ca 8074917cfe2b0200648feaeeaf612170157dcc95 3132c7841e3e63c5eb968e37b301aa64dd1e8fb0
3132c78 01426328c4d751777bad684a17c7bc7941589603 546c174a007fdea08f907bd4d428cc87ce7e6148
546c174 21f7408f587a9837da6ae2ba960c74b756c79858 13d31bf17fdc8a5292b7fff288de94088d5c1440
13d31bf 378e434005c6c42021d4398a15e89149b0fd8671
```

Her satır bir düğümü, üçüncü sütun o düğümün kenarını verir. Son satırda üçüncü sütun boştur:
kök işlemenin öncülü yoktur. Birinci sütundaki değerler ikinci satırdan itibaren üçüncü
sütunda yeniden görünür; liste, çizgenin kenar listesi gösterimidir. Veri Yapıları kursunda
tanımlanan üç çizge gösteriminden biri burada doğrudan karşımıza çıkmaktadır.

#### Özet

- Varsayılan günlük biçimi kimliği, yazarı, tarihi ve mesajın tamamını verir; `--oneline`
  bunları tek satıra indirir.
- `--pretty=format:` ile alanlar tek tek seçilir; `%H`, `%T`, `%P` işleme, ağaç ve öncül
  kimliklerini verir.
- `--stat` işleme başına dokunulan dosyaları ve satır sayılarını gösterir.
- Yol süzmesi iki tireli ayırıcıyla, içerik süzmesi `-S` ile yapılır; `-S` bir dizginin geçiş
  sayısını değiştiren işlemeleri bulur.
- `A..B` gösterimi, B'den erişilebilen ama A'dan erişilemeyen işlemeleri tanımlar.

#### Sonraki Adım

Günlük, hangi işlemenin hangi dosyaya dokunduğunu söylüyor ama değişikliğin içeriğini
göstermiyor. Üstelik henüz işlenmemiş değişiklikler günlükte hiç görünmez. Sonraki ders üç
bölge arasındaki farkları — çalışma dizini ile hazırlık alanı, hazırlık alanı ile son işleme,
iki işleme arası — ayrı ayrı almayı ve fark çıktısının biçimini okumayı ele alacak.

### Farkları İnceleme

Source: https://academia.sh/tr/kurslar/surum-kontrolune-giris/farklari-inceleme

Çalışma dizini, hazırlık alanı ve işlemeler arasındaki üç ayrı karşılaştırma; birleşik fark biçiminin okunması ve nesne düzeyinde fark alma.

Günlük, hangi işlemenin hangi dosyaya dokunduğunu söylüyor ama değişikliğin içeriğini
göstermiyor. Üstelik henüz işlenmemiş değişiklikler günlükte hiç görünmez: çalışma dizinindeki
bir düzenleme, işlenene kadar tarihçenin dışındadır.

Bu ders **fark (diff)** almanın üç ayrı biçimini tanımlar ve fark çıktısının nasıl okunacağını
gösterir. Üç bölgeli model burada pratik değerini kazanır: hangi iki bölgenin karşılaştırıldığı
sorusu, hangi seçeneğin yazılacağını belirler.

#### Üç Karşılaştırma

| Komut | Karşılaştırılan | Yanıtladığı soru |
|---|---|---|
| `git diff` | Çalışma dizini ↔ hazırlık alanı | Henüz hazırlığa almadığım ne var? |
| `git diff --staged` | Hazırlık alanı ↔ son işleme | Bir sonraki işlemeye ne girecek? |
| `git diff HEAD` | Çalışma dizini ↔ son işleme | Son işlemeden bu yana toplam ne değişti? |

Üçüncü satır, ilk ikisinin birleşimidir. `--staged` seçeneğinin eş anlamlısı `--cached`'dir;
kurs boyunca ilki kullanılacaktır.

#### Çalışma Dizini ile Hazırlık Alanı

Arama betiği, eşleşme bulunamadığında sessiz kalıyor ve sıfır çıkış koduyla sonlanıyor. Betik
şu hâle getirilir. Dosya aynı adla yeniden yazılır; `cat >` var olan dosyanın içeriğini
değiştirir, çalıştırma izni korunur:

```bash
cat > ara.sh <<'SON'
#!/bin/sh
# terimler.txt içinde arama yapar.

if [ $# -ne 1 ]; then
    echo "kullanım: ara.sh ARANAN" >&2
    exit 1
fi

if ! grep -i -- "$1" terimler.txt; then
    echo "eşleşme yok: $1" >&2
    exit 2
fi
SON
```

```bash
git diff
```

```
diff --git a/ara.sh b/ara.sh
index b87baa8..582ddde 100755
--- a/ara.sh
+++ b/ara.sh
@@ -6,4 +6,7 @@ if [ $# -ne 1 ]; then
     exit 1
 fi
 
-grep -i -- "$1" terimler.txt
+if ! grep -i -- "$1" terimler.txt; then
+    echo "eşleşme yok: $1" >&2
+    exit 2
+fi
```

#### Fark Çıktısının Anatomisi

Çıktı **birleşik fark biçimindedir (unified diff)** ve dört bölümden oluşur.

**Başlık satırı.** `diff --git a/ara.sh b/ara.sh` — karşılaştırılan iki sürüm `a/` ve `b/`
önekleriyle adlandırılır. `a` eski, `b` yeni taraftır.

**Nesne satırı.** `index b87baa8..582ddde 100755` — eski ve yeni blob kimlikleri ile dosya
kipi. Bu satır, farkın nesne veritabanındaki hangi iki nesne arasında hesaplandığını
kaydeder. Kip her iki tarafta aynıysa satırın sonunda tek bir değer yazar; kip değişmişse iki
ayrı satır eklenir.

**Dosya satırları.** `---` eski, `+++` yeni sürümü gösterir. Yeni oluşturulan bir dosyada
eski taraf `/dev/null` olur.

**Parça başlığı.** Değişikliğin geçtiği her bölgeye **parça (hunk)** denir ve her parça bir
başlıkla açılır. `@@ -6,4 +6,7 @@` — dört sayı taşır: eski dosyanın 6. satırından başlayan
4 satır, yeni dosyanın 6. satırından başlayan 7 satırla değiştirilmiştir. Başlığın sonundaki
`if [ $# -ne 1 ]; then` metni, değişikliğin bağlamını veren en yakın üst satırdır; farkın
parçası değildir.

Parça içindeki satırlar üç işaretle başlar: boşluk (değişmemiş bağlam satırı), `-` (silinen),
`+` (eklenen). Bağlam satırları varsayılan olarak üç satırdır; `-U` seçeneğiyle değiştirilir.
Değiştirilen bir satır, fark biçiminde silme ve ekleme çifti olarak görünür — biçimde
"değiştirme" diye bir işlem yoktur.

#### Hazırlık Alanı ile Son İşleme

```bash
git add ara.sh
git diff
```

Komut hiçbir şey yazmaz: çalışma dizini ile hazırlık alanı artık aynıdır. Fark yer değiştirmiştir:

```bash
git diff --staged
```

```
diff --git a/ara.sh b/ara.sh
index b87baa8..582ddde 100755
--- a/ara.sh
+++ b/ara.sh
@@ -6,4 +6,7 @@ if [ $# -ne 1 ]; then
     exit 1
 fi
 
-grep -i -- "$1" terimler.txt
+if ! grep -i -- "$1" terimler.txt; then
+    echo "eşleşme yok: $1" >&2
+    exit 2
+fi
```

`git add` içeriği taşımadı; hazırlık alanının hangi bloba baktığını değiştirdi. Farkın kendisi
aynı iki nesne arasında hesaplandığı için çıktı harfi harfine aynıdır.

#### İki Bölge Aynı Anda

Terim listesine bir satır eklenir ama hazırlık alanına alınmaz:

```bash
echo "küme | set" >> terimler.txt
git status --short
```

```
M  ara.sh
 M terimler.txt
```

İki sütunun anlamı burada belirginleşir: `ara.sh` birinci sütunda (hazırlığa alınmış),
`terimler.txt` ikinci sütunda (yalnızca çalışma dizininde) işaretlidir.

```bash
git diff
```

```
diff --git a/terimler.txt b/terimler.txt
index 11660ec..17af3b8 100644
--- a/terimler.txt
+++ b/terimler.txt
@@ -4,3 +4,4 @@ kuyruk | queue
 ağaç | tree
 karma tablosu | hash table
 bağlı liste | linked list
+küme | set
```

`git diff` yalnızca `terimler.txt` değişikliğini, `git diff --staged` yalnızca `ara.sh`
değişikliğini gösterir. İkisini birden görmek için `HEAD` ile karşılaştırılır:

```bash
git diff HEAD --stat
```

```
 ara.sh       | 5 ++++-
 terimler.txt | 1 +
 2 files changed, 5 insertions(+), 1 deletion(-)
```

`--stat`, satır satır çıktı yerine dosya başına özet verir. Artı ve eksi işaretlerinden oluşan
çubuk, eklenen ve silinen satırların oranını ölçekli gösterir; büyük farklarda toplam sayı
sabit genişliğe sığdırılır.

#### İki İşleme Arasındaki Fark

İki başvuru verildiğinde fark, ilkinden ikincisine geçişi anlatır:

```bash
git diff 13d31bf 60e13bd -- terimler.txt
```

```
diff --git a/terimler.txt b/terimler.txt
index 9b9ef70..11660ec 100644
--- a/terimler.txt
+++ b/terimler.txt
@@ -1,3 +1,6 @@
 yığıt | stack
 kuyruk | queue
 çizge | graph
+ağaç | tree
+karma tablosu | hash table
+bağlı liste | linked list
```

Sıra önemlidir: `git diff B A`, aynı farkı ters yönde gösterir. Yol ayırıcısı burada da
çıktıyı tek dosyayla sınırlamak için kullanılmıştır.

#### Nesne Düzeyinde Fark

Karşılaştırma başvurularla sınırlı değildir; `başvuru:yol` yazımı, o başvurudaki belirli bir
nesneyi adlandırır:

```bash
git diff 13d31bf:README.md 3132c78:README.md
```

```
diff --git a/README.md b/README.md
index 49daf90..c0a6e3d 100644
--- a/README.md
+++ b/README.md
@@ -6,4 +6,4 @@ Bilgisayar bilimi terimlerinin Türkçe karşılıklarını tutan küçük bir l
 
 `terimler.txt` dosyasında her satır şu biçimdedir:
 
-    turkce | english
+    türkçe | english
```

Bu yazım, dosya adı iki sürüm arasında değişmiş olsa bile karşılaştırma yapmayı sağlar.

#### Sözcük Düzeyinde Fark

Satır tabanlı fark, uzun satırlarda küçük bir değişikliği tüm satırın silinip yeniden
eklenmesi olarak gösterir. `--word-diff` bu durumda okunabilirliği artırır:

```bash
git diff --word-diff HEAD -- terimler.txt
```

```
diff --git a/terimler.txt b/terimler.txt
index 11660ec..17af3b8 100644
--- a/terimler.txt
+++ b/terimler.txt
@@ -4,3 +4,4 @@ kuyruk | queue
ağaç | tree
karma tablosu | hash table
bağlı liste | linked list
{+küme | set+}
```

Eklenen bölüm `{+ +}`, silinen bölüm `[- -]` içine alınır. Sunum biçimi değişmiştir; farkın
kendisi ve kaydedilecek içerik aynıdır.

#### Değişikliklerin Kaydedilmesi

İki değişiklik ayrı işlemelere ayrılır. İşlemeler ertesi güne, 6 Mart 2024'e düştüğü için her
işlemeden önce tarih yeniden yazılır:

```bash
export GIT_AUTHOR_DATE="2024-03-06 11:00:00 +0300"
export GIT_COMMITTER_DATE="2024-03-06 11:00:00 +0300"
git commit -m "Eşleşme bulunamadığında hata bildir"
export GIT_AUTHOR_DATE="2024-03-06 11:18:00 +0300"
export GIT_COMMITTER_DATE="2024-03-06 11:18:00 +0300"
git commit -a -m "Küme terimini ekle"
```

```
[main 2c883a7] Eşleşme bulunamadığında hata bildir
 1 file changed, 4 insertions(+), 1 deletion(-)
[main ece664b] Küme terimini ekle
 1 file changed, 1 insertion(+)
```

Birinci komut hazırlık alanındaki `ara.sh` değişikliğini kaydetti; ikincisi `-a` seçeneğiyle
kalan izlenen değişikliği aldı.

#### Özet

- `git diff` çalışma dizini ile hazırlık alanını, `--staged` hazırlık alanı ile son işlemeyi,
  `HEAD` ile çağrılan biçim ikisini birden karşılaştırır.
- Birleşik fark çıktısı başlık, nesne, dosya ve parça satırlarından oluşur; parça başlığı
  eski ve yeni taraftaki başlangıç satırı ile satır sayısını verir.
- Biçimde "değiştirme" işlemi yoktur; değişen satır bir silme ve bir ekleme olarak görünür.
- İki başvuru verilerek işlemeler arası, `başvuru:yol` yazımıyla nesneler arası fark alınır.
- `--stat` dosya başına özet, `--word-diff` sözcük düzeyinde gösterim verir.

#### Sonraki Adım

Depoda yalnızca elle yazılan dosyalar bulunuyor. Oysa çalışırken üretilen dosyalar da oluşur:
betiğin çıktısı, düzenleyicinin bıraktığı yedekler, derleme sonuçları. Bunların tarihçeye
girmesi hem gürültü hem de risktir. Sonraki ders, hangi dosyaların depodan uzak tutulacağını
belirleyen yoksayma kurallarını ve kuralların izlenen dosyalara neden işlemediğini ele alacak.

### Yoksayma Kuralları

Source: https://academia.sh/tr/kurslar/surum-kontrolune-giris/yoksayma-kurallari

Depoya girmemesi gereken dosyalar, `.gitignore` kalıp söz dizimi, kuralın kaynağını bulma ve yoksayma kurallarının izlenen dosyalara neden işlemediği.

Depoda şimdiye kadar yalnızca elle yazılan dosyalar bulunuyor. Oysa çalışırken üretilen
dosyalar da oluşur: betiğin çıktısı, düzenleyicinin bıraktığı yedekler, derleme sonuçları.
Bunlar her `git status` çağrısında listelenerek gerçek değişikliklerin görünürlüğünü düşürür
ve yanlışlıkla işlemeye girebilir.

Bu ders, hangi dosyaların depodan uzak tutulacağını ve bu kararın nasıl kaydedileceğini ele
alır.

#### Depoya Girmemesi Gerekenler

Dört sınıf ayrılır:

- **Türetilmiş dosyalar.** Depodaki kaynaklardan üretilebilen her şey: derleme çıktıları,
  betiklerin ürettiği veriler, geçici raporlar. Tarihçede tutulmaları gereksizdir, çünkü
  kaynaktan yeniden üretilebilirler; üstelik her üretimde değiştikleri için sürekli fark
  gösterirler.
- **Yerel ortam dosyaları.** Düzenleyici ayarları, işletim sisteminin dizinlere bıraktığı
  üstveri dosyaları, kişisel notlar. Bunlar projeye değil kişiye aittir.
- **Gizli bilgiler.** Parolalar, erişim anahtarları, özel sertifikalar. Bunların depoya
  girmemesi bir düzen sorunu değil, güvenlik gereğidir.
- **Büyük ikili dosyalar.** Her sürümü ayrı bir nesne olarak saklanır ve fark alınamadığı için
  sıkıştırılamaz. Deponun tüm kopyalarında yer kaplarlar.

Üçüncü madde ayrı bir uyarı gerektirir. Önceki konuda belirtildiği gibi, dağıtık bir depoda
tarihçe her kopyaya yayılır. Bir parola işlendikten sonra silinse bile silme işlemi yalnızca
yeni bir işleme ekler; parolayı içeren eski işleme yerinde durur ve deponun her kopyasında
bulunur. Bu durumda tek doğru davranış, gizli bilginin geçersiz kılınmasıdır.

#### `.gitignore` Dosyası

Örnek depoda betik çalıştırıldığında bir günlük dosyası ve bir çıktı dizini oluşur;
düzenleyici de bir yedek bırakır. Bunları elle üretmek için betik iki kez çalıştırılır ve
`README.md` dosyasının bir yedeği alınır:

```bash
mkdir cikti
./ara.sh stack > cikti/son-arama.txt
./ara.sh queue > ara.log
cp README.md "README.md~"
```

Durum şimdi şöyle görünür:

```bash
git status --short
```

```
?? README.md~
?? ara.log
?? cikti/
```

Kurallar `.gitignore` adlı bir metin dosyasına yazılır:

```bash
cat > .gitignore <<'SON'
# Betiğin ürettiği çıktılar
ara.log
cikti/

# Düzenleyici yedekleri
*~
SON
```

```bash
git status --short
```

```
?? .gitignore
```

Üç girdi listeden çıktı; geriye kuralları taşıyan dosyanın kendisi kaldı. `.gitignore`
depoya işlenir: kurallar projeye aittir ve deponun her kopyasında aynı olmalıdır.

```bash
export GIT_AUTHOR_DATE="2024-03-06 16:35:00 +0300"
export GIT_COMMITTER_DATE="2024-03-06 16:35:00 +0300"
git add .gitignore
git commit -m "Üretilen dosyaları yoksayma listesine al"
```

```
[main 9b23cc3] Üretilen dosyaları yoksayma listesine al
 1 file changed, 6 insertions(+)
 create mode 100644 .gitignore
```

#### Kalıp Söz Dizimi

Her satır bir **kalıptır (pattern)**: yol adlarıyla eşleştirilen, joker karakterler içerebilen
bir dizgi.

| Kalıp | Anlamı |
|---|---|
| `*.log` | Uzantısı `.log` olan dosyalar, her derinlikte |
| `cikti/` | Yalnızca `cikti` adlı dizinler ve içerikleri |
| `/gecici.tmp` | Yalnızca depo kökündeki `gecici.tmp` |
| `not?.txt` | Tek karakter joker: `not1.txt`, `not2.txt` |
| `a/**/veri.bin` | `a` altında herhangi bir derinlikteki `veri.bin` |
| `!ara.log` | Önceki bir kuralın kapsadığı dosyayı kural dışı bırakır |
| `# metin` | Açıklama satırı |

İki ayrıntı sık karıştırılır. Birincisi **eğik çizginin konumu**: kalıbın içinde ya da başında
eğik çizgi varsa kalıp `.gitignore` dosyasının bulunduğu dizine göre çözülür; yoksa her
derinlikte eşleşir. `/gecici.tmp` yalnızca kökteki dosyayı yakalar, `alt/gecici.tmp` dosyasını
yakalamaz. İkincisi **sondaki eğik çizgi**: `cikti/` yalnızca dizinlerle eşleşir, `cikti` adlı
bir dosyayla eşleşmez.

Kurallar sırayla değerlendirilir ve **son eşleşen kural** geçerlidir. Bu nedenle `!` ile başlayan
kural, kapsadığı kalıptan sonra yazılmalıdır; önce yazılırsa etkisiz kalır.

#### Bir Dosya Neden Yoksayılıyor

Uzun kural listelerinde hangi satırın etkili olduğu doğrudan sorulur:

```bash
git check-ignore -v ara.log cikti/son-arama.txt "README.md~"
```

```
.gitignore:2:ara.log	ara.log
.gitignore:3:cikti/	cikti/son-arama.txt
.gitignore:6:*~	README.md~
```

Her satır kuralın bulunduğu dosyayı, satır numarasını, kalıbı ve eşleşen yolu verir. `!` ile
başlayan bir kural eşleşiyorsa o da listelenir; bu durumda dosya yoksayılmıyor demektir, çünkü
son eşleşen kural onu kural dışı bırakmıştır.

Yoksayılan dosyaların tamamı da listelenebilir:

```bash
git status --short --ignored
```

```
!! README.md~
!! ara.log
!! cikti/
```

`!!` işareti yoksayılan girdileri belirtir.

#### Yoksayma İzlenen Dosyalara İşlemez

Yerel notların tutulduğu bir dosya yanlışlıkla işlenir. Önce dosya oluşturulur ve tarih
bir sonraki güne alınır:

```bash
cat > notlar-yerel.md <<'SON'
# Yerel notlar
Yarın: karma tablosu örneğini gözden geçir.
Kitap: bölüm 4'ü bitir.
SON
export GIT_AUTHOR_DATE="2024-03-07 09:10:00 +0300"
export GIT_COMMITTER_DATE="2024-03-07 09:10:00 +0300"
git add notlar-yerel.md
git commit -m "Yerel notları ekle"
```

```
[main 7e44d29] Yerel notları ekle
 1 file changed, 3 insertions(+)
 create mode 100644 notlar-yerel.md
```

Hata fark edilir ve dosya adı `.gitignore` dosyasına eklenir:

```bash
echo "notlar-yerel.md" >> .gitignore
```

Ancak durum değişmez:

```bash
git ls-files
```

```
.gitignore
README.md
ara.sh
notlar-yerel.md
terimler.txt
```

Dosya hâlâ izleniyor. Kuralın işlememesi bir kusur değil, tanımın sonucudur: yoksayma
kuralları **izlenmeyen** dosyaların listelenip listelenmeyeceğini belirler. Bir dosya hazırlık
alanında kayıtlıysa artık izlenmektedir ve kurallar onu ilgilendirmez. Aksi hâlde bir kural
eklemek, izlenen dosyaların sessizce tarihçeden düşmesine yol açardı.

Aynı nedenle `git check-ignore` de sessiz kalır: komut varsayılan olarak izlenen yolları
değerlendirmez.

Çözüm, dosyayı hazırlık alanından çıkarmaktır:

```bash
git rm --cached notlar-yerel.md
```

```
rm 'notlar-yerel.md'
```

`--cached` seçeneği yalnızca hazırlık alanındaki kaydı siler; çalışma dizinindeki dosya yerinde
kalır. Seçenek yazılmazsa dosya diskten de silinir.

```bash
export GIT_AUTHOR_DATE="2024-03-07 09:25:00 +0300"
export GIT_COMMITTER_DATE="2024-03-07 09:25:00 +0300"
git commit -a -m "Yerel notları izlemeden çıkar"
```

```
[main d3ab7b0] Yerel notları izlemeden çıkar
 2 files changed, 1 insertion(+), 3 deletions(-)
 delete mode 100644 notlar-yerel.md
```

Bu işlemeden sonra dosya izlenmiyor ve `.gitignore` kuralı devreye giriyor. Dosyanın eski
içeriği ise tarihçede duruyor: `7e44d29` işlemesi hâlâ erişilebilir. Yoksayma, geçmişi
temizlemez; yalnızca bundan sonrasını düzenler.

#### Üç Yoksayma Katmanı

| Yer | Kapsam | Paylaşılır mı |
|---|---|---|
| `.gitignore` | Bulunduğu dizin ve altı | Evet, depoya işlenir |
| `.git/info/exclude` | Yalnızca bu depo | Hayır, yerelde kalır |
| `core.excludesFile` ile gösterilen dosya | Kullanıcının tüm depoları | Hayır |

Ayrım şu ölçütle yapılır: kural **projeye** mi yoksa **çalışma alışkanlığına** mı aittir?
Derleme çıktısının adı projeye aittir ve `.gitignore` dosyasına yazılır. Kullanılan
düzenleyicinin bıraktığı geçici dosyalar kişiye aittir; bunları her projenin `.gitignore`
dosyasına eklemek yerine kullanıcı düzeyindeki dosyaya yazmak doğru olanıdır.

Depoya özel ama paylaşılmayacak kurallar `.git/info/exclude` dosyasına yazılır ve aynı söz
dizimini kullanır. Bir kural eklenir ve hangi dosyadan geldiği sorulur:

```bash
echo 'deneme-*.txt' >> .git/info/exclude
git check-ignore -v deneme-1.txt
```

```
.git/info/exclude:7:deneme-*.txt	deneme-1.txt
```

Çıktının ilk alanı kuralın hangi dosyadan geldiğini gösterdiği için, üç katman arasındaki
karışıklık aynı komutla çözülür.

#### Özet

- Türetilmiş dosyalar, yerel ortam dosyaları, gizli bilgiler ve büyük ikili dosyalar depoya
  girmemelidir.
- Kurallar `.gitignore` dosyasına yazılır; dosya depoya işlenir ve tüm kopyalarda geçerlidir.
- Kalıplarda eğik çizginin konumu kapsamı belirler; sondaki eğik çizgi kalıbı dizinlerle
  sınırlar; son eşleşen kural geçerlidir.
- Yoksayma kuralları yalnızca izlenmeyen dosyaları etkiler; izlenen bir dosya `git rm --cached`
  ile izlemeden çıkarılmalıdır.
- Kurallar üç katmanda tutulabilir: depoya işlenen, depoya özel yerel ve kullanıcı düzeyindeki
  dosyalar.

#### Sonraki Adım

Temel döngü tamamlandı: değişiklik yapılıyor, hazırlık alanına alınıyor, işleniyor, tarihçe
okunuyor. Ancak bu döngü tek yönlü anlatıldı. Yanlış bir dosya hazırlık alanına alındığında,
bir düzenleme geri istendiğinde ya da bir işleme hatalı yazıldığında ne yapılır? Sonraki konu
geri alma araçlarını ele alıyor ve ilk ders en dar kapsamlı olanlarla — hazırlıktan çıkarma ve
dosya geri yükleme — başlıyor.

## Geri Alma

Hazırlıktan çıkarma, dosya geri yükleme, işlemeyi değiştirme, sıfırlama kipleri, devirme, zula ve etiketleme.

### Hazırlıktan Çıkarma ve Dosya Geri Yükleme

Source: https://academia.sh/tr/kurslar/surum-kontrolune-giris/hazirliktan-cikarma-ve-dosya-geri-yukleme

Hazırlık alanındaki kaydın ve çalışma dizinindeki içeriğin ayrı ayrı geri alınması; kaynak seçimi ve hangi durumların kurtarılabilir olduğu.

Temel döngü tek yönlü anlatıldı: değişiklik yapılır, hazırlık alanına alınır, işlenir. Bu
konu ters yönü ele alıyor. İlk ders en dar kapsamlı iki işlemi tanımlar; ikisi de tarihçeye
dokunmaz, yalnızca çalışma dizinini ve hazırlık alanını etkiler.

Ayrımı baştan kurmak gerekir, çünkü iki işlem farklı şeyleri geri alır ve birinin bedeli
diğerinden ağırdır.

#### İki Ayrı Geri Alma

| İşlem | Etkilediği bölge | Kaynak | Kaybolan |
|---|---|---|---|
| Hazırlıktan çıkarma | Hazırlık alanı | Son işleme | Yok |
| Dosya geri yükleme | Çalışma dizini | Hazırlık alanı ya da bir işleme | Kaydedilmemiş düzenlemeler |

Birinci işlem geri alınabilir: hazırlıktan çıkarılan içerik çalışma dizininde durmaya devam
eder. İkinci işlem geri alınamaz — çalışma dizinindeki düzenleme hiçbir yerde saklanmadıysa
üzerine yazıldığında gider.

#### Hata

Terim listesine iki terim eklenirken arama betiğinde de bir düzenleme yapılır: `grep`
çağrısına `-x` seçeneği eklenir. Bu seçenek eşleşmenin tüm satırı kapsamasını zorunlu kılar
ve betiği bozar. Düzenlemeler komut satırından yapılır:

```bash
printf 'öbek | heap\ndizi | array\n' >> terimler.txt
sed -i.bak 's/grep -i --/grep -ix --/' ara.sh
rm ara.sh.bak
```

Betik şimdi bozuktur:

```bash
./ara.sh yığıt
```

```
eşleşme yok: yığıt
```

Terim listede bulunduğu hâlde bulunamıyor: `-x`, "yığıt" örüntüsünün `yığıt | stack`
satırının tamamına eşit olmasını istiyor. Hata fark edilmeden iki değişiklik birlikte hazırlık
alanına alınır:

```bash
git add .
git status --short
```

```
M  ara.sh
M  terimler.txt
```

Terim eklemesi tutulmalı, betikteki düzenleme geri alınmalıdır.

#### Hazırlıktan Çıkarma

```bash
git restore --staged ara.sh
git status --short
```

```
 M ara.sh
M  terimler.txt
```

`ara.sh` işareti birinci sütundan ikinci sütuna geçti: dosya artık hazırlık alanında değil,
yalnızca çalışma dizininde değişik. Komut hazırlık alanındaki girdiyi son işlemedeki hâline
döndürdü; çalışma dizinine dokunmadı.

Bunu doğrulamak için fark alınır:

```bash
git diff
```

```
diff --git a/ara.sh b/ara.sh
index 582ddde..fd7e235 100755
--- a/ara.sh
+++ b/ara.sh
@@ -6,7 +6,7 @@ if [ $# -ne 1 ]; then
     exit 1
 fi
 
-if ! grep -i -- "$1" terimler.txt; then
+if ! grep -ix -- "$1" terimler.txt; then
     echo "eşleşme yok: $1" >&2
     exit 2
 fi
```

Düzenleme yerinde duruyor. Bu noktada iki seçenek vardır: düzenlemeyi elle düzeltmek ya da
tümüyle geri almak.

#### Çalışma Dizinini Geri Yükleme

```bash
git restore ara.sh
git status --short
```

```
M  terimler.txt
```

```bash
./ara.sh yığıt
```

```
yığıt | stack
```

Betik yeniden çalışıyor. `git restore`, dosyayı hazırlık alanındaki hâline döndürdü; hazırlık
alanı da son işlemeyle aynı olduğu için sonuç, dosyanın son işlemedeki hâlidir.

Bu komut **yıkıcıdır**. Geri alınan düzenleme hiçbir yerde saklanmamıştı; ne nesne
veritabanında ne de hazırlık alanında bir kaydı vardı. Komut çalıştıktan sonra o metin geri
getirilemez. Kural olarak, geri alınacak düzenlemenin gerçekten istenmediğinden emin olmadan
çalıştırılmamalı; kararsızlık varsa değişiklik önce hazırlık alanına alınmalı ya da zulaya
konmalıdır. Zula, bu konunun beşinci dersinin konusudur.

Kalan değişiklik işlenir; tarih de yeni işlemeye göre ilerletilir:

```bash
export GIT_AUTHOR_DATE="2024-03-07 14:00:00 +0300"
export GIT_COMMITTER_DATE="2024-03-07 14:00:00 +0300"
git commit -m "Öbek ve dizi terimlerini ekle"
```

```
[main 0e74ba9] Öbek ve dizi terimlerini ekle
 1 file changed, 2 insertions(+)
```

#### Kaynağı Seçmek

Varsayılan olarak `git restore` kaynağı hazırlık alanıdır. `--source` seçeneği başka bir
işlemeyi kaynak yapar:

```bash
git restore --source=HEAD~1 terimler.txt
git diff --stat
```

```
 terimler.txt | 2 --
 1 file changed, 2 deletions(-)
```

Dosya bir önceki işlemedeki hâline döndü; iki satır eksildi. Bu, geçmişteki bir sürümü
inceleme ya da tek bir dosyayı geri getirme yoludur. Değişiklik yalnızca çalışma dizinindedir;
tarihçe olduğu gibi durur ve `git restore terimler.txt` ile son duruma dönülür:

```bash
git restore terimler.txt
```

Komutun etkilediği bölgeler açıkça seçilebilir:

| Yazım | Etkilenen |
|---|---|
| `git restore <yol>` | Çalışma dizini |
| `git restore --staged <yol>` | Hazırlık alanı |
| `git restore --staged --worktree <yol>` | Her ikisi |

Üçüncü satır, bir dosyayı tümüyle son işlemedeki hâline döndürür.

#### Silinen Dosyayı Geri Getirmek

Silme de bir değişikliktir ve aynı araçla geri alınır. Terim listesi yanlışlıkla silinirse:

```bash
rm terimler.txt
git status --short
```

```
 D terimler.txt
```

`D` işareti ikinci sütunda: dosya çalışma dizininden kaldırılmış ama hazırlık alanındaki kaydı
duruyor. Kayıt bir blob kimliği taşıdığına göre içerik nesne veritabanındadır:

```bash
git restore terimler.txt
git status --short
```

İkinci komut hiçbir şey yazmaz; dosya geri gelmiştir. Silme hazırlık alanına da alınmışsa
(`D` birinci sütunda görünüyorsa) önce hazırlıktan çıkarmak, sonra geri yüklemek gerekir;
`--staged --worktree` ikisini tek komutta yapar.

Bu, önceki bölümdeki ölçütün doğrudan sonucudur: silinen dosyanın içeriği izleniyordu, dolayısıyla
nesne veritabanındaydı. İzlenmeyen bir dosya silindiğinde geri getirilemez.

#### Eski Yazımlar

Aynı işler daha eski komutlarla da yapılabilir ve belgelerde bu yazımlara sık rastlanır.
Denemek için dosyaya bir satır eklenir ve hazırlık alanına alınır:

```bash
echo "deneme | trial" >> terimler.txt
git add terimler.txt
```

Ardından iki eski yazım sırayla uygulanır:

```bash
git reset HEAD terimler.txt      # hazırlıktan çıkarma
git checkout -- terimler.txt     # çalışma dizinini geri yükleme
```

Birinci komut şu bilgilendirmeyi yazar:

```
Unstaged changes after reset:
M	terimler.txt
```

İki eski yazımın sorunu, komutların aşırı yüklenmiş olmasıdır: `git reset` aynı zamanda
tarihçeyi geriye alan, `git checkout` aynı zamanda dallar arasında geçiş yapan komuttur. Aynı
adın çok farklı sonuçlar doğurması, hangi işlemin yapıldığını komuttan okumayı zorlaştırır.
`git restore` ve `git switch` komutları bu ayrımı adlandırmak için tanımlanmıştır. Eski
yazımlar geçerliliğini korur; bu kursta yeni adlar kullanılacaktır.

#### Neyin Kurtarılabildiği

Geri alma araçlarının sınırı tek bir ölçüte indirgenir: **içerik nesne veritabanına yazıldı
mı?**

| Durum | Nesne veritabanında | Kurtarılabilir mi |
|---|---|---|
| İşlenmiş içerik | Evet | Evet |
| Hazırlık alanına alınmış içerik | Evet (blob olarak) | Evet |
| Yalnızca çalışma dizinindeki düzenleme | Hayır | Hayır |
| İzlenmeyen dosya | Hayır | Hayır |

İkinci satır beklenmedik olabilir: `git add` çalıştırıldığı anda içerik blob olarak yazılır ve
işleme yapılmasa bile veritabanında kalır. Hazırlıktan çıkarılan ve sonra üzerine yazılan bir
içerik bile, kimliği bilindiği sürece `git cat-file` ile okunabilir. Buna karşılık hiç
hazırlığa alınmamış bir düzenlemenin hiçbir izi yoktur.

Pratik sonuç şudur: uzun süre üzerinde çalışılan bir değişiklik, ara ara hazırlık alanına
alınırsa yıkıcı bir komuta karşı korunmuş olur. Bu, hazırlık alanının işlemeye hazırlık
dışında ikinci bir işlevidir.

#### Özet

- Hazırlıktan çıkarma hazırlık alanını, dosya geri yükleme çalışma dizinini etkiler.
- `git restore --staged` kaydı son işlemedeki hâline döndürür ve veri kaybettirmez.
- `git restore` çalışma dizinindeki düzenlemeyi yıkıcı biçimde geri alır.
- `--source` ile kaynak bir işleme seçilebilir; `--staged --worktree` her iki bölgeyi birden
  geri yükler.
- Kurtarılabilirliğin ölçütü, içeriğin nesne veritabanına yazılmış olmasıdır; hazırlığa alma
  bu güvenceyi sağlar.

#### Sonraki Adım

Bu araçlar henüz işlenmemiş değişiklikleri geri alıyor. Yazılmış bir işlemede eksik ya da
hata varsa ne yapılır? Sonraki ders son işlemenin değiştirilmesini, bu işlemin neden yeni bir
nesne ürettiğini ve hangi durumlarda kullanılmaması gerektiğini ele alacak.

### İşlemeyi Değiştirme

Source: https://academia.sh/tr/kurslar/surum-kontrolune-giris/islemeyi-degistirme

Son işlemenin mesajının ya da içeriğinin düzeltilmesi; işlemenin değiştirilemez olması nedeniyle yeni nesne üretilmesi, başvuru günlüğü ve paylaşılmış tarihçenin sınırı.

Önceki ders henüz işlenmemiş değişiklikleri geri aldı. Bu ders bir adım ileri gider: yazılmış
bir işlemede eksik ya da hata varsa ne yapılacağını ele alır. En sık karşılaşılan iki durum,
mesajın yanlış yazılması ve bir dosyanın işlemeye alınmayı unutulmasıdır.

#### Değiştirme Aslında Değiştirmez

İşleme nesnesi değiştirilemez. Kimliği, içeriğinin karma değeridir; içerik değişirse kimlik de
değişir ve ortaya başka bir nesne çıkar. Bu nedenle "işlemeyi değiştirme" adı verilen işlem,
var olan nesneyi düzenlemez: aynı öncüle bağlanan **yeni** bir işleme oluşturur ve dalın ucunu
o yeni işlemeye taşır. Eski işleme nesne veritabanında kalır ama hiçbir başvurudan
erişilemez hâle gelir.

Ayrım pratikte önemlidir: geçmişi düzeltmek, geçmişi yeniden yazmaktır.

#### Mesajı Düzeltmek

Kullanım bölümü `README.md` dosyasına eklenir ve işlenir; ancak mesajda iki yazım hatası
vardır. Yazar tarihi bu işlemeden sonra da korunacağı için önce tarih sabitlenir:

```bash
cat >> README.md <<'SON'

## Kullanım

    ./ara.sh ARANAN
SON
export GIT_AUTHOR_DATE="2024-03-08 11:30:00 +0300"
export GIT_COMMITTER_DATE="2024-03-08 11:30:00 +0300"
git add README.md
git commit -m "READMEye kullanm bölümü ekle"
```

```
[main b55cf62] READMEye kullanm bölümü ekle
 1 file changed, 4 insertions(+)
```

```bash
export GIT_COMMITTER_DATE="2024-03-08 11:33:00 +0300"
git commit --amend -m "README'ye kullanım bölümü ekle"
```

```
[main b2ed6c2] README'ye kullanım bölümü ekle
 Date: Fri Mar 8 11:30:00 2024 +0300
 1 file changed, 4 insertions(+)
```

Kimlik `b55cf62` iken `b2ed6c2` oldu. İçerikte tek bir bayt bile değişmedi; değişen yalnızca
mesajdı ve mesaj da kimlik hesabına giriyordu.

Çıktıdaki `Date:` satırı, işlemenin yazar tarihinin korunduğunu bildirmek için yazılır.

Değişen şeyin gerçekten yalnızca mesaj olduğu, ağaç kimlikleri karşılaştırılarak sınanabilir:

```bash
git log -1 --format='%h %T' HEAD@{1}
git log -1 --format='%h %T' HEAD
```

```
b55cf62 4e359f7361da5c8654dce5682f26e5a79e43f5ca
b2ed6c2 4e359f7361da5c8654dce5682f26e5a79e43f5ca
```

İki işleme aynı ağacı gösteriyor. Proje içeriği bayt düzeyinde özdeş, işleme kimlikleri farklı:
kimliğin içerik dışında üstveriyi de kapsadığının doğrudan kanıtı budur. Nesne veritabanında
yeni yazılan tek şey ikinci işleme nesnesidir; blob ve ağaç nesneleri paylaşılmıştır.

#### Yazar ve İşleyen

İşleme nesnesindeki iki tarih alanının ayrı olmasının nedeni burada görünür:

```bash
git log -1 --format='yazar   : %an %ad%nişleyen : %cn %cd' --date=iso
```

```
yazar   : Deniz Kaya 2024-03-08 11:30:00 +0300
işleyen : Deniz Kaya 2024-03-08 11:33:00 +0300
```

**Yazar (author)**, değişikliği yazan kişi ve o değişikliğin ilk oluşturulma zamanıdır.
**İşleyen (committer)**, işlemeyi nesne veritabanına koyan kişi ve o kaydın zamanıdır.
Değiştirme işlemi yazar alanını korur, işleyen alanını günceller. İki alanın ayrı tutulması,
bir katkının başka biri tarafından tarihçeye yerleştirildiği durumlarda kaynağın
kaybolmamasını sağlar.

#### Unutulan Bir Değişikliği Eklemek

`README.md` dosyasında çıkış kodunu anlatan satır yazılmadan işlenmişti. Eksik satır eklenir,
hazırlık alanına alınır ve mesaj korunarak işlemeye katılır:

```bash
printf '\nEşleşme bulunamazsa betik 2 koduyla çıkar.\n' >> README.md
export GIT_COMMITTER_DATE="2024-03-08 11:41:00 +0300"
git add README.md
git commit --amend --no-edit
```

```
[main 377b1f8] README'ye kullanım bölümü ekle
 Date: Fri Mar 8 11:30:00 2024 +0300
 1 file changed, 6 insertions(+)
```

`--no-edit`, düzenleyiciyi açmadan var olan mesajı kullanır. Satır sayısı dörtten altıya
çıktı: hazırlık alanındaki içerik, yeni işlemenin ağacını oluşturdu.

Tarihçede tek bir işleme görünüyor:

```bash
git log --oneline -n 3
```

```
377b1f8 README'ye kullanım bölümü ekle
0e74ba9 Öbek ve dizi terimlerini ekle
d3ab7b0 Yerel notları izlemeden çıkar
```

Üç ayrı işleme nesnesi yazıldı — `b55cf62`, `b2ed6c2`, `377b1f8` — ama tarihçede yalnızca
sonuncusu duruyor. İlk ikisi erişilemez hâle geldi.

#### Değiştirmenin Kapsamı

`--amend`, yeni işlemenin ağacını **hazırlık alanının o anki durumundan** üretir. Bu, kolaylık
olduğu kadar bir tuzaktır: hazırlık alanına başka bir iş için alınmış dosyalar varsa, onlar da
değiştirilen işlemeye girer ve tarihçede yanlış yere kaydedilmiş olurlar.

Yalnızca mesajı düzeltmek istendiğinde hazırlık alanının son işlemeyle aynı olması gerekir.
Sınama tek komuttur:

```bash
git status --short
```

Çıktının birinci sütununda hiçbir işaret bulunmamalıdır. Bulunuyorsa, o girdiler değiştirme
işleminin kapsamına girecektir.

Aynı mekanizma yazar alanı için de geçerlidir. `--author` seçeneği yeni işlemenin yazarını
belirler; yapılandırmadaki kimlik yanlışken yazılmış bir işlemenin düzeltilmesi bu yolla
yapılır. İşleyen alanı yine yapılandırmadan alınır, dolayısıyla iki alan farklılaşır — bu,
alanların ayrı tutulmasının beklenen sonucudur.

#### Eski İşlemelere Ne Oldu

Erişilemez olmak yok olmak değildir:

```bash
git cat-file -t HEAD@{2}
```

```
commit
```

Nesne yerinde. Ona ulaşmanın yolu **başvuru günlüğüdür (reflog)**: `HEAD` ve dal uçlarının
geçmişte hangi değerleri aldığını kaydeden yerel bir günlük.

```bash
git reflog -n 3
```

```
377b1f8 HEAD@{0}: commit (amend): README'ye kullanım bölümü ekle
b2ed6c2 HEAD@{1}: commit (amend): README'ye kullanım bölümü ekle
b55cf62 HEAD@{2}: commit: READMEye kullanm bölümü ekle
```

`HEAD@{n}` gösterimi, `HEAD` başvurusunun `n` adım önceki değerini adlandırır. Günlük yereldir
ve paylaşılmaz; deponun bir kopyasında yapılan değiştirme, başka bir kopyanın günlüğünde
görünmez.

Erişilemez nesneler süresiz kalmaz. Depo bakımı sırasında çalışan **çöp toplama (garbage
collection)**, hiçbir başvurudan ve başvuru günlüğünden erişilemeyen nesneleri siler.
Varsayılan bekleme süresi yeterince uzundur; ancak "erişilemez nesne kalıcıdır" varsayımıyla
çalışmak doğru değildir. Kurtarma penceresi sınırlıdır.

#### Kaybolan İşlemeyi Geri Getirmek

Başvuru günlüğü yalnızca bir kayıt değil, bir kurtarma aracıdır. Yanlışlıkla değiştirilen bir
işlemeye yeniden erişilebilir hâle getirmenin yolu, ona bir ad vermektir:

```bash
git branch kurtarma HEAD@{2}
git log --oneline -n 2 kurtarma
```

```
b55cf62 READMEye kullanm bölümü ekle
0e74ba9 Öbek ve dizi terimlerini ekle
```

Komut sessizce çalışır ve `kurtarma` adlı bir başvuru oluşturur. Nesne artık bir addan
erişilebilir olduğu için çöp toplamanın kapsamı dışına çıkar; içerik incelenip gerekeni
alındıktan sonra bu ad silinebilir.

Aynı işlem bir kimlikle de yapılabilir: başvuru günlüğündeki `b55cf62` doğrudan yazılabilir.
`HEAD@{n}` gösterimi tercih edilir, çünkü hangi adımın geri alınacağı kimlikten değil
sıradan okunur.

Buradaki genel kural şudur: bir nesneye erişilebilen tek bir ad kalması, onu korumaya yeter.
Değiştirme ve sonraki derste görülecek sıfırlama gibi işlemler nesneleri silmez; yalnızca
onlara giden adları taşır.

#### Değiştirmenin Sınırı

Değiştirme, yalnızca **son** işlemeye uygulanır ve yalnızca **paylaşılmamış** işlemelerde
güvenlidir.

İkinci koşulun nedeni, kimliğin öncül zincirini kapsamasıdır. Bir işleme değiştirildiğinde
kimliği değişir; ondan sonraki her işlemenin öncül alanı da değişmek zorunda kalır ve
kimlikleri değişir. Tarihçe, değiştirilen noktadan sonra bütünüyle yeni nesnelerden oluşur.

Bu tarihçeyi daha önce almış bir kopya, kendi elindeki eski zinciri tutmaya devam eder.
Sonuçta iki kopyada aynı değişiklikleri içeren ama farklı kimlikler taşıyan iki ayrı zincir
bulunur; bunlar birleştirilmek istendiğinde her işleme iki kez görünür. İşbirliği içinde
çalışan bir depoda bu, kaçınılması gereken bir durumdur.

Kural sadedir: bir işleme paylaşıldıysa değiştirilmez. Onun yerine, etkisini tersine çeviren
yeni bir işleme yazılır — ileride ele alınacak devirme.

Değiştirme, yalnızca son işlemeyle sınırlı olduğu için de dar bir araçtır. Daha eski bir
işlemeyi düzeltmek gerektiğinde tarihçenin o noktadan itibaren yeniden yazılması gerekir; bu
işlemler İleri Git kursunda ele alınacaktır.

#### Özet

- İşleme nesnesi değiştirilemez; değiştirme işlemi aynı öncüle bağlanan yeni bir işleme
  oluşturur ve dal ucunu ona taşır.
- Kimlik mesajı da kapsadığı için yalnızca mesajın düzeltilmesi bile yeni bir kimlik üretir.
- Yazar alanı korunur, işleyen alanı güncellenir; iki alanın ayrılması katkının kaynağını
  korur.
- Eski işlemeler erişilemez hâle gelir ama silinmez; başvuru günlüğü onlara ulaşmayı sağlar.
  Çöp toplama, erişilemez nesneleri belirli bir süre sonra siler.
- Değiştirme yalnızca son işlemeye ve yalnızca paylaşılmamış tarihçeye uygulanır.

#### Sonraki Adım

Değiştirme, son işlemeyi hedefliyor ve dal ucunu yeni bir nesneye taşıyordu. Dal ucunu daha
geriye taşımak, yani birden çok işlemeyi tarihçeden düşürmek de mümkündür — ve bu işlemin üç
farklı kipi vardır. Sonraki ders, bu kiplerin çalışma dizini ile hazırlık alanına ne yaptığını
tek tek gösterecek.

### Sıfırlama Kipleri

Source: https://academia.sh/tr/kurslar/surum-kontrolune-giris/sifirlama-kipleri

Dal ucunun geriye taşınması; `--soft`, `--mixed` ve `--hard` kiplerinin üç bölgeye etkisi, kaybolan içerik ve başvuru günlüğüyle kurtarma.

Değiştirme, dal ucunu aynı öncüle bağlanan yeni bir işlemeye taşıyordu. **Sıfırlama (reset)**,
dal ucunu tarihçede daha geriye taşır: bir ya da daha çok işleme, dalın erişilebilir
geçmişinden düşer. Sıfırlamanın üç kipi vardır ve aralarındaki fark, hangi bölgelerin
etkilendiğidir.

Bu ders üç kipi aynı hata üzerinde tek tek uygular.

#### Hata

Terim listesi abecesel sıralanmak istenir ve genel amaçlı bir sıralama aracına verilir. Araç
bayt değerlerine göre çalışsın diye dil ayarı kapatılır (`LC_ALL=C`); böylece sonuç hangi
makinede olursa olsun aynı çıkar:

```bash
LC_ALL=C sort terimler.txt -o terimler.txt
cat terimler.txt
```

```
ağaç | tree
bağlı liste | linked list
dizi | array
karma tablosu | hash table
kuyruk | queue
küme | set
yığıt | stack
çizge | graph
öbek | heap
```

Sıra yanlıştır. "çizge" ve "öbek" listenin sonuna düşmüş, "küme" ise "kuyruk"tan sonra
gelmiştir. Nedeni, sıralamanın Türkçe abeceye göre değil bayt değerlerine göre yapılmasıdır:
Bilgisayarlar Nasıl Çalışır kursunda görüldüğü gibi, ASCII aralığı dışındaki harfler UTF-8'de
birden çok baytla kodlanır ve ilk baytları tüm ASCII harflerinden büyüktür. Doğru sıra, dile
duyarlı bir karşılaştırma düzeni gerektirir.

Hata fark edilmeden işlenir. Bu derste aynı işleme birkaç kez yeniden yazılacağı için tarih
önce sabitlenir; bu iki değişken açık oturumda tanımlı kalır, yeni bir terminal açtıysanız
yeniden yazın:

```bash
export GIT_AUTHOR_DATE="2024-03-08 15:00:00 +0300"
export GIT_COMMITTER_DATE="2024-03-08 15:00:00 +0300"
git commit -a -m "Terim listesini abecesel sırala"
```

```
[main baf5138] Terim listesini abecesel sırala
 1 file changed, 5 insertions(+), 5 deletions(-)
```

#### Sıfırlama Ne Yapar

Sıfırlama üç adımdan oluşur ve kip, adımların kaçının uygulanacağını belirler:

1. **Dal ucunu taşı.** Her kipte yapılır.
2. **Hazırlık alanını hedefe eşitle.** `--soft` dışında yapılır.
3. **Çalışma dizinini hedefe eşitle.** Yalnızca `--hard` ile yapılır.

Birinci adım tarihçeye, ikinci ve üçüncü adımlar içeriğe dokunur.

#### `--soft`

```bash
git reset --soft HEAD~1
git log --oneline -n 1
```

```
377b1f8 README'ye kullanım bölümü ekle
```

İşleme tarihçeden düştü. İçeriğe ne oldu?

```bash
git status --short
```

```
M  terimler.txt
```

Değişiklik hazırlık alanında duruyor. Yalnızca birinci adım uygulandı: dal ucu geriye taşındı,
hazırlık alanı ve çalışma dizini olduğu gibi bırakıldı. Sonuç, "işleme hiç yazılmamış ama
içerik işlenmeye hazır" durumudur.

```bash
git diff --staged --stat
```

```
 terimler.txt | 10 +++++-----
 1 file changed, 5 insertions(+), 5 deletions(-)
```

Bu kip, son işlemenin kapsamını yeniden düzenlemek için kullanılır: işleme geri alınır, içerik
istenen biçimde bölünür ve yeniden işlenir.

#### `--mixed`

Sıfırlanan işleme aynı mesajla yeniden yazılır ve bu kez varsayılan kiple sıfırlanır:

```bash
git commit -m "Terim listesini abecesel sırala"
```

```
[main baf5138] Terim listesini abecesel sırala
 1 file changed, 5 insertions(+), 5 deletions(-)
```

```bash
git reset HEAD~1
```

```
Unstaged changes after reset:
M	terimler.txt
```

```bash
git status --short
```

```
 M terimler.txt
```

İşaret ikinci sütuna geçti: içerik artık hazırlık alanında değil, yalnızca çalışma dizininde.
Birinci ve ikinci adım uygulandı. `--mixed` yazılmasa da varsayılan kip budur.

Bu kip, hem işlemeyi hem de hazırlık alanındaki seçimi geri alır; hangi dosyaların birlikte
işleneceğine baştan karar vermek istendiğinde kullanılır.

#### `--hard`

İşleme bir kez daha yazılır; çalışma dizinindeki değişiklik hazırlık alanına `-a` ile alınır:

```bash
git commit -a -m "Terim listesini abecesel sırala"
```

```
[main baf5138] Terim listesini abecesel sırala
 1 file changed, 5 insertions(+), 5 deletions(-)
```

```bash
git reset --hard HEAD~1
```

```
HEAD is now at 377b1f8 README'ye kullanım bölümü ekle
```

```bash
git status --short
```

Çıktı boştur. Terim listesi de eski hâline dönmüştür: sıralama tümüyle geri alınmıştır. Üç
adım da uygulandı.

Bu kip **yıkıcıdır** ve iki ayrı içeriği götürür: sıfırlanan işlemelerin içeriğini ve o sırada
çalışma dizininde bulunan, işlenmemiş bütün düzenlemeleri. Birincisi başvuru günlüğünden geri
getirilebilir; ikincisi getirilemez. `git reset --hard` çalıştırmadan önce `git status`
çıktısına bakmak, bu ikinci kaybı önlemenin tek yoludur.

#### Üç Kipin Karşılaştırması

| Kip | Dal ucu | Hazırlık alanı | Çalışma dizini | Değişiklik nerede kalır |
|---|---|---|---|---|
| `--soft` | Taşınır | Dokunulmaz | Dokunulmaz | Hazırlık alanında |
| `--mixed` | Taşınır | Eşitlenir | Dokunulmaz | Çalışma dizininde |
| `--hard` | Taşınır | Eşitlenir | Eşitlenir | Hiçbir yerde |

Tablo tek bir cümleye indirgenebilir: kip sertleştikçe geri alma daha derine iner. Seçim,
işlemenin içeriğinin korunup korunmayacağına göre yapılır.

#### Kurtarma

Sıfırlanan işleme nesne veritabanında durur ve başvuru günlüğünden bulunabilir:

```bash
git reflog -n 6
```

```
377b1f8 HEAD@{0}: reset: moving to HEAD~1
baf5138 HEAD@{1}: commit: Terim listesini abecesel sırala
377b1f8 HEAD@{2}: reset: moving to HEAD~1
baf5138 HEAD@{3}: commit: Terim listesini abecesel sırala
377b1f8 HEAD@{4}: reset: moving to HEAD~1
baf5138 HEAD@{5}: commit: Terim listesini abecesel sırala
```

Günlük, üç kipin denendiği sırayı olduğu gibi kaydetmiştir. İşleme kimliğinin her seferinde
`baf5138` çıkması rastlantı değildir: içerik, mesaj, yazar ve tarih aynı olduğu sürece
kimlik de aynıdır. İçerik adresli depolamanın doğrudan sonucudur.

Dal ucu istenen kimliğe geri taşınır:

```bash
git reset --hard baf5138
```

```
HEAD is now at baf5138 Terim listesini abecesel sırala
```

İşleme tarihçeye döndü. Bu örnekte sıralama gerçekten yanlış olduğu için son karar onu
düşürmektir:

```bash
git reset --hard HEAD~1
```

```
HEAD is now at 377b1f8 README'ye kullanım bölümü ekle
```

#### Yol Verilen Biçim

`git reset` komutuna bir yol verildiğinde davranış tümüyle değişir: dal ucu taşınmaz, yalnızca
o yolun hazırlık alanındaki kaydı hedefteki hâline döndürülür. Denemek için listeyi yeniden
sıralamak gerekir:

```bash
LC_ALL=C sort terimler.txt -o terimler.txt
git add terimler.txt
git status --short
```

```
M  terimler.txt
```

```bash
git reset terimler.txt
```

```
Unstaged changes after reset:
M	terimler.txt
```

```bash
git status --short
```

```
 M terimler.txt
```

Bu, önceki derste `git restore --staged` ile yapılan işin eski yazımıdır. Aynı komut adının
yol verildiğinde ve verilmediğinde farklı işler yapması, `git restore` komutunun neden ayrı
adlandırıldığını açıklar.

#### `ORIG_HEAD`

Sıfırlama, dal ucunu taşımadan önce eski değeri `ORIG_HEAD` adlı bir dosyaya yazar:

```bash
cat .git/ORIG_HEAD
```

```
baf5138febc3dd9acb9ef94162c9d2f72e8e5d0a
```

Bu ad bir başvuru gibi kullanılabilir; yanlışlıkla yapılan bir sıfırlamayı geri almanın en kısa
yolu, başvuru günlüğünü okumadan `ORIG_HEAD` hedefine dönmektir:

```bash
git reset --hard ORIG_HEAD
```

```
HEAD is now at baf5138 Terim listesini abecesel sırala
```

`ORIG_HEAD` dosyası yalnızca son işlemi kaydeder; art arda yapılan sıfırlamalarda üzerine
yazılır. Daha geriye gitmek için başvuru günlüğü gerekir.

Sıralama yanlış olduğundan bu denemeden sonra yeniden düşürülür; sonraki ders `377b1f8`
durumundan başlar:

```bash
git reset --hard HEAD~1
```

```
HEAD is now at 377b1f8 README'ye kullanım bölümü ekle
```

#### Sıfırlama ile Dosya Geri Yükleme Farkı

İki komut karıştırılır çünkü ikisi de "geri alma" olarak adlandırılır. Ayrım nettir:

- `git restore` **yol** üzerinde çalışır; tarihçeye dokunmaz.
- `git reset` **başvuru** üzerinde çalışır; dal ucunu taşır.

Bir dosyayı eski hâline döndürmek istiyorsanız `git restore`, bir işlemeyi tarihçeden
düşürmek istiyorsanız `git reset` kullanılır.

Sıfırlamanın kendisi de paylaşılmış tarihçede sorunludur: dal ucunu geriye taşımak, o
işlemeleri almış kopyalarla uyumsuzluk yaratır. Önceki dersteki kural burada da geçerlidir —
paylaşılmış tarihçe geriye alınmaz.

#### Özet

- Sıfırlama dal ucunu taşır; kip, hazırlık alanı ile çalışma dizininin de eşitlenip
  eşitlenmeyeceğini belirler.
- `--soft` içeriği hazırlık alanında, `--mixed` çalışma dizininde bırakır; `--hard` her ikisini
  de hedefe eşitler.
- `--hard`, işlenmemiş düzenlemeleri geri getirilemez biçimde siler.
- Sıfırlanan işlemeler nesne veritabanında kalır; başvuru günlüğünden bulunup geri getirilebilir.
- Aynı içerik, mesaj, yazar ve tarih her zaman aynı işleme kimliğini üretir.

#### Sonraki Adım

Sıfırlama ve değiştirme, tarihçeyi yeniden yazarak çalışıyor ve bu nedenle paylaşılmış
işlemelerde kullanılamıyor. Peki paylaşılmış bir işleme hatalıysa ne yapılır? Sonraki ders,
tarihçeyi bozmadan bir işlemenin etkisini tersine çeviren aracı — devirmeyi — ele alacak.

### Devirme

Source: https://academia.sh/tr/kurslar/surum-kontrolune-giris/devirme

Bir işlemenin etkisini tersine çeviren yeni işleme; tarihçeyi bozmadan geri alma, ağaç kimliğiyle doğrulama, işlemeden devirme ve devirmenin devrilmesi.

Sıfırlama ve değiştirme, tarihçeyi yeniden yazarak çalışır; bu yüzden paylaşılmış işlemelerde
kullanılamazlar. Paylaşılmış bir işleme hatalıysa geriye tek bir yol kalır: geçmişi olduğu gibi
bırakıp, hatanın etkisini tersine çeviren **yeni** bir işleme yazmak. Bu işleme **devirme
(revert)** denir.

#### Hata

Arama betiğinin çıktısı yalnızca Türkçe sütunla sınırlandırılmak istenir ve `grep` çıktısı bir
süzgeçten geçirilir. Betikteki koşul satırı `sed` ile düzenlenir:

```bash
sed -i.bak "s/terimler.txt; then/terimler.txt | cut -d '|' -f 1; then/" ara.sh
rm ara.sh.bak
```

Düzenlemeden sonra koşul şu hâle gelir:

{/* run: skip */}
```sh
if ! grep -i -- "$1" terimler.txt | cut -d '|' -f 1; then
    echo "eşleşme yok: $1" >&2
    exit 2
fi
```

Değişiklik, tarihleri sabitlenmiş bir işlemeyle kaydedilir. Tarih değişkenleri açık
oturumda tanımlıdır; yeni bir terminal açtıysanız yeniden yazın:

```bash
export GIT_AUTHOR_DATE="2024-03-11 09:30:00 +0300"
export GIT_COMMITTER_DATE="2024-03-11 09:30:00 +0300"
git commit -a -m "Arama çıktısını yalnızca Türkçe sütuna indir"
```

```
[main d245350] Arama çıktısını yalnızca Türkçe sütuna indir
 1 file changed, 1 insertion(+), 1 deletion(-)
```

Değişiklik istenen çıktıyı üretir ama gizli bir kusur taşır: kabuk, boru hattının çıkış
kodunu son komuttan alır. `cut` her durumda başarıyla sonlandığı için `grep` eşleşme
bulamadığında da koşul yanlış çıkar:

```bash
./ara.sh yokboyle
echo "çıkış kodu: $?"
```

```
çıkış kodu: 0
```

Betik hiçbir eşleşme bildirimi yazmadı ve sıfır çıkış koduyla sonlandı; oysa eşleşme yoktur ve
çıkış kodu 2 olmalıdır. Kusur, çıktının kendisinde değil hata bildirimindedir; bu nedenle
gözden kaçmaya elverişlidir.

İşleme paylaşılmıştır ve tarihçeden düşürülemez.

#### Devirme

```bash
export GIT_AUTHOR_DATE="2024-03-11 10:12:00 +0300"
export GIT_COMMITTER_DATE="2024-03-11 10:12:00 +0300"
git revert --no-edit HEAD
```

```
[main c497738] Revert "Arama çıktısını yalnızca Türkçe sütuna indir"
 Date: Mon Mar 11 10:12:00 2024 +0300
 1 file changed, 1 insertion(+), 1 deletion(-)
```

`--no-edit`, hazırlanan mesajı düzenleyici açmadan kabul eder. Betik yeniden doğru çalışır:

```bash
./ara.sh yokboyle
```

```
eşleşme yok: yokboyle
```

```bash
git log --oneline -n 4
```

```
c497738 Revert "Arama çıktısını yalnızca Türkçe sütuna indir"
d245350 Arama çıktısını yalnızca Türkçe sütuna indir
377b1f8 README'ye kullanım bölümü ekle
0e74ba9 Öbek ve dizi terimlerini ekle
```

Hatalı işleme tarihçede duruyor. Yanına, etkisini tersine çeviren bir işleme eklendi.

#### Devirme İşlemesinin İçeriği

```bash
git show HEAD
```

```
commit c49773829409f26d221a2bb5b46a58d8ca2c8327
Author: Deniz Kaya <deniz@ornek.test>
Date:   Mon Mar 11 10:12:00 2024 +0300

    Revert "Arama çıktısını yalnızca Türkçe sütuna indir"

    This reverts commit d2453504d3bed0b24e4bedfaac3c3b87c508b799.

diff --git a/ara.sh b/ara.sh
index 64b5b70..582ddde 100755
--- a/ara.sh
+++ b/ara.sh
@@ -6,7 +6,7 @@ if [ $# -ne 1 ]; then
     exit 1
 fi
 
-if ! grep -i -- "$1" terimler.txt | cut -d '|' -f 1; then
+if ! grep -i -- "$1" terimler.txt; then
     echo "eşleşme yok: $1" >&2
     exit 2
 fi
```

Fark, devrilen işlemenin farkının tersidir: silinen satır eklenmiş, eklenen satır silinmiştir.
Otomatik oluşturulan mesaj, devrilen işlemenin tam kimliğini gövdeye yazar; bu satır sayesinde
bir devirmenin neyi geri aldığı tarihçeden okunabilir.

#### Sonucun Doğrulanması

Devirmenin gerçekten önceki duruma döndürüp döndürmediği, ağaç kimlikleri karşılaştırılarak
kesin olarak sınanır:

```bash
git log --format='%h %T %s' -n 4
```

```
c497738 961039799e5ee6f157229351478a98abb7652c82 Revert "Arama çıktısını yalnızca Türkçe sütuna indir"
d245350 0f2d862b8a585d8dfc9b1a0acbdb30a221233ade Arama çıktısını yalnızca Türkçe sütuna indir
377b1f8 961039799e5ee6f157229351478a98abb7652c82 README'ye kullanım bölümü ekle
0e74ba9 c6ec3cea3b8943f818cd8bb423c65f0cb5c553ea Öbek ve dizi terimlerini ekle
```

Devirme işlemesinin ağacı `9610397`, hatalı işlemeden önceki `377b1f8` işlemesinin ağacıyla
aynıdır. İki farklı işleme aynı ağacı gösteriyor: proje içeriği bayt düzeyinde eski hâline
dönmüştür. İçerik adresli depolamanın verdiği bu eşitlik sınaması, farkları gözle karşılaştırmaya
gerek bırakmaz.

#### Devirme Neden Tarihçeyi Bozmaz

Devirme yalnızca ekleme yapar: var olan hiçbir nesneye dokunmaz, hiçbir kimliği değiştirmez.
Tarihçeyi daha önce almış kopyalar, ellerindeki zinciri korur ve üzerine tek bir yeni işleme
alır. Sıfırlamada ortaya çıkan uyumsuzluk burada oluşmaz.

Bedeli, hatanın tarihçede görünür kalmasıdır. Bu bir kusur değil, çoğu zaman istenen
davranıştır: hatalı bir değişikliğin ne zaman girdiği, ne zaman ve neden geri alındığı
kaydedilmiş olur.

#### İşlemeden Devirmek

Devirmenin sonucu doğrudan işlenmeden incelenebilir:

```bash
git revert -n HEAD~3
git status --short
```

```
M  terimler.txt
```

```bash
git diff --staged
```

```
diff --git a/terimler.txt b/terimler.txt
index a5350ef..17af3b8 100644
--- a/terimler.txt
+++ b/terimler.txt
@@ -5,5 +5,3 @@ ağaç | tree
 karma tablosu | hash table
 bağlı liste | linked list
 küme | set
-öbek | heap
-dizi | array
```

`-n` seçeneği değişikliği hazırlık alanına koyar ama işlemez. Bu, birden çok işlemeyi tek bir
devirme işlemesinde toplamak ya da sonucu işlemeden önce incelemek için kullanılır. İşlem
`git revert --abort` ile iptal edilebilir:

```bash
git revert --abort
```

Komut hazırlık alanını ve çalışma dizinini devirme başlamadan önceki hâline döndürür.

Örnekte devrilen işleme, tarihçenin en son işlemesi değildi. Devirme herhangi bir işlemeye
uygulanabilir; hesaplanan şey, o işlemenin farkının tersinin şu anki içeriğe uygulanmasıdır.
Aradan geçen işlemeler aynı satırlara dokunmuşsa uygulama başarısız olur ve çakışma bildirilir.
Çakışma çözümü Dallanma ve İşbirliği kursunun konusudur.

#### Devirmenin Devrilmesi

Devirme de bir işlemedir; devrilebilir. Bu, geri alınan bir değişikliği yeniden uygulamanın
yoludur:

```bash
export GIT_AUTHOR_DATE="2024-03-11 15:00:00 +0300"
export GIT_COMMITTER_DATE="2024-03-11 15:00:00 +0300"
git revert --no-edit HEAD
```

```
[main 5bba728] Reapply "Arama çıktısını yalnızca Türkçe sütuna indir"
 Date: Mon Mar 11 15:00:00 2024 +0300
 1 file changed, 1 insertion(+), 1 deletion(-)
```

Mesaj bu kez `Revert` değil `Reapply` ile başlar: bir devirmenin devrilmesi, özünde yeniden
uygulamadır.

```bash
git log --format='%h %T %s' -n 4
```

```
5bba728 0f2d862b8a585d8dfc9b1a0acbdb30a221233ade Reapply "Arama çıktısını yalnızca Türkçe sütuna indir"
c497738 961039799e5ee6f157229351478a98abb7652c82 Revert "Arama çıktısını yalnızca Türkçe sütuna indir"
d245350 0f2d862b8a585d8dfc9b1a0acbdb30a221233ade Arama çıktısını yalnızca Türkçe sütuna indir
377b1f8 961039799e5ee6f157229351478a98abb7652c82 README'ye kullanım bölümü ekle
```

Dört işleme, iki ağaç arasında dönüşümlü gidip geliyor. Örnek deponun tarihçesinde bu son
adım tutulmamıştır — kusurlu değişiklik yeniden uygulanmamış, devirme yerinde bırakılmıştır.
Örnek depoyu o durumda tutmak için son işleme geri sarılır:

```bash
git reset --hard HEAD~1
```

```
HEAD is now at c497738 Revert "Arama çıktısını yalnızca Türkçe sütuna indir"
```

#### Devirme mi, Sıfırlama mı

| Ölçüt | Devirme | Sıfırlama |
|---|---|---|
| Tarihçe | Korunur, yeni işleme eklenir | Yeniden yazılır |
| Paylaşılmış işlemede | Uygundur | Uygun değildir |
| Hatanın görünürlüğü | Kayıtta kalır | Silinir |
| Uygulanabildiği işleme | Herhangi biri | Dal ucundan geriye doğru |

Ölçüt tektir: işleme paylaşılmışsa devirme, paylaşılmamışsa her ikisi de kullanılabilir.

#### Özet

- Devirme, bir işlemenin farkının tersini uygulayan yeni bir işleme oluşturur.
- Tarihçe korunur; hiçbir nesne değişmez, yalnızca yeni bir işleme eklenir.
- Devirme işlemesinin ağacı, devrilen işlemeden önceki ağaçla aynıdır; bu eşitlik doğrulama
  aracıdır.
- `-n` seçeneği sonucu işlemeden hazırlık alanına koyar; `--abort` işlemi iptal eder.
- Bir devirme de devrilebilir; sonuç, değişikliğin yeniden uygulanmasıdır.

#### Sonraki Adım

Buraya kadarki araçlar tamamlanmış değişikliklerle ilgiliydi. Peki yarım kalmış bir iş varken
başka bir konuya geçmek gerekirse ne yapılır? İşlemek erken, geri almak ise kayıptır. Sonraki
ders, yarım kalmış işi geçici olarak saklayan zulayı ve bu saklamanın nesne modelindeki
karşılığını ele alacak.

### Zula

Source: https://academia.sh/tr/kurslar/surum-kontrolune-giris/zula

Yarım kalmış işin geçici olarak saklanması; zula yığıtı, içeriğin incelenmesi, izlenmeyen dosyaların dâhil edilmesi ve zulanın nesne modelindeki karşılığı.

Buraya kadarki araçlar tamamlanmış değişikliklerle ilgiliydi: bir değişiklik ya işlenir ya
geri alınır. Üçüncü bir durum vardır — değişiklik yarım kalmıştır ve başka bir işe geçmek
gerekmektedir. İşlemek erkendir, çünkü ortada çalışan bir bütün yoktur; geri almak kayıptır.

**Zula (stash)**, bu durum için tanımlanmış bir bekletme alanıdır: çalışma dizini ve hazırlık
alanı temizlenir, içerikleri kenara alınır ve sonra geri getirilir.

#### Yarım Kalan İş

Arama betiğine tüm terimleri listeleyen bir seçenek eklenmek isteniyor. Kullanım satırı
güncelleniyor, gerçekleştirim henüz yazılmamış; ayrıca yapılacaklar listesi olarak izlenmeyen
bir dosya oluşturulmuş. Bu durumu kurmak için kullanım satırı değiştirilir ve
yapılacaklar dosyası yazılır:

```bash
sed -i.bak 's/ara.sh ARANAN/ara.sh ARANAN | ara.sh -l/' ara.sh
rm ara.sh.bak
echo "- [ ] -l seçeneğini gerçekleştir" > TODO.md
```

```bash
git status --short
```

```
 M ara.sh
?? TODO.md
```

Bu sırada belgede bir eksiklik bildirilir ve önce onun düzeltilmesi gerekir. Yarım iş
işlenemez.

#### Zulaya Almak

Zula girdisi de bir işlemedir ve işleme gibi zaman damgası taşır; çıktılarınızın bu derstekiyle
aynı kalması için tarih önce yazılır (tarih değişkenleri açık oturumda tanımlıdır; yeni bir
terminal açtıysanız yeniden yazın):

```bash
export GIT_AUTHOR_DATE="2024-03-12 09:30:00 +0300"
export GIT_COMMITTER_DATE="2024-03-12 09:30:00 +0300"
git stash push -m "listeleme seçeneği, yarım"
```

```
Saved working directory and index state On main: listeleme seçeneği, yarım
```

```bash
git status --short
```

```
?? TODO.md
```

İzlenen dosyadaki değişiklik kayboldu; çalışma dizini son işlemedeki hâline döndü. İzlenmeyen
`TODO.md` yerinde kaldı: zula varsayılan olarak yalnızca izlenen dosyaları alır.

`-m` seçeneği girdiye bir açıklama bağlar. Açıklama yazılmazsa yerine son işlemenin konu
satırı konur; birden çok girdi biriktiğinde bu açıklamalar ayırt edici olmaktan çıkar.

#### Zula Bir Yığıttır

```bash
git stash list
```

```
stash@{0}: On main: listeleme seçeneği, yarım
```

Girdiler bir yığıt gibi davranır: en son eklenen `stash@{0}` olur, önceki girdiler bir sıra
geriye kayar. Veri Yapıları kursunda tanımlanan son giren ilk çıkar düzeni burada doğrudan
uygulanır. Ancak erişim yığıtla sınırlı değildir: herhangi bir girdi sıra numarasıyla
adlandırılıp tek başına alınabilir ya da silinebilir.

#### İçeriği İncelemek

```bash
git stash show
```

```
 ara.sh | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
```

```bash
git stash show -p
```

```
diff --git a/ara.sh b/ara.sh
index 582ddde..078ea08 100755
--- a/ara.sh
+++ b/ara.sh
@@ -2,7 +2,7 @@
 # terimler.txt içinde arama yapar.
 
 if [ $# -ne 1 ]; then
-    echo "kullanım: ara.sh ARANAN" >&2
+    echo "kullanım: ara.sh ARANAN | ara.sh -l" >&2
     exit 1
 fi
 
```

İkinci komut farkın tamamını verir. Girdi belirtilmezse `stash@{0}` varsayılır; başka bir girdi
için adı yazılır.

#### Araya Giren İş

Çalışma dizini temiz olduğu için acil düzeltme rahatça yapılır ve işlenir:

```bash
cat >> README.md <<'SON'

Arama büyük/küçük harfe duyarlı değildir.
SON
export GIT_AUTHOR_DATE="2024-03-12 09:48:00 +0300"
export GIT_COMMITTER_DATE="2024-03-12 09:48:00 +0300"
git commit -a -m "Aramanın harf duyarsızlığını README'de belirt"
```

```
[main 11fe7e8] Aramanın harf duyarsızlığını README'de belirt
 1 file changed, 2 insertions(+)
```

#### Geri Getirmek

```bash
git stash pop
```

```
On branch main
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
	modified:   ara.sh

Untracked files:
  (use "git add <file>..." to include in what will be committed)
	TODO.md

no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (f319b5815214cb386c16d3fe061c284d6ff9936d)
```

Yarım kalan iş geri geldi ve zula girdisi silindi. Son satır, silinen girdinin nesne kimliğini
bildirir; bu kimlik saklanırsa girdi yanlışlıkla silinse bile geri getirilebilir.

İki komut arasındaki ayrım önemlidir:

| Komut | Etkisi |
|---|---|
| `git stash apply` | İçeriği uygular, girdiyi listede bırakır |
| `git stash pop` | İçeriği uygular ve girdiyi listeden düşürür |
| `git stash drop` | Girdiyi uygulamadan siler |
| `git stash clear` | Tüm girdileri siler |

Uygulama sırasında çakışma çıkabileceği için, sonucun belirsiz olduğu durumlarda `apply`
tercih edilir: uygulama başarısız olursa girdi hâlâ listededir.

#### İzlenmeyen Dosyaları Dâhil Etmek

```bash
export GIT_AUTHOR_DATE="2024-03-12 10:05:00 +0300"
export GIT_COMMITTER_DATE="2024-03-12 10:05:00 +0300"
git stash push -u -m "listeleme seçeneği, yarım"
```

```
Saved working directory and index state On main: listeleme seçeneği, yarım
```

```bash
git status --short
```

Çıktı boştur; `TODO.md` de zulaya alınmıştır. `-u` seçeneği izlenmeyen dosyaları da kapsar.
Yoksayılan dosyalar için ayrı bir seçenek gerekir; varsayılan davranış onları yerinde bırakır.

#### Zula Nesne Modelinde Nedir

Zula, ayrı bir veri yapısı değildir. `refs/stash` adlı bir başvurudur ve gösterdiği şey bir
işlemedir:

```bash
git rev-parse stash@{0}
```

```
48acf5295ce885fe839291522c1d8e48d7ad73e1
```

```bash
git cat-file -p stash@{0}
```

```
tree fa90a8ed35bd3b7bad8a3f7048186a030b33df2e
parent 11fe7e8840e866dda55da81f522f27f3268f1751
parent 22beea37c86e26d1cbe008233684b5d656b87945
parent f5310757c803a7c475d9ee8c0a7f972b8db76418
author Deniz Kaya <deniz@ornek.test> 1710227100 +0300
committer Deniz Kaya <deniz@ornek.test> 1710227100 +0300

On main: listeleme seçeneği, yarım
```

Üç öncül satırı vardır. Birincisi zulanın alındığı andaki dal ucudur; ikincisi hazırlık
alanının o andaki durumunu saklayan bir işleme; üçüncüsü, `-u` kullanıldığı için, izlenmeyen
dosyaları saklayan bir işlemedir. `-u` kullanılmasaydı iki öncül olurdu.

Bu yapı, dersin başındaki soruya nesne modeli düzeyinde yanıt verir: zula "geçici bir alan"
değil, olağan işlemelerden yapılmış ama hiçbir dala bağlı olmayan küçük bir tarihçe
parçasıdır. Zula girdileri de nesne veritabanında durur ve erişilemez hâle geldiklerinde çöp
toplamanın kapsamına girerler.

#### Sınırlar

Zula yereldir ve paylaşılmaz; deponun bir kopyasındaki girdiler başka kopyalarda görünmez.
Açıklamalar dışında hiçbir yapı taşımaz: girdiler ne sıralanır ne de gruplanır. Bu nedenle
uzun süreli bekletme için uygun değildir — biriken girdilerin hangi işe ait olduğu kısa sürede
belirsizleşir.

Yarım işin günler boyu bekletilmesi gerekiyorsa doğru araç zula değil, ayrı bir dal üzerinde
yazılan işlemelerdir. Dallar Dallanma ve İşbirliği kursunun konusudur.

Örnek depoda girdi geri alınır:

```bash
git stash pop
```

```
On branch main
Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git restore <file>..." to discard changes in working directory)
	modified:   ara.sh

Untracked files:
  (use "git add <file>..." to include in what will be committed)
	TODO.md

no changes added to commit (use "git add" and/or "git commit -a")
Dropped refs/stash@{0} (48acf5295ce885fe839291522c1d8e48d7ad73e1)
```

Ardından seçenek tamamlanır: betik, `-l` verildiğinde yalnızca Türkçe sütunu yazacak biçimde
yeniden yazılır, `TODO.md` silinir ve değişiklik işlenir:

```bash
cat > ara.sh <<'SON'
#!/bin/sh
# terimler.txt içinde arama yapar.

if [ $# -ne 1 ]; then
    echo "kullanım: ara.sh ARANAN | ara.sh -l" >&2
    exit 1
fi

if [ "$1" = "-l" ]; then
    cut -d '|' -f 1 terimler.txt
    exit 0
fi

if ! grep -i -- "$1" terimler.txt; then
    echo "eşleşme yok: $1" >&2
    exit 2
fi
SON
rm TODO.md
export GIT_AUTHOR_DATE="2024-03-12 10:20:00 +0300"
export GIT_COMMITTER_DATE="2024-03-12 10:20:00 +0300"
git commit -a -m "Tüm terimleri listeleyen -l seçeneğini ekle"
```

```
[main a0e3bfe] Tüm terimleri listeleyen -l seçeneğini ekle
 1 file changed, 6 insertions(+), 1 deletion(-)
```

#### Özet

- Zula, izlenen dosyalardaki değişiklikleri kenara alır ve çalışma dizinini son işlemedeki
  hâline döndürür.
- Girdiler yığıt düzeninde tutulur; `stash@{0}` en son eklenendir.
- `apply` girdiyi listede bırakır, `pop` düşürür, `drop` uygulamadan siler.
- `-u` seçeneği izlenmeyen dosyaları da kapsar.
- Zula girdisi, iki ya da üç öncülü olan ve hiçbir dala bağlı olmayan bir işlemedir.

#### Sonraki Adım

Tarihçedeki belirli noktalara insan tarafından okunabilir adlar verilmedi; her şey kırk
karakterlik kimliklerle ya da göreli gösterimlerle anıldı. Bir sürüm yayımlandığında o noktaya
kalıcı bir ad vermek gerekir. Kursun son dersi etiketleri, dördüncü nesne türünü ve anlamlı
sürümleme ile ilişkisini ele alacak.

### Etiketleme

Source: https://academia.sh/tr/kurslar/surum-kontrolune-giris/etiketleme

Tarihçedeki belirli noktalara kalıcı ad verme; hafif etiket ile etiket nesnesinin farkı, dördüncü nesne türü, etiketle konum belirleme ve anlamlı sürümleme.

Tarihçedeki noktalar buraya kadar kırk karakterlik kimliklerle ya da `HEAD~1` gibi göreli
gösterimlerle anıldı. İkisi de kalıcı ad değildir: kimlik akılda tutulamaz, göreli gösterim
tarihçe büyüdükçe başka bir işlemeyi gösterir.

**Etiket (tag)**, belirli bir işlemeye verilen sabit addır. Dal uçlarından farkı, yeni işleme
yazıldığında yerinden kıpırdamamasıdır: dal ilerler, etiket durur.

#### Hafif Etiket

En yalın biçim, bir ada bir işleme kimliği bağlar:

```bash
git tag v1.0.0 HEAD~1
git tag -l
```

```
v1.0.0
```

```bash
cat .git/refs/tags/v1.0.0
```

```
11fe7e8840e866dda55da81f522f27f3268f1751
```

Dosyanın içeriği doğrudan işleme kimliğidir. **Hafif etiket (lightweight tag)**, nesne
veritabanında yeni bir nesne oluşturmaz; yalnızca bir başvuru dosyası yazar.

```bash
git cat-file -t v1.0.0
```

```
commit
```

Ad bir işlemeyi gösteriyor. Etiketin kimin, ne zaman ve neden koyduğu hiçbir yerde kayıtlı
değil. Yayımlanan bir sürümü işaretlemek için bu yetersizdir.

```bash
git tag -d v1.0.0
```

```
Deleted tag 'v1.0.0' (was 11fe7e8)
```

#### Etiket Nesnesi

Etiket nesnesi koyanın adı ve zamanıyla birlikte saklanır; zaman da işleyen tarihinden alındığı
için önce sabitlenir (tarih değişkenleri açık oturumda tanımlıdır; yeni bir terminal
açtıysanız yeniden yazın):

```bash
export GIT_COMMITTER_DATE="2024-03-13 09:00:00 +0300"
git tag -a v1.0.0 -m "İlk kararlı sürüm: arama, harf duyarsızlığı, hata kodu" HEAD~1
git cat-file -t v1.0.0
```

```
tag
```

Nesne türü değişti. **Açıklamalı etiket (annotated tag)**, ikinci konuda tanıtılan dört nesne
türünün sonuncusudur ve nesne veritabanına yazılır:

```bash
git cat-file -p v1.0.0
```

```
object 11fe7e8840e866dda55da81f522f27f3268f1751
type commit
tag v1.0.0
tagger Deniz Kaya <deniz@ornek.test> 1710309600 +0300

İlk kararlı sürüm: arama, harf duyarsızlığı, hata kodu
```

Beş bileşen vardır: işaret edilen nesnenin kimliği, türü, etiket adı, etiketi koyan kişi ile
zamanı ve açıklama metni. Yapı, işleme nesnesine benzer — ve aynı kuralla adlandırılır:

```bash
git rev-parse v1.0.0
```

```
9c57fc4649ef6bdcd4ee73dc697fe500468d50f6
```

Bu kimlik etiket nesnesine aittir, işlemeye değil. İşaret edilen işlemeye ulaşmak için tür
dönüşümü istenir:

```bash
git rev-parse "v1.0.0^{commit}"
```

```
11fe7e8840e866dda55da81f522f27f3268f1751
```

Komutların çoğu bu dönüşümü kendiliğinden yapar; ayrım yalnızca nesnenin kendisi sorulduğunda
görünür.

```bash
git show v1.0.0 --stat
```

```
tag v1.0.0
Tagger: Deniz Kaya <deniz@ornek.test>
Date:   Wed Mar 13 09:00:00 2024 +0300

İlk kararlı sürüm: arama, harf duyarsızlığı, hata kodu

commit 11fe7e8840e866dda55da81f522f27f3268f1751
Author: Deniz Kaya <deniz@ornek.test>
Date:   Tue Mar 12 09:48:00 2024 +0300

    Aramanın harf duyarsızlığını README'de belirt

 README.md | 2 ++
 1 file changed, 2 insertions(+)
```

Çıktı önce etiketi, sonra işaret ettiği işlemeyi gösterir.

| Ölçüt | Hafif etiket | Açıklamalı etiket |
|---|---|---|
| Nesne oluşturur mu | Hayır | Evet |
| Koyan ve zaman kaydı | Yok | Var |
| Açıklama metni | Yok | Var |
| Kullanım | Geçici, yerel işaret | Yayımlanan sürüm |

#### Etiketleri Listelemek

Listeleme seçeneği tamamlandıktan sonra ikinci bir sürüm işaretlenir. Önce seçenek README'de
belgelenir ve işlenir:

```bash
cat >> README.md <<'SON'

Tüm terimleri listelemek için `./ara.sh -l` yazın.
SON
export GIT_AUTHOR_DATE="2024-03-13 11:00:00 +0300"
export GIT_COMMITTER_DATE="2024-03-13 11:00:00 +0300"
git commit -a -m "README'de -l seçeneğini belgele"
```

Ardından etiket konur:

```bash
export GIT_COMMITTER_DATE="2024-03-13 11:10:00 +0300"
git tag -a v1.1.0 -m "Listeleme seçeneği (-l) eklendi"
git tag -l
```

```
v1.0.0
v1.1.0
```

```bash
git tag -l "v1.0*"
```

```
v1.0.0
```

```bash
git tag -n
```

```
v1.0.0          İlk kararlı sürüm: arama, harf duyarsızlığı, hata kodu
v1.1.0          Listeleme seçeneği (-l) eklendi
```

Etiketler tarihçe listesinde de görünür:

```bash
git log --oneline --decorate -n 5
```

```
67c7ca6 (HEAD -> main, tag: v1.1.0) README'de -l seçeneğini belgele
a0e3bfe Tüm terimleri listeleyen -l seçeneğini ekle
11fe7e8 (tag: v1.0.0) Aramanın harf duyarsızlığını README'de belirt
c497738 Revert "Arama çıktısını yalnızca Türkçe sütuna indir"
d245350 Arama çıktısını yalnızca Türkçe sütuna indir
```

Başvuruların tümü tek komutla da listelenebilir:

```bash
git for-each-ref refs/tags
```

```
9c57fc4649ef6bdcd4ee73dc697fe500468d50f6 tag	refs/tags/v1.0.0
7cbb6f6054352e79e94cf24d5079ae5af15482f1 tag	refs/tags/v1.1.0
```

İkinci sütun nesne türünü verir; hafif etiketlerde bu sütunda `commit` yazardı.

#### Etikete Göre Konum

```bash
git describe
```

```
v1.1.0
```

Etiketten sonra yeni bir işleme yazıldığında çıktı değişir. Bir bileşik terim örneği README'ye
eklenip işlenir:

```bash
cat >> README.md <<'SON'

Bileşik terimleri tırnak içinde verin: `./ara.sh "bağlı liste"`.
SON
export GIT_AUTHOR_DATE="2024-03-14 10:00:00 +0300"
export GIT_COMMITTER_DATE="2024-03-14 10:00:00 +0300"
git commit -a -m "Bileşik terim örneği ekle"
```

```bash
git describe
```

```
v1.1.0-1-g2a41365
```

Üç bölüm vardır: en yakın etiket, o etiketten bu yana yazılan işleme sayısı ve şu anki
işlemenin kısaltılmış kimliği. Kimliğin başındaki `g`, değerin bir git nesnesi olduğunu
belirtir. Bu dizgi, çalıştırılabilir bir programın sürüm bilgisine gömüldüğünde, elde bulunan
ikili dosyanın tam olarak hangi işlemeden üretildiğini söyler.

#### Anlamlı Sürümleme

Etiket adı serbesttir; ancak sürüm işaretlemede yaygın bir düzen vardır: **anlamlı sürümleme
(semantic versioning)**. Sürüm numarası noktayla ayrılmış üç sayıdan oluşur ve her sayının
artışı bir söz verir:

| Bölüm | Ne zaman artar | Kullanıcıya söylediği |
|---|---|---|
| Ana | Geriye dönük uyumluluk bozulduğunda | Uyarlama gerekebilir |
| Ara | Uyumlu yeni yetenek eklendiğinde | Var olan kullanım bozulmaz |
| Yama | Yalnızca düzeltme yapıldığında | Davranış aynı, kusur giderildi |

Örnek depoda `v1.0.0` ilk kararlı sürümü, `v1.1.0` ise geriye dönük uyumlu bir yetenek
eklenmesini işaretledi: `-l` seçeneği önceki kullanımı bozmuyor, yalnızca yeni bir çağrı
biçimi ekliyor. Betiğin çıkış kodları değiştirilseydi ana sürümün artması gerekirdi.

Düzenin değeri, numaranın kendisinden çok verdiği sözdedir. Geriye dönük uyumluluk kavramı
Programlama Temelleri kursunda dil seçimi bağlamında tanımlanmıştı; sürüm numarası, aynı
kavramın makine tarafından okunabilir bir bildirimidir.

#### Etiketin Sınırları

Etiketler taşınabilir ama taşınmamalıdır. Bir etiket yayımlandıktan sonra başka bir işlemeye
kaydırılırsa, o etiketi daha önce almış kopyalar eski işlemeyi göstermeye devam eder; aynı ad
iki farklı içeriği adlandırır hâle gelir. Yayımlanmış bir etiketin işaret ettiği nokta
değiştirilmez; gerekiyorsa yeni bir etiket konur.

Silme de aynı sorunu taşır. Yerelde silinen bir etiket, deponun başka kopyalarında durmaya
devam eder.

Etiketler işlemelerin dışındaki nesneleri de işaret edebilir — bir bloba ya da bir ağaca etiket
konabilir. Uygulamada bu seyrek kullanılır; etiketin olağan hedefi bir işlemedir.

#### Özet

- Etiket, bir işlemeye verilen ve yeni işlemelerle yer değiştirmeyen sabit addır.
- Hafif etiket yalnızca bir başvuru dosyasıdır; açıklamalı etiket, koyanı ve açıklamayı
  saklayan ayrı bir nesnedir.
- Etiket nesnesi dördüncü nesne türüdür ve diğerleriyle aynı kuralla adlandırılır.
- `git describe`, en yakın etiketten bu yana kaç işleme geçtiğini ve şu anki kimliği verir.
- Anlamlı sürümleme, üç sayılı bir numarayla geriye dönük uyumluluk sözü verir.
- Yayımlanmış etiketler taşınmaz ve silinmez; gerektiğinde yeni etiket konur.

#### Kurs Kapanışı

Kurs boyunca tek bir depo kuruldu ve on sekiz işlemeyle bugünkü hâline geldi:

```bash
git log --oneline --decorate
```

```
2a41365 (HEAD -> main) Bileşik terim örneği ekle
67c7ca6 (tag: v1.1.0) README'de -l seçeneğini belgele
a0e3bfe Tüm terimleri listeleyen -l seçeneğini ekle
11fe7e8 (tag: v1.0.0) Aramanın harf duyarsızlığını README'de belirt
c497738 Revert "Arama çıktısını yalnızca Türkçe sütuna indir"
d245350 Arama çıktısını yalnızca Türkçe sütuna indir
377b1f8 README'ye kullanım bölümü ekle
0e74ba9 Öbek ve dizi terimlerini ekle
d3ab7b0 Yerel notları izlemeden çıkar
7e44d29 Yerel notları ekle
9b23cc3 Üretilen dosyaları yoksayma listesine al
ece664b Küme terimini ekle
2c883a7 Eşleşme bulunamadığında hata bildir
60e13bd Aramayı büyük/küçük harften bağımsız yap
43370ca Üç veri yapısı terimi ekle
3132c78 Biçim örneğindeki yazımı düzelt
546c174 Terim arama betiği ekle
13d31bf Terim listesini ve biçim belgesini ekle
```

Bu listede kursun yapısı görünür: dosyaların eklenmesi, atomik işlemeler, bir hatanın
işlenmesi ve devrilmesi, yoksayma kurallarının kurulması ve iki sürümün etiketlenmesi.

Kursun asıl konusu komutlar değil, altlarındaki modeldi. Dört nesne türü — blob, ağaç, işleme,
etiket — içerik adresli depolamayla adlandırılır; işlemeler öncül bağlarıyla bir yönlü
çevrimsiz çizge kurar; hazırlık alanı bu çizgeye eklenecek bir sonraki anlık görüntüyü
biriktirir. Bütün komutlar bu üç cümlenin sonucudur. Değiştirme neden yeni bir kimlik üretir,
devirme neden tarihçeyi bozmaz, aynı içerik neden aynı kimliği verir — üçünün de yanıtı
modeldedir.

Kurs boyunca bir konu bilinçli olarak dışarıda bırakıldı: tarihçe hep tek zincir olarak kaldı.
Oysa çizge tanımı dallanmaya izin veriyordu ve `--graph` çıktısının tek sütun çıkması bir
sınırlama değil, bu deponun özelliğiydi.

Sıradaki kurs — **Dallanma ve İşbirliği** — o sütunu çoğaltıyor. Dalın bir işaretçiden ibaret
olduğu, iki dalın nasıl birleştirildiği, çakışmaların nasıl çözüldüğü ve tarihçenin uzak
depolarla nasıl eşlendiği orada ele alınacak. Bu kursta kurulan model orada da geçerlidir:
dal, `refs/heads` altında bir dosyadan; birleştirme ise iki öncüllü bir işlemeden ibarettir.

