git gc - aggressive vs git repack


91

gitDeponun boyutunu küçültmenin yollarını arıyorum . Aramak beni git gc --aggressiveçoğu zaman götürür . Bunun tercih edilen yaklaşım olmadığını da okudum.

Neden? koşarsam nelere dikkat etmeliyim gc --aggressive?

git repack -a -d --depth=250 --window=250tavsiye edilir gc --aggressive. Neden? repackBir havuzun boyutunu nasıl küçültür? Ayrıca, bayraklar hakkında oldukça açık değilim --depthve --window.

Ben arasında neler seçmeliyim gcve repack? Ne zaman kullanmalıyım gcve repack?

Yanıtlar:


78

Bugünlerde bir fark yok: git gc --aggressiveLinus'un 2007'de yaptığı öneriye göre çalışıyor; aşağıya bakınız. Sürüm 2.11'den (Q4 2016) itibaren, git varsayılan olarak 50 derinliğe ayarlanmıştır. 250 boyutunda bir pencere iyidir çünkü her nesnenin daha büyük bir bölümünü tarar, ancak 250'de derinlik kötüdür çünkü her zinciri çok eskiye işaret eder. az miktarda daha düşük disk kullanımı için gelecekteki tüm git işlemlerini yavaşlatan nesneler .


Tarihsel arka plan

Linus, git gc --aggressiveyalnızca kendi sözleriyle, " gerçekten kötü bir paket" veya "gerçekten korkunç derecede kötü deltalar" , ancak "hemen hemen her zaman, diğer durumlarda, aslında gerçekten kötü yapılacak şey." Sonuç, havuzunuzu başladığınızdan daha kötü durumda bile bırakabilir!

"Uzun ve karmaşık bir geçmişi" içe aktardıktan sonra bunu düzgün bir şekilde yapmak için önerdiği komut,

git repack -a -d -f --depth=250 --window=250

Ancak bu , depo geçmişinizden istenmeyen gunkları zaten kaldırdığınızı ve git filter-branchbelgelerde bulunan bir depoyu küçültmek için kontrol listesini izlediğinizi varsayar .

git-filter-branch, bir dosya alt kümesinden kurtulmak için, genellikle --index-filterve --subdirectory-filter. İnsanlar ortaya çıkan deponun orijinalinden daha küçük olmasını bekler, ancak onu küçültmek için birkaç adıma daha ihtiyacınız vardır, çünkü Git siz söyleyene kadar nesnelerinizi kaybetmemek için çok çalışır. Önce şunlardan emin olun:

  • Bir blob ömrü boyunca taşınmışsa, bir dosya adının tüm değişkenlerini gerçekten kaldırmışsınızdır. git log --name-only --follow --all -- filenameyeniden adlar bulmanıza yardımcı olabilir.

  • Gerçekten tüm referansları filtrelediniz: --tag-name-filter cat -- --allarama yaparken kullanın git filter-branch.

O zaman daha küçük bir depo almanın iki yolu vardır. Daha güvenli bir yol, orijinalinizi sağlam tutan klonlamaktır.

  • İle klonlayın git clone file:///path/to/repo. Klon, kaldırılan nesnelere sahip olmayacaktır. Git-clone'a bakın. (Düz bir yolla klonlamanın yalnızca her şeyi sabitlediğini unutmayın!)

Herhangi bir nedenle onu gerçekten klonlamak istemiyorsanız, bunun yerine aşağıdaki noktaları kontrol edin (bu sırayla). Bu çok yıkıcı bir yaklaşımdır, bu nedenle bir yedekleme yapın veya klonlamaya geri dönün. Uyarıldın.

  • Git-filter-branch tarafından yedeklenen orijinal referansları kaldırın:

    git for-each-ref --format="%(refname)" refs/original/ |
      xargs -n 1 git update-ref -d
    
  • İle tüm yeniden blog'ları sona erdirin git reflog expire --expire=now --all.

  • Çöp Tüm başvurulmayan nesneleri toplamak git gc --prune=now(veya eğer senin git gciçin destek argümanları yeni yetmez --prune, kullanmak git repack -ad; git pruneyerine).


Date: Wed, 5 Dec 2007 22:09:12 -0800 (PST)
From: Linus Torvalds <torvalds at linux-foundation dot org>
To: Daniel Berlin <dberlin at dberlin dot org>
cc: David Miller <davem at davemloft dot net>,
    ismail at pardus dot org dot tr,
    gcc at gcc dot gnu dot org,
    git at vger dot kernel dot org
Subject: Re: Git and GCC
In-Reply-To: <4aca3dc20712052111o730f6fb6h7a329ee811a70f28@mail.gmail.com>
Message-ID: <alpine.LFD.0.9999.0712052132450.13796@woody.linux-foundation.org>
References: <4aca3dc20712051947t5fbbb383ua1727c652eb25d7e@mail.gmail.com>
            <20071205.202047.58135920.davem@davemloft.net>
            <4aca3dc20712052032n521c344cla07a5df1f2c26cb8@mail.gmail.com>
            <20071205.204848.227521641.davem@davemloft.net>
            <4aca3dc20712052111o730f6fb6h7a329ee811a70f28@mail.gmail.com>

6 Aralık 2007 Perşembe günü Daniel Berlin şunları yazdı:

Aslında, git-gc --aggressivebu aptalca şeyi bazen bir SVN deposundan dönüştürüp dönüştürmediğinize bakılmaksızın dosyaları paketlemek için yapıyor.

Kesinlikle. git --aggressiveçoğunlukla aptaldır. Bu gerçekten yalnızca "Biliyorum, gerçekten kötü bir paketim ve yaptığım tüm kötü paketleme kararlarını atmak istiyorum .

Bunu açıklamak için, git delta zincirlerinin nasıl çalıştığını ve diğer birçok sistemden ne kadar farklı olduklarını açıklamaya değer (muhtemelen bunun farkındasınız, ancak yine de temelleri gözden geçirmeme izin verin).

Diğer SCM'lerde, bir delta zinciri genellikle sabittir. "İleri" veya "geriye doğru" olabilir ve siz depoyla çalışırken biraz gelişebilir, ancak genellikle bir tür tek SCM varlığı olarak temsil edilen tek bir dosyadaki değişiklikler zinciridir. CVS'de, bu açıkça *,vdosyadır ve diğer birçok sistem oldukça benzer şeyler yapar.

Git ayrıca delta zincirleri de yapıyor, ancak onları çok daha "gevşek" yapıyor. Sabit bir varlık yoktur. Deltalar, git'in iyi bir delta adayı (oldukça başarılı çeşitli buluşsal yöntemler ile) olarak gördüğü herhangi bir rasgele başka versiyona karşı oluşturulur ve kesinlikle hiçbir katı gruplama kuralı yoktur.

Bu genellikle çok iyi bir şeydir. Çeşitli kavramsal nedenlerden dolayı iyidir ( yani , dahili olarak git hiçbir zaman tüm revizyon zincirini önemsemeye bile gerek duymaz - gerçekten deltalar açısından düşünmez), ama aynı zamanda harika çünkü esnek olmayan delta kurallarından kurtulmak demektir Git'in iki dosyayı bir araya getirme konusunda hiçbir problemi yok, örneğin - sadece keyfi yok*,v bazı gizli anlamı olan "revizyon dosyaları" .

Bu aynı zamanda delta seçiminin çok daha açık uçlu bir soru olduğu anlamına gelir. Delta zincirini tek bir dosyayla sınırlarsanız, deltalar hakkında ne yapacağınız konusunda gerçekten çok fazla seçeneğiniz olmaz, ancak git'te bu gerçekten tamamen farklı bir sorun olabilir.

Ve gerçekten kötü bir şekilde adlandırılmış olan yer burasıdır --aggressive. Git genellikle delta bilgisini yeniden kullanmaya çalışırken (çünkü bu iyi bir fikirdir ve daha önce bulduğumuz tüm iyi deltaları yeniden bulmak için CPU zamanını boşa harcamaz), bazen siz "boş bir sayfayla baştan başlayalım ve önceki tüm delta bilgilerini yok sayalım ve yeni bir delta kümesi oluşturmaya çalışalım" demek istiyorum.

Yani --aggressive gerçekten agresif olmakla ilgili değil, daha önce verdiğimiz bir kararı yeniden yaparak CPU zamanını boşa harcamakla ilgili!

Bazen bu iyi bir şeydir. Özellikle bazı ithalat araçları gerçekten korkunç derecede kötü deltalar oluşturabilir. Kullanan her şeygit fast-importÖrneğin, büyük olasılıkla çok iyi bir delta düzenine sahip değildir, bu nedenle "Temiz bir sayfadan başlamak istiyorum" demeye değer olabilir.

Ama neredeyse her zaman, diğer durumlarda, aslında yapılması gerçekten çok kötü bir şey. Bu, CPU zamanını boşa harcayacak ve özellikle daha önce deltaing konusunda gerçekten iyi bir iş çıkardıysanız, sonuç zaten bulduğunuz tüm bu iyi deltaları yeniden kullanmayacaktır , bu yüzden aslında çok fazla daha da kötü sonuç!

Junio'ya bir yama göndereceğim. git gc --aggressive Belgeleri . Yararlı olabilir, ancak genellikle ne yaptığını çok derin bir düzeyde anladığınızda ve bu dokümantasyon bunu yapmanıza yardımcı olmadığında faydalıdır.

Genel olarak, artımlı yapmak git gcdoğru yaklaşımdır ve yapmaktan daha iyidir git gc --aggressive. Eski deltaları yeniden kullanacak ve bu eski deltalar bulunamadığında (ilk etapta artımlı GC yapmanın nedeni!) Yenilerini yaratacak.

Öte yandan, "uzun ve karmaşık bir tarihin ilk ithalatı" nın, gerçekten iyi deltaları bulmak için çok zaman harcamaya değecek bir nokta olduğu kesinlikle doğrudur . Daha sonra, her kullanıcı (bunu git gc --aggressivegeri almak için kullanmadıkları sürece!) Bu tek seferlik olaydan yararlanacaktır. Bu nedenle, özellikle uzun bir geçmişe sahip büyük projeler için, deltaya kodu bulmasını söyleyerek biraz fazladan çalışma yapmaya değer.

Öyleyse eşdeğeri git gc --aggressive- ancak düzgün yapıldığında - gibi bir şey (bir gecede) yapmaktır

git repack -a -d --depth=250 --window=250

burada bu derinlik meselesi, delta zincirlerinin ne kadar derin olabileceğiyle ilgilidir (eski tarih için onları daha uzun hale getirin - uzay ek yüküne değer) ve pencere meselesi, her delta adayının taramasını istediğimiz nesne penceresinin ne kadar büyük olduğuyla ilgilidir.

Ve burada, pekala eklemek isteyebilirsiniz -f bayrağı ("tüm eski deltaları bırak" dır, çünkü şimdi gerçekten bunun iyi adaylar bulduğundan emin olmaya çalışıyorsunuz.

Ve sonra sonsuza kadar sürecek ( yani , "bir gecede yap" şeyi). Ancak sonuç şu ki, o depodan aşağı akıştaki herkes, kendi başına herhangi bir çaba harcamadan çok daha iyi paketler alacak.

          Linus

2
Derinlikle ilgili yorumunuz biraz kafa karıştırıcı. İlk başta, son derece yanlış olduğunuzu, saldırganlığın git deposunu büyük ölçüde hızlandırdığından şikayet edecektim. Agresif bir çöp toplama yaptıktan sonra, git durumu saniyelere düşürüldü. Ama sonra agresif gc'nin repoyu yavaşlattığını değil, sadece aşırı derecede büyük bir derinlik boyutunu kastettiğinizi fark ettim.
user6856

58

Gc & repack'i ne zaman kullanmalıyım?

" Git Çöp toplama işlemi tam olarak çalışmıyor " da bahsettiğim gibi , a git gc --aggressivetek başına ne yeterli ne de yeterli.
Ve aşağıda açıkladığım gibi , çoğu zaman gerekli değildir.

En etkili kombinasyon eklemek git repack, aynı zamanda git prune:

git gc
git repack -Ad      # kills in-pack garbage
git prune           # kills loose garbage

Not: Git 2.11 (Q4 2016) varsayılan gc aggressivederinliği 50 olarak ayarlayacak

Bkz. 07e7dbf (11 Ağu 2016), Jeff King ( peff) .
(Göre Birleştirilmiş - Junio Cı Hamano gitster- içinde 0952ca8 tamamlama 2016, 21 Eyl)

gc: varsayılan agresif derinlik 50'dir

" git gc --aggressive" delta zinciri uzunluğunu 250 ile sınırlamak için kullanılır; bu, ek alan tasarrufu sağlamak için çok derin ve çalışma zamanı performansı için zararlıdır.
Limit 50'ye düşürüldü.

Özet şu şekildedir: mevcut varsayılan 250, fazla yer tasarrufu sağlamaz ve CPU'ya mal olur. Bu iyi bir değiş tokuş değil.

" --aggressive" İşareti git-gcüç şey yapar:

  1. -fmevcut deltaları atmak ve sıfırdan yeniden hesaplamak için " " kullanın
  2. deltaları daha dikkatli görmek için "--window = 250" kullanın
  3. daha uzun delta zincirleri yapmak için "--depth = 250" kullanın

(1) ve (2) maddeleri "agresif" bir yeniden paketleme için iyi eşleşmelerdir.
Yeniden paketlemeden daha iyi bir paket elde etme umuduyla daha fazla hesaplama çalışması yapmasını istiyorlar. Yeniden paketleme sırasında masrafları ödersiniz ve diğer işlemler yalnızca faydayı görür.

Öğe (3) o kadar net değil.
Daha uzun zincirlere izin vermek, deltalarda daha az kısıtlama anlamına gelir, bu da potansiyel olarak daha iyi olanları bulma ve biraz yer tasarrufu anlamına gelir.
Ancak bu, deltalara erişen operasyonların daha uzun zincirleri takip etmesi gerektiği anlamına gelir ve bu da performanslarını etkiler.
Yani bu bir değiş tokuş ve değiş tokuşun iyi bir şey olduğu bile açık değil.

( Çalışma için taahhüt bölümüne bakın )

Derinliği düşürdükçe düzenli işlemler için CPU tasarruflarının arttığını görebilirsiniz.
Ancak, derinlik arttıkça alan tasarrufunun o kadar büyük olmadığını da görebiliriz. 10 ile 50 arasında% 5-10 tasarruf etmek muhtemelen CPU ödünleşmesine değer. 50'den 100'e gitmek için% 1 veya 100'den 250'ye gitmek için başka bir% 0,5 tasarruf etmek muhtemelen yeterli değildir.


CPU tasarrufundan bahsetmişken, " git repack" --threads=<n>seçeneği kabul etmeyi ve paket nesnelerine aktarmayı öğrendi .

Bkz. 40bcf31 (26 Nisan 2017), Junio ​​C Hamano ( gitster) .
(Göre Birleştirilmiş - Junio Cı Hamano gitster- içinde 31fb6f4 tamamlama 2017 29 Mayıs)

yeniden paketleme: kabul edin --threads=<n>ve aktarınpack-objects

Bunu zaten --window=<n>ve için yapıyoruz --depth=<n>; bu, kullanıcı --threads=1birden fazla iş parçacığının yarışmasından etkilenmeden tekrarlanabilir test için zorlamak istediğinde yardımcı olacaktır .


3
"Git Çöp koleksiyonu tam olarak çalışmıyor" bağlantısındaki Linus iş parçacığından bahsetmiştim
VonC

1
Bu modern güncelleme için teşekkürler ! Buradaki diğer tüm cevaplar eskidir. Şimdi bunun git gc --aggressiveiki kez düzeltildiğini görüyoruz : İlk olarak, Linus'un 2007'de "daha iyi bir paketleme yöntemi" olarak önerdiği şeyi yapmak. Ve sonra Git 2.11'de Linus'un önerdiği ancak zararlı olduğu ortaya çıkan aşırı nesne derinliğinden kaçınmak için (gelecekteki tüm Git işlemlerini yavaşlatır ve bahsetmeye değer herhangi bir yer tasarrufu sağlamaz).
gw0

git gc, ardından git repack -Ad ve git prune depomun boyutunu artırıyor ... neden?
devops

@devops Emin değilim: Git'in hangi sürümünü kullanıyorsunuz? Bunun için yeni bir soru sorabilirsiniz (işletim sistemi,
deponuzun

man git-repackdiyor ki -d: "Gereksiz gevşek nesne dosyalarını kaldırmak için git prune-pack'i de çalıştırın." Yoksa bunu git pruneda yapıyor mu? man git-prunediyor In most cases, users should run git gc, which calls git prune., peki sonra ne işe yarar git gc? Sadece kullanmak daha iyi veya yeterli olmaz mıydı git repack -Ad && git gc?
Jakob

14

İle ilgili sorun git gc --aggressive , seçenek adı ve belgelerinin yanıltıcı olmasıdır.

As Linus kendisi bu postada açıklıyor ne git gc --aggressiveikonların yapar şudur:

Git genellikle delta bilgisini yeniden kullanmaya çalışırken (çünkü bu iyi bir fikir ve daha önce bulduğumuz tüm iyi deltaları yeniden bulmak için CPU zamanını boşa harcamıyor), bazen "baştan başlayalım, boş seçenek listesi ve önceki tüm delta bilgilerini yok sayın ve yeni bir delta kümesi oluşturmaya çalışın ".

Git bu deltaları çok esnek olarak belirlediğinden, genellikle git'te deltaları yeniden hesaplamaya gerek yoktur. Sadece gerçekten çok kötü deltalarınız olduğunu biliyorsanız mantıklıdır. Linus'un açıkladığı gibi, esas olarakgit fast-import bu kategoriye girer.

Git, çoğu zaman yararlı deltaları belirlemede oldukça iyi bir iş çıkarır ve kullanmak git gc --aggressive, sizi çok fazla CPU zamanı israf ederken potansiyel olarak daha da kötü olan deltalarla bırakacaktır.


Linus postasını, git repackbüyük --depthve--window çoğu zaman daha iyi bir seçim olduğu ; özellikle büyük bir projeyi içe aktardıktan ve git'in iyi deltalar bulduğundan emin olmak istiyorsanız.

Öyleyse eşdeğeri git gc --aggressive- ancak düzgün yapıldığında - gibi (bir gecede)

git repack -a -d --depth=250 --window=250

burada bu derinlik meselesi, delta zincirlerinin ne kadar derin olabileceğiyle ilgilidir (eski tarih için onları daha uzun hale getirin - uzay ek yüküne değer) ve pencere meselesi, her delta adayının taramasını istediğimiz nesne penceresinin ne kadar büyük olduğuyla ilgilidir.

Ve buraya, -fbayrağı eklemek isteyebilirsiniz (bu "tüm eski deltaları bırak" dır, çünkü şu anda bunun gerçekten iyi adaylar bulduğundan emin olmaya çalışıyorsunuz.


9

Dikkat. git gc --agressiveYedeklemeniz yoksa, uzaktan kumanda ile senkronize edilmeyen depo ile çalıştırmayın .

Bu işlem deltaları sıfırdan yeniden oluşturur ve sorunsuz bir şekilde kesilirse veri kaybına neden olabilir.

8GB'lık bilgisayarım için agresif gc, 10k küçük kaydetme ile 1Gb depoda yetersiz kaldı. OOM katili git sürecini sonlandırdığında - beni neredeyse boş bir depoyla bıraktı, sadece çalışan ağaç ve birkaç delta hayatta kaldı.

Tabii ki, deponun tek kopyası bu değildi, bu yüzden onu yeniden oluşturdum ve uzaktan aldım (getirme bozuk depo üzerinde çalışmadı ve birkaç kez 'deltaları çözme' adımında kilitlendi), ancak deponuz ise hiç uzaktan kumanda olmadan tek geliştiricili yerel depo - önce yedekleyin.


5

Not: git gc --aggressiveGit 2.22'nin (2019 2. Çeyrek) açıkladığı gibi kullanmaya dikkat edin .

Bkz 0044f77 işlemek , daecbf2 işlemek , 7384504 taahhüt , 22d4e3b işlemek , 080a448 taahhüt , 54d56f5 taahhüt , d257e0f işlemek , b6a8d09 taahhüt (2019 7 Nisan) ve fc559fb taahhüt , cf9cd77 işlemek , b11e856 taahhüt tarafından (22 Mar 2019) (Ævar Arnfjord Bjarmason avar) .
( Junio ​​C Hamano ile birleştirildi - gitster- in commit ac70c53 , 25 Nis 2019)

gc dokümanlar: yararlılığını küçümseme --aggressive

Mevcut " gc --aggressive" dokümanlar, kullanıcılara onu düzenli olarak çalıştırmalarını önermekten çok uzaktır.
Bu dokümanları bu seçeneği kullanmak için bir tavsiye olarak alan birçok kullanıcıyla şahsen konuştum ve bu genellikle (çoğunlukla) bir zaman kaybıdır .

Öyleyse, gerçekte ne yaptığını açıklığa kavuşturalım ve kullanıcının kendi sonuçlarını çıkarmasına izin verelim.

Jeff King'in açıklamasının kısa bir versiyonunu başka bir deyişle "Etkiler [...] kalıcıdır" konusuna da açıklık getirelim .

Bu, git-gc belgelerinin artık şunları içerdiği anlamına gelir :

AGRESİF

Ne zaman --aggressivebir seçenek verilir, git-repackile çağrılır -fsırayla geçecek bayrak, --no-reuse-deltaiçin git-pack-nesneler .
Bu, yeniden paketleme için çok daha fazla zaman harcamak pahasına, mevcut deltaları atacak ve yeniden hesaplayacaktır.

Bunun etkileri çoğunlukla kalıcıdır, örneğin paketler ve gevşek nesneler birbiri içinde birleştirildiğinde, bu paketteki mevcut deltalar yeniden kullanılabilir, ancak daha yeni bir delta alabileceğimiz çeşitli durumlar da vardır. bunun yerine paketleyin.

Ayrıca, tedarik --aggressive, iletilen --depthve --windowseçenekleri değiştirecektir git-repack.
Bkz gc.aggressiveDepthve gc.aggressiveWindowayarları aşağıda.
Daha büyük bir pencere boyutu kullanarak, daha uygun deltaları bulmamız daha olasıdır.

Bu seçeneği belirli bir depoda özel performans karşılaştırmaları çalıştırmadan kullanmaya muhtemelen değmez .
Çok daha fazla zaman alır ve ortaya çıkan alan / delta optimizasyonu buna değebilir veya değmeyebilir. Bunu hiç kullanmamak, çoğu kullanıcı ve depoları için doğru bir değiş tokuş.

Ve ( 080a448 işle ):

gcdocs: nasıl --aggressiveetkilere --windowve--depth

Yana 07e7dbf ( gc: 50, varsayılan agresif derinliği, 2016-08-11, Git v2.10.1) biz biraz karışıklığa neden altında aynı derinliğe kullanımı--aggressive varsayılan şekilde olduğu gibi.

Bu işlemde belirtildiği gibi, bu mantıklıdır, "agresif" için daha fazla derinliği varsayılan yapmak ve bu nedenle çalışma zamanı performansı pahasına disk alanından tasarruf etmek yanlıştı, bu genellikle "agresif gc" yi seven birinin tam tersidir. istiyor.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.