Ders 02 / 12
Toplu Tarihçe Dönüşümü
Depo genelinde bir dönüşüm ilk işlemeden başlar: bin işlemelik tarihçede 1000 kimlik değişir, 5640 nesneye dokunulur ve yeni tarihçe eskisiyle tek bir işleme bile paylaşmaz — bu yüzden her kopya yeniden klonlanmak zorundadır ve işlem geri alınamaz.
İçindekiler
Önceki ders yeniden yazmayı tek bir dalın üstünde tuttu. Plan uca yakın kaldığında bedel küçüktü: üç işlemelik bir plan altı nesneye dokunuyordu. Tarihçenin ortasından başlandığında bile işlemelerin yaklaşık yarısı kimlik değiştiriyor, geri kalan yarısı olduğu gibi kalıyordu. O yarı, ölçümün gördüğü en derin noktaydı.
Bazı işler o kadarını bile bırakmaz. Deponun ilk günlerinde işlenmiş ve orada durmaması gereken bir varlık, bütün işlemelerde yanlış yazılmış bir yazar alanı, kökün altına taşınması gereken bir dizin — bunların hepsi tarihçenin ilk işlemesinden başlamak zorundadır. Bunlara toplu tarihçe dönüşümü denir ve önceki dersin aracıyla aynı aileden olsalar da başka bir ölçekte çalışırlar. Bu dersin sorusu şudur: dönüşüm ilk işlemeden başladığında bedel ne olur, ve işlem bittikten sonra deponun öbür kopyalarının elinde ne kalır.
Kural Olarak Dönüşüm
Etkileşimli kipte plan bir listeydi: satırları görüyor, tek tek eylem yazıyordunuz. Toplu dönüşümde plan yoktur; kural vardır. Kural her işlemeye sırayla uygulanır, işlemenin ağacı kuraldan geçirilir ve sonuçtan yeni bir işleme üretilir. On işlemeyle bin işleme arasındaki fark yalnız süredir; yazılan kural aynı kuraldır.
Dört tipik gereksinim bu sınıfa girer. Bir varlığın çıkarılması: hiç işlenmemesi gereken bir ikili dosya ya da bir gizli anahtar tarihçede duruyorsa, onu son işlemeden silmek yetmez; eski işlemelerden okunabilir olmaya devam eder. Üstveri düzeltmesi: yazar ya da işleyen alanı bütün tarihçede yanlışsa. Ağaç taşıması: bir alt dizinin deponun kökü hâline getirilmesi ya da tersi. Geriye dönük normalleştirme: satır sonu ya da kodlama düzeltmesinin yalnız yeni işlemelere değil, eskilerine de uygulanması.
Aracın bu işi yapan alt komutu vardır ve depo dışında çalışan süzme araçları da vardır. Komut bu derste tam biçimde verilmez. Nedeni öğretim değil sorumluluktur: kopyalanıp çalıştırılabilir bir toplu dönüşüm satırı, çalıştırıldığı deponun tarihçesini geri alınamayacak biçimde değiştirir ve o deponun bütün kopyalarını geçersiz kılar. Aşağıdaki döküm süzgeç yerine bir yer tutucu taşır ve çalıştırılamaz.
# örnek döküm — çalıştırılmamıştır, komut tam biçimde verilmemiştir $ git filter-branch <süzgeç> -- --all Rewrite 9c4d7e1 (1/1000) (0 seconds passed, remaining 0 predicted) Rewrite 4a5b6c7 (2/1000) (0 seconds passed, remaining 0 predicted) ... Ref 'refs/heads/ana' was rewritten
Dökümün sayacı dersin ölçüsünü doğrudan gösteriyor: sayaç birden bine kadar sayıyor, çünkü bin işlemenin bini yeniden üretiliyor.
Dökümün sonundaki satır ikinci bir şey söylüyor. Etkileşimli kip tek bir dalın ucundan çalışır; toplu dönüşüm başvuruların tümüne uygulanabilir ve genellikle öyle uygulanır. Nedeni ölçümle doğrudan ilgilidir: dönüşümün dışında bırakılan bir dal ya da bir etiket eski zinciri göstermeye devam eder, o zincir erişilebilir kalır ve çıkarılmak istenen varlık depodan gitmez. Bir dalı unutmak, dönüşümü yapmamakla aynı sonucu verir. Bu yüzden kapsam kararı kuralın kendisinden önce verilir: hangi başvurular dönüşüme girecek, hangileri dönüşümden önce silinecek.
Dönüşüm Nereden Başlar
Kural her işlemeye uygulanır, ama kimlik değişimi her işlemede başlamaz. Kuralın içeriği gerçekten değiştirdiği ilk işlemeye kadar üretilen işlemeler eskisiyle birebir aynı çıkar ve aynı kimliği alır. Değişim o ilk işlemede başlar ve önceki dersin kuralı gereği uca kadar sürer.
Bu, bir dosyayı tarihçeden çıkarma işini şu soruya indirger: o dosyaya ilk ne zaman dokunulmuş. Yanıt genellikle hoş değildir. Bir depoda birkaç dosya varsa ve her işleme onlardan birine dokunuyorsa, her dosyanın ilk görünüşü tarihçenin en başındadır. Ölçüm bunu beş dosya ve bir ikili varlık için ayrı ayrı sorar.
Ölçümün varsayımları:
- YZ9 — Kurgu önceki dersin kurgusudur ve değiştirilmez: dört ölçek (50, 200, 1000, 4000), her işleme beş dosyadan birine dokunur, on birde biri bir ikili varlık taşır.
- YZ10 — Toplu dönüşüm her işlemeye uygulanan bir kuraldır. Ölçüm kuralın ne yaptığını değil, kaç işlemeyi yeniden ürettiğini sayar; bu yüzden yazar düzeltmesiyle dosya çıkarma aynı sütunda durur.
- YZ11 — Kimlik değişimi, kuralın içeriği gerçekten değiştirdiği ilk işlemede başlar ve tarihçenin ucuna kadar sürer.
- YZ12 — Bir dosyayı çıkarmak, o dosyaya ilk dokunan işlemeden başlar; ikili varlık için başlangıç, ikili taşıyan ilk işlemedir.
- YZ13 — Bu dersin bedel birimi dokunulan nesnedir. Kimliği değişen işleme sayısı kümenin genişliğidir; adım birimi bu derste kullanılmaz.
- YZ14 — Paylaşılan önek, yeni tarihçenin eskisiyle ortak kalan işlemeleridir: başlanan konumdan bir öncesine kadar olan aralık.
- YZ15 — Getirilecek nesne, karşı tarafın elinde bulunmayan nesnelerin sayısıdır; ortak önek dışındaki her nesne yeniden aktarılır. Bu bir ağ ölçümü değil, nesne sayımıdır.
- YZ16 — Kümenin çözünürlüğü dört ölçekte 1/50, 1/200, 1/1000, 1/4000’dir.
Ölçüm
"""Toplu tarihce donusumu: ilk islemeden baslayan yeniden yazmanin bedeli. Bolum 1 - dort olcekte ilk islemeden donusum. Bolum 2 - hangi varlik cikarilirsa donusum nereden baslamak zorunda. Bolum 3 - eski ve yeni tarihcenin paylastigi onek. """ TOHUM = 20260814 DOSYALAR = ("olcum.py", "rapor.py", "kimlik.py", "ayar.py", "belge.md") IKILI_VARLIK = "sunum.bin" OLCEKLER = (50, 200, 1000, 4000) 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 ilk_dokunus(t, ad): """Cikarilacak varliga ilk dokunan isleme: donusum oradan baslar.""" for x in t: if x["ikili"] if ad == IKILI_VARLIK else x["dosya"] == ad: return x["no"] return 0 print(f"{'işleme':>7s} {'kimliği değişen':>16s} {'dokunulan nesne':>16s}" f" {'oran':>6s} {'paylaşılan önek':>16s}") for n in OLCEKLER: t = tarihce(n) isl, nes = yeniden_yaz(t, 1) print(f"{n:7d} {isl:16d} {nes:16d} {isl / n:6.3f}" f" {len(t) - isl:16d}") print() T = tarihce(1000) print(f"{'çıkarılan varlık':<17s} {'ilk dokunuş':>12s} {'kimliği değişen':>16s}" f" {'dokunulan nesne':>16s} {'oran':>6s}") for ad in DOSYALAR + (IKILI_VARLIK,): k = ilk_dokunus(T, ad) isl, nes = yeniden_yaz(T, k) print(f"{ad:<17s} {k:12d} {isl:16d} {nes:16d} {isl / len(T):6.3f}") print() print(f"{'başlanan konum':>15s} {'paylaşılan önek':>16s} {'ortak nesne':>12s}" f" {'getirilecek nesne':>18s}") for konum in (1, 2, 9, 501): ortak = sum(x["nesne"] for x in T if x["no"] < konum) print(f"{konum:15d} {konum - 1:16d} {ortak:12d}" f" {sum(x['nesne'] for x in T) - ortak:18d}")
işleme kimliği değişen dokunulan nesne oran paylaşılan önek
50 50 380 1.000 0
200 200 920 1.000 0
1000 1000 5640 1.000 0
4000 4000 22600 1.000 0
çıkarılan varlık ilk dokunuş kimliği değişen dokunulan nesne oran
olcum.py 1 1000 5640 1.000
rapor.py 8 993 5586 0.993
kimlik.py 4 997 5634 0.997
ayar.py 3 998 5636 0.998
belge.md 2 999 5638 0.999
sunum.bin 6 995 5630 0.995
başlanan konum paylaşılan önek ortak nesne getirilecek nesne
1 0 0 5640
2 1 2 5638
9 8 56 5584
501 500 2640 3000
Oran Bire Sabitlenir
Üst tablo dört ölçekte aynı işlemi yapıyor ve oran sütunu tek bir değer veriyor: 1,000. Bin işlemelik tarihçede 1000 kimlik değişiyor ve 5640 nesneye dokunuluyor. Önceki dersin ortadan yeniden yazması aynı tarihçede 501 kimlik ve 3002 nesne demekti; ilk işlemeden başlamak bu sayıyı yaklaşık ikiye katlıyor. Ama asıl fark sağdaki sütunda: paylaşılan önek 0. Ortadan yeniden yazmada eski ve yeni tarihçe ilk 500 işlemeyi paylaşıyordu; burada tek bir ortak işleme kalmıyor.
Oranın sabitlenmesi ölçeğin önemsiz olduğu anlamına gelmez, tersini söyler. Oran sabit olduğu için mutlak bedel tarihçeyle birlikte doğrusal büyür: dört bin işlemelik tarihçede dokunulan nesne 22600’dür ve bu, elli işlemeliğin altmış katıdır. Ölçüm bir süre ölçmüyor, ama sayının pratik karşılığı bellidir — dönüşüm bir anlık iş değil, planlanması gereken bir iştir.
Orta tablo başlangıç noktasının seçilebilir bir şey olmadığını gösteriyor. Beş dosyanın ve ikili varlığın ilk dokunuşları 1, 8, 4, 3, 2 ve 6 numaralı işlemelerde. En geç görüneni sekizinci işleme ve onu çıkarmak bile 993 işlemeyi yeniden yazdırıyor — tarihçenin 0,993’ü. Bu bir tesadüf değil, sayının doğrudan sonucudur: bir avuç dosyanın paylaşıldığı bir depoda her dosya ilk birkaç işlemede görünür. Toplu dönüşümde “tarihçenin bir kısmı” diye bir seçenek yoktur; seçenek tarihçenin tamamı ile tarihçenin neredeyse tamamı arasındadır.
Alt tablo bedelin nereye düştüğünü söylüyor. Başlangıç konumu 1 olduğunda karşı tarafın elindeki hiçbir nesne işe yaramaz: ortak nesne 0, getirilecek nesne 5640, yani deponun tamamı. Konum 501 olsaydı ortak nesne 2640 olur ve aktarılacak miktar 3000’e inerdi. Aradaki fark yalnız nicelik değil, nitelik farkıdır: ortak bir ata varken karşı taraf getirme yapabilir, yokken yapabileceği tek şey klonlamaktır. Getirme işlemi elde olanın üzerine ekler; eklenecek bir taban kalmadığında getirme adı üstünde bir getirme olmaktan çıkar.
Dönüşümün Değiştirmediği Şey
Sayılar yalnız bedeli veriyor; dönüşümün tarihçeye ne yaptığını vermiyor. O tarafta durum şaşırtıcı biçimde sakindir. Kural yalnız üstveriye dokunuyorsa — yazar alanı gibi — her işlemenin getirdiği değişiklik olduğu gibi kalır, sıra korunur, dalların yapısı korunur. Önceki kursun ölçtüğü sorular aynı yanıtları alır; değişen yalnız o yanıtların bağlı olduğu kimliklerdir. Toplu dönüşüm çoğu durumda tarihçenin yanıtlarını değil, adreslerini değiştirir.
Bir durumda bu doğru değildir: kural bir varlığı çıkarıyorsa, o varlığa dokunan işlemelerin getirdiği değişiklik de kaybolur. O dosyanın satır tarihçesi artık sorulamaz, ona dokunan işlemeler artık ona dokunmuş görünmez. Kaybolan bilgi budur ve dönüşümün amacı da genellikle tam olarak budur. Ayrımı yapmak gerekir: üstveri düzeltmesi bilgi silmez, varlık çıkarma siler. İkisi aynı bedeli öder ve aynı ölçüde geri alınamazdır, ama tarihçenin okunabilirliği bakımından aynı işlem değildirler.
Geri Alınamazlık ve Güvenli Yol
Toplu dönüşüm geri alınamaz bir işlemdir ve bunun iki ayrı nedeni vardır.
Yerelde eski zincir erişilemez kalır. Referans günlüğü bir süre onu gösterir, sonra çöp toplama nesneleri temizler; kurtarma penceresi bu konunun dördüncü dersinde ölçülür. Bu ara dönemin doğrudan bir sonucu vardır ve sık gözden kaçar: dönüşümü yapmış olan depo, dönüşüm biter bitmez temiz değildir. Çıkarılmış varlığın nesneleri erişilemez durumda ama yerinde durur; kimliğini bilen biri onları hâlâ okuyabilir. Temiz olan şey, o depodan alınan yeni bir klondur — çünkü klonlama yalnız erişilebilir nesneleri aktarır. Bu, “ayrı klon üzerinde çalış” alışkanlığının yalnız güvenlik değil, sonuç bakımından da doğru yol olmasının nedenidir.
Kopyalarda kurtarma diye bir şey yoktur, çünkü kurtarılacak bir kayıp da yoktur: her kopyanın elinde eski zincir olduğu gibi durur. Sorun budur. Eski zinciri elinde tutan bir kopya yeni tarihçeyle birleştirilirse, çıkarılan varlık geri gelir ve dönüşüm boşa gider. Bu yüzden her kopya yeniden klonlanmak zorundadır ve bu kural bir öneri değil, işlemin tanımının parçasıdır. Kopyalarını değiştirmediğiniz sürece toplu dönüşüm tamamlanmamıştır.
Dönüşümün etkisi depo dışına da taşar. Eski kimlikler bir sorun izleme kaydında, bir yayım notunda ya da bir yapı kaydında yazılıysa, o kimlikler artık hiçbir şeyi göstermez. Etiketler eski işlemelere bağlıysa ayrıca ele alınmaları gerekir.
Güvenli yol dört maddedir. Birincisi ayrı klondur: dönüşüm asıl depoda değil, onun taze bir kopyasında denenir ve asıl depo doğrulama bitene kadar el sürülmeden bekler. İkincisi doğrulamadır: yeni tarihçede çıkarılmak istenen varlığın gerçekten kalmadığı ve işleme sayısının beklenen sayı olduğu ölçülür. Doğrulama üç soruya yanıt arar — dönüşüm sonrası işleme sayısı nedir, çıkarılan varlığın adı hiçbir işlemenin ağacında geçiyor mu, ve dönüşüme girmemiş bir başvuru kalmış mı. Üçü de okuma işlemleridir ve hiçbirinin yıkıcı tarafı yoktur; ölçüm bunları saymayı zaten yapıyor, aynı sayım gerçek bir depoda da yapılabilir. Üçüncüsü eşgüdümdür: kopyaların ne zaman değiştirileceği önceden duyurulur, çünkü değişimi kaçıran bir kopya eski zinciri geri getirebilir. Dördüncüsü sızıntı kuralıdır: tarihçeden çıkarılan bir gizli anahtar çıkarılmakla geçersiz olmaz. Bir anahtar bir kez yazıldıysa yenilenmelidir; toplu dönüşüm onun okunmasını zorlaştırır, olmamış hâle getirmez.
Eşgüdüm maddesi uygulamada bir sıraya dönüşür. Dönüşüm bir ana bağlanır: o ana kadar herkes elindeki işi karşı tarafa yazar, o andan sonra kimse eski zincirden yeni iş türetmez, dönüşüm uygulanır, kopyalar yenilenir ve ancak ondan sonra çalışmaya devam edilir. Sıranın hangi adımı atlanırsa atlansın sonuç aynıdır: eski zincirden türetilmiş tek bir işleme yeni tarihçeye girdiğinde dönüşüm bozulur ve baştan yapılması gerekir. Bu, toplu dönüşümü teknik bir işlem olmaktan çıkarıp bir takvim işi hâline getirir; bedelin ölçülmeyen ama çoğu zaman en büyük kalemi de budur.
Özet
- Toplu dönüşüm bir plan değil bir kuraldır: her işlemeye uygulanır ve her işlemeyi yeniden üretir. Aracın alt komutu ve depo dışı süzme araçları bu işi yapar; komut burada tam biçimde verilmez.
- Kimlik değişimi, kuralın içeriği değiştirdiği ilk işlemede başlar. Bir dosyayı çıkarmak için o dosyanın ilk görünüşüne kadar geri gidilir.
- İlk işlemeden dönüşüm dört ölçekte 380 / 920 / 5640 / 22600 nesneye dokunur ve oran her ölçekte 1,000’dir; bin işlemelik tarihçede 1000 kimlik değişir.
- Beş dosyanın ve ikili varlığın ilk dokunuşları 1 ile 8 arasındadır; en geç görünen varlığı çıkarmak bile tarihçenin 0,993’ünü yeniden yazdırır.
- Paylaşılan önek 0’a indiğinde ortak ata kalmaz: karşı taraf getirme yapamaz, 5640 nesnenin tamamını yeniden klonlamak zorundadır.
- İşlem geri alınamaz. Güvenli yol ayrı klon, doğrulama, eşgüdüm ve sızan anahtarın yenilenmesidir.
Sonraki Adım
Bu derste bedel bir kez sayıldı ve tek bir depoda kaldı: bin kimlik, beş bin altı yüz kırk nesne, sıfır ortak ata. Sayının eksik bıraktığı taraf şudur — yeniden yazılmış tarihçeyi karşı tarafa yazmak, karşı taraftaki zinciri ezmek demektir ve bunu yapan kişi bedelin kendi payına düşen kısmını ödemez. Sonraki ders bu ayrımı ölçer: bin işlemelik bir tarihçede son işlemeyi düzeltmekle ilk işlemeyi düzeltmek arasında kimlik bakımından bin kat fark varken, deponun kopyaları bakımından hiç fark olup olmadığı.
İlerlemeni kaydetmek ve not almak için Giriş yap
Notlarım
Not almak için giriş yapmalısın.