Ders 04 / 12
Referans Günlüğü
Yeniden yazma tarihçeyi kısaltmaz, ikiye katlar: bin işlemelik depoda ilk işlemeden dönüşümden sonra 1000 işleme erişilebilir, 1000 işleme erişilemez durumda durur; altı kayıtlık bir günlükte saklama ufku 7, 30, 60 ve 90 gün olduğunda kurtarılabilen işleme 3, 50, 500 ve 1000'dir.
İçindekiler
Önceki dersin kurtarma yollarından ikisi aynı yere bakıyordu: dal ucunun eski değerini tutan yerel kayda. Ezilmiş bir dalın geri getirilmesi de, dayanaksız kalan yerel işin kurtarılması da o kayıttan başlıyordu. Ders orada bir uyarıyla bitti — o kaydın bir ömrü var.
Bu ders o ömrü ölçer. İki soru sorulur ve ikisi ayrıdır. Birincisi: bir yeniden yazmadan sonra deponun içinde ne kalıyor, kaç işleme erişilebilir durumda ve kaçı değil. İkincisi: erişilemez kalanlar ne kadar süreyle kurtarılabilir, pencere hangi anda kapanıyor ve kapandığında ne kayboluyor.
Erişilemez Olmak, Yok Olmak Değildir
Bu kursun ilk dersinde yeniden yazmanın bir silme değil bir çoğaltma olduğu söylenmişti. Ölçüm o cümleyi sayıya çevirir. Bin işlemelik bir tarihçe yeniden yazıldığında yeni zincir de bin işlemedir; eski zincirin işlemeleri hiçbir yere gitmez. Depoda artık iki zincir vardır: biri dal ucundan erişilebilen, öbürü hiçbir başvurunun göstermediği.
Bir nesnenin erişilebilir olması, bir daldan, bir etiketten ya da HEAD’den başlayarak
öncül bağlantıları izlenerek bulunabilmesi demektir. Erişilemez nesne bu yürüyüşle bulunamaz;
ama diskte durur, kimliği verilirse okunur ve çöp toplama çalışana kadar da orada kalır.
Yeniden yazma bittiğinde depo küçülmez, büyür.
Günlük İşleme Değil, Hareket Tutar
Erişilemez zinciri kurtarmanın yolu eski ucun kimliğini bilmektir. Araç bunu kendiliğinden kaydeder: her başvurunun her hareketi yerel bir günlüğe yazılır. Referans günlüğü (reflog) budur.
Kaydın birimi bu dersin en önemli ayrımıdır. Günlük işlemeleri değil, hareketleri tutar. Beş yüz işlemeyi erişilemez bırakan bir yeniden yazma günlüğe beş yüz satır yazmaz; bir satır yazar. O satır o andaki ucu gösterir, uçtan geriye yürünerek beş yüz işlemenin hepsine ulaşılır. Kayıt sayısıyla kurtarılabilir işleme sayısı bu yüzden aynı şey değildir.
Günlüğün üç sınırı vardır. Yereldir: karşı tarafa gitmez, klonlanmaz, bir kopyanın
günlüğü öbür kopyayı kurtarmaz. Başvuru başınadır: her dalın kendi günlüğü vardır,
ayrıca HEAD’in genel bir günlüğü tutulur. Süresizdir sanılır ama değildir: kayıtlar bir
saklama ufkuna göre temizlenir ve o ufuk bir ayardır.
# öğretilen komut, örnek döküm — çalıştırılmamıştır
$ git reflog olcum
5b6c7d8 olcum@{0}: rebase (finish): refs/heads/olcum onto 9c4d7e1
2f8a1c3 olcum@{1}: commit: olcum: eşik değerini yazdır
7e1b4d2 olcum@{2}: commit: olcum: ayar dosyasını böl
$ git branch kurtarma/olcum olcum@{1}
İkinci satır kurtarmanın tamamıdır: eski uca bir dal adı verilir ve o zincir yeniden erişilebilir olur. İşlem hiçbir şeyi silmez, hiçbir başvuruyu taşımaz; bu yüzden burada tam biçimde yazılabilir. Kurtarma yolları yıkıcı değildir — yıkıcı olan, onları gerektiren işlemdir.
Günlüğün gösteremediği bir durum için ikinci bir araç vardır: deponun bütünlüğünü denetleyen alt komut, hiçbir başvurunun göstermediği nesneleri sarkık olarak listeler. Kayıt temizlenmiş ama çöp toplama henüz çalışmamışsa kurtarma oradan yapılır. O da bir okuma işlemidir.
Üçüncü sınırın pratikte en sık ödettiği durum şudur: dal silindiğinde onun günlüğü de
silinir. Yanlışlıkla silinmiş bir dalın kendi kaydına bakmak artık olanaksızdır. Bu
durumda çare HEAD’in günlüğüdür — çalışma alanının hangi uçlarda durduğu orada ayrıca
tutulur ve silinen dalın son ucu genellikle o listede görünür. İki günlüğün ayrı tutulması
bir ayrıntı değil, kurtarmanın kalan tek yolu olabilir.
Nesnelerin ne zaman gerçekten temizlendiği de yazılmalıdır. Çöp toplama kendiliğinden çalışır; bakım işlemleri sırasında tetiklenir ve elle de çağrılabilir. Ama erişilemez bir nesnenin temizlenmesi için iki koşulun birden sağlanması gerekir: onu gösteren günlük kaydı ufkun dışına düşmüş olmalı ve toplama çalışmış olmalıdır. İki koşul da sağlanana kadar nesne yerinde durur. Ufkun kendisi de tek bir sayı değildir: erişilebilir uçların kayıtları ile erişilemez uçların kayıtları ayrı ayrı ayarlanabilir ve ikincisi genellikle daha kısa tutulur.
Ölçümün varsayımları:
- YZ25 — Kurgu önceki derslerin kurgusudur ve değiştirilmez; ölçüm 1000 işlemelik tarihçe üzerinde yapılır.
- YZ26 — Yeniden yazma tarihçeyi kısaltmaz: yeni zincir aynı uzunluktadır ve eski zincirin işlemeleri depoda erişilemez durumda kalır.
- YZ27 — Referans günlüğü dal ucunun hareketlerini kaydeder, işlemeleri değil. Bir kayıt o andaki ucu tutar; o uçtan geriye erişilen bütün zinciri temsil eder.
- YZ28 — Kayıtların gösterdiği eski uçlar iç içe geçmiş soneklerdir; kurtarılabilir kümeyi en geriye giden kayıt belirler, kayıtların toplamı değil.
- YZ29 — Saklama ufku bir ayardır, sabit bir sayı değildir. Ölçüm dört değer dener: 7, 30, 60, 90 gün.
- YZ30 — Ufkun dışında kalan kayıt silinir ve yalnız o kayıttan erişilen işlemeler toplanabilir hâle gelir. Ölçüm çöp toplamanın ne zaman çalıştığını değil, hangi kümenin toplanabilir olduğunu sayar.
- YZ31 — Bu derste iki ayrı şey sayılır ve karıştırılmaz: erişilebilirlik işleme sayısıyla, bedel dokunulan nesneyle sayılır. Adım birimi kullanılmaz.
- YZ32 — Çözünürlük işlemede 1/1000, günlük kaydında 1/6’dır.
Ölçüm
"""Referans gunlugu: erisilebilirlik ve kurtarma penceresi. Bolum 1 - yeniden yazmadan sonra depoda ne kaliyor. Bolum 2 - gunluk kayitlari: kayit sayisi ile kurtarilabilir isleme ayri sey. Bolum 3 - saklama ufku pencereyi ne zaman kapatiyor. """ TOHUM = 20260814 DOSYALAR = ("olcum.py", "rapor.py", "kimlik.py", "ayar.py", "belge.md") KONUMLAR = (1, 300, 501, 800, 951, 998) UFUKLAR = (7, 30, 60, 90) def uretec(tohum): d = tohum % 2147483646 + 1 def r(n): nonlocal d d = (d * 48271) % 2147483647 return d % n return r def tarihce(n, tohum=TOHUM): """n islemelik dogrusal tarihce; her isleme bir dosyaya dokunuyor.""" r, liste = uretec(tohum), [] for i in range(n): dosya = DOSYALAR[r(5)] ikili = r(11) == 0 liste.append({"no": i + 1, "dosya": dosya, "ikili": ikili, "nesne": 2 + (40 if ikili else 0)}) return liste def yeniden_yaz(t, konum): sonra = [x for x in t if x["no"] >= konum] return len(sonra), sum(x["nesne"] for x in sonra) def gunluk(tohum=TOHUM): """Dal ucunun her hareketi bir kayit yazar; kayit gunu ve ucu tutar.""" r, kayit, gun = uretec(tohum), [], 0 for i, konum in enumerate(KONUMLAR): gun += 1 + r(30) kayit.append({"no": i + 1, "gun": gun, "konum": konum}) return kayit def kurtarilabilir(t, kayitlar): """Kayitlarin gosterdigi uclarin birlesimi: en geriye giden belirler.""" if not kayitlar: return 0, 0 return yeniden_yaz(t, min(k["konum"] for k in kayitlar)) T = tarihce(1000) G = gunluk() BUGUN = G[-1]["gun"] print(f"{'yeniden yazılan yer':>20s} {'erişilebilir':>13s} {'erişilemez':>11s}" f" {'depodaki toplam':>16s} {'erişilemez nesne':>17s}") for konum in (998, 501, 300, 1): isl, nes = yeniden_yaz(T, konum) print(f"{konum:20d} {len(T):13d} {isl:11d} {len(T) + isl:16d} {nes:17d}") print() print(f"{'kayıt':>6s} {'gün':>5s} {'eski ucun konumu':>17s}" f" {'o kayıttan erişilen':>20s}") for k in G: isl, _ = yeniden_yaz(T, k["konum"]) print(f"{k['no']:6d} {k['gun']:5d} {k['konum']:17d} {isl:20d}") print(f"kayıt sayısı {len(G)}, bugün {BUGUN}. gün") print() print(f"{'saklama ufku':>13s} {'kalan kayıt':>12s} {'kurtarılabilir işleme':>22s}" f" {'kurtarılabilir nesne':>21s} {'kalıcı kayıp':>13s}") tum_isl, _ = kurtarilabilir(T, G) for ufuk in UFUKLAR: kalan = [k for k in G if BUGUN - k["gun"] <= ufuk] isl, nes = kurtarilabilir(T, kalan) print(f"{ufuk:13d} {len(kalan):12d} {isl:22d} {nes:21d}" f" {tum_isl - isl:13d}")
yeniden yazılan yer erişilebilir erişilemez depodaki toplam erişilemez nesne
998 1000 3 1003 6
501 1000 500 1500 3000
300 1000 701 1701 4162
1 1000 1000 2000 5640
kayıt gün eski ucun konumu o kayıttan erişilen
1 11 1 1000
2 20 300 701
3 40 501 500
4 49 800 201
5 58 951 50
6 81 998 3
kayıt sayısı 6, bugün 81. gün
saklama ufku kalan kayıt kurtarılabilir işleme kurtarılabilir nesne kalıcı kayıp
7 1 3 6 997
30 2 50 260 950
60 4 500 3000 500
90 6 1000 5640 0
Depo Küçülmez
Üst tablonun ikinci sütunu dört satırda da aynı: 1000. Yeniden yazma nereden başlarsa başlasın, dal ucundan erişilen tarihçe bin işlemedir. Üçüncü sütun değişkendir: erişilemez kalan 3, 500, 701 ve 1000. Dördüncü sütun ikisinin toplamıdır ve dersin başlığını taşır — ilk işlemeden dönüşümden sonra depoda 2000 işleme durur, yarısı erişilebilir, yarısı değil.
Bu, önceki dersteki toplu dönüşümün neden hemen bir kazanç getirmediğini açıklıyor. Bir ikili varlığı tarihçeden çıkarmak deponun boyutunu düşürmez; yalnız o varlığın nesnelerini erişilemez kümeye taşır. Erişilemez nesne sütunu ilk işlemeden dönüşümde 5640’tır ve bu sayı ancak çöp toplama çalıştığında serbest kalır. Kazanç ile işlem arasında bir gecikme vardır ve o gecikme aynı zamanda kurtarma penceresidir. İkisi aynı şeydir: nesneleri tutan süre, hatayı geri alma süresidir.
Kayıt Sayısı ile Kurtarılabilir İşleme
Orta tablo günlüğün altı kaydını gösteriyor. Bir kayıt üç işleme kurtarıyor, bir kayıt bin işleme. 6 kayıtlık bir günlük 1000 işlemeyi kurtarabiliyor; oran kayıt başına yüz altmış yedi işleme. Bu, günlüğün ucuz bir düzenek olmasının nedeni: uçları saklıyor, zincirleri değil.
Kayıtların okunmasında ikinci bir bilgi daha var. Her satır hareketin türünü de yazar: bir işleme yazıldığında, bir yeniden temellendirme bittiğinde, bir dal ucu sıfırlandığında kayıt bunu ayrı ayrı bildirir. Kurtarılacak ucu ararken bakılacak yer bu alandır — aranan genellikle yeniden yazmayı bildiren satırın bir öncesindeki uçtur. Günlüğün kimliği ve türü birlikte tutması, doğru kaydı bulmayı bir tahmin işi olmaktan çıkarır.
Aynı yapı bir tuzağı da doğuruyor. Kayıtların kapsadığı kümeler iç içe geçmiş sonekler olduğu için, kurtarılabilir kümeyi kayıtların sayısı değil, aralarında en geriye gideni belirliyor. Beş kayıt kalsa bile en derin kayıt gitmişse, kurtarılabilir küme o beş kaydın en derinine kadar iner. Günlükte çok satır görmek, kurtarma kapsamı hakkında hiçbir şey söylemez.
Pencere Kapanırken
Alt tablo pencerenin nasıl kapandığını gösteriyor. Saklama ufku 90 gün olduğunda altı kaydın altısı duruyor, 1000 işlemenin hepsi kurtarılabilir ve kalıcı kayıp 0. Ufuk 60 güne indiğinde dört kayıt kalıyor ve kurtarılabilir işleme 500’e düşüyor: tarihçenin yarısı artık günlükten bulunamaz. 30 günde iki kayıt ve 50 işleme kalıyor. 7 günde geriye tek bir kayıt kalıyor, kurtarılabilir işleme 3, kalıcı kayıp 997.
Sayıların ayrık atlaması ufkun değil, kayıtların dağılımının sonucudur: onbirinci gündeki derin kayıt ufuk altmışın dışında kalır kalmaz beş yüz işleme bir anda erişilmez olur. Pencere düzgün kapanmaz, basamak basamak kapanır. Bu yüzden “günlükte bir hafta daha var” cümlesi bir güvence değildir; hangi kaydın hangi gün düştüğü bilinmeden ne kadarının kurtarılabildiği bilinemez. Basamakların yeri de rastgeledir: kayıtların günleri çalışma düzeninden gelir, kapsadıkları derinlik ise o gün hangi işin yapıldığından. İkisi arasında bir bağ yoktur, bu yüzden en derin kaydın en eski kayıt olması sık rastlanan ama garanti edilmeyen bir durumdur.
Ufkun kendisi bir ayardır ve depodan depoya değişir. Ölçümün söylediği şey belirli bir sayıyı savunmak değil, ufkun kurtarma kapsamını doğrudan belirlediğidir. Uzun ufuk daha çok kurtarma, daha çok tutulan nesne demektir; kısa ufuk tersini. İki yönlü bir ödünleşimdir ve iki yönü de bu tabloda görünür: kurtarılabilir nesne sütunu 6’dan 5640’a çıkarken serbest bırakılabilecek nesne de aynı ölçüde azalır.
Kayıp Yolları ve Kurtarma Yolları
Bu konuda sayılan her kayıp yolunun bir kurtarma yolu vardır ve dördü birlikte yazılabilir.
Yeniden yazılmış zincirin eski hâli kaybolduğunda kurtarma günlüktedir: eski uca bir dal adı verilir. Pencere kapalıysa sarkık nesne listesi ikinci yoldur.
Toplu dönüşümde çıkarılan varlık yanlışlıkla çıkarıldıysa kurtarma yine günlüktedir — ama yalnız dönüşümü yapan depoda. Ayrı klon alışkanlığı burada kendini öder: asıl depo el sürülmemiş durursa kurtarma diye bir soru doğmaz.
Ezilmiş uzak dal için kurtarma yerel günlükte değil, kopyalardadır. Ezilen tarafın yedeği bedeli ödeyen taraftır ve o yedeğin bir saklama ufku yoktur; kopya eski ucu gösterdiği sürece kurtarma açıktır.
Ufkun dışına düşmüş kayıt için kurtarma yolu yoktur. Tek çare önlemdir ve önlem yeniden yazmadan önce açılan yedek daldır: yedek dal bir başvurudur, başvurular ufka tabi değildir ve silinene kadar erişilebilirliği ayakta tutar.
Dört yolun ortak bir özelliği var ve dersin sonucu da bu: kurtarma her zaman nesneleri elinde tutan tarafta yapılır. Merkezî bir kurtarma yeri yoktur. Kendi günlüğünüz yalnız kendi deponuzu kurtarır; bir kopyanın kaybettiği işi sizin günlüğünüz göstermez, sizin ezdiğiniz dalı sizin günlüğünüz geri getirmez. Bu, önceki dersteki bedel dağılımının aynadaki görüntüsüdür — bedel kopyalara dağılıyordu, kurtarma yeteneği de kopyalara dağılmıştır.
Buradan tek satırlık bir alışkanlık çıkar: yeniden yazmadan önce ucun nerede olduğu kaydedilir. Yedek dal bunu yapmanın en ucuz yoludur ve maliyeti önceki kursun ölçtüğü kadardır — tek bir başvuru. Pencerenin ne kadar açık kalacağını sormak yerine pencereye hiç ihtiyaç duymamak, sayılan bütün yolların en kısası.
Özet
- Yeniden yazma tarihçeyi kısaltmaz. Dört konumda da erişilebilir işleme 1000 kalır; erişilemez kalan 3 / 500 / 701 / 1000 olur ve depodaki toplam 2000’e kadar çıkar.
- Erişilemez nesneler çöp toplama çalışana kadar diskte durur; ilk işlemeden dönüşümde serbest kalmayı bekleyen 5640 nesne vardır. Kazancın gecikmesi ile kurtarma penceresi aynı süredir.
- Referans günlüğü işlemeleri değil dal ucu hareketlerini kaydeder: 6 kayıt 1000 işlemeyi kurtarabilir. Kayıt sayısı kurtarma kapsamını göstermez.
- Kurtarılabilir kümeyi kayıtların en geriye gideni belirler; saklama ufku 7 / 30 / 60 / 90 gün olduğunda kurtarılabilir işleme 3 / 50 / 500 / 1000, kalıcı kayıp 997 / 950 / 500 / 0 olur.
- Günlük yereldir, başvuru başınadır ve ufka tabidir; yedek dal üçünün de dışındadır ve tek kalıcı önlemdir.
- Kurtarma işlemleri okuma işlemleridir: eski uca dal adı vermek hiçbir şeyi silmez.
Sonraki Adım
Buraya kadar tarihçe değiştirildi ve her değişikliğin bedeli dokunulan nesneyle sayıldı: etkileşimli kipte 3002, toplu dönüşümde 5640, zorlayıcı itmede kopyalar üzerinden 39480, kurtarmada pencerenin genişliğine göre 6 ile 5640 arası. Değiştirmenin bedeli artık biliniyor. Bilinmeyen, tersinin bedelidir: aynı tarihçeye soru sormak ne kadar tutar. Sonraki konu bunu ölçer — bin işlemelik bir tarihçede bir kusurun hangi işlemeyle girdiğini bulmak kaç adım sürer, ve tarihçe dört kat büyüdüğünde o adım sayısı kaça çıkar. Bedelin birimi de orada değişir: nesne değil, adım.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.