Linus zasugerował (zobacz poniżej pełny post na liście mailingowej), używając go git gc --aggressive
tylko wtedy, gdy masz, jego słowami, „ naprawdę zły pakiet” lub „naprawdę strasznie złe delty”, jednak „prawie zawsze, w innych przypadkach jest to naprawdę bardzo złe rzecz do zrobienia." Rezultat może nawet pozostawić repozytorium w gorszym stanie niż na początku!
Polecenie, które sugeruje, aby zrobić to właściwie po zaimportowaniu „długiej i zawiłej historii”, brzmi
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>
W czwartek, 6 grudnia 2007, Daniel Berlin napisał:
Właściwie okazuje się, że git-gc --aggressive
czasami pakuje się pliki, niezależnie od tego, czy dokonałeś konwersji z repozytorium SVN, czy nie.
Absolutnie. git --aggressive
jest przeważnie głupi. Jest to przydatne tylko w przypadku „Wiem, że mam naprawdę kiepski pakiet i chcę odrzucić wszystkie złe decyzje dotyczące pakowania”.
Aby to wyjaśnić, warto wyjaśnić (prawdopodobnie jesteś tego świadomy, ale i tak przejdę przez podstawy), jak działają łańcuchy delta git i jak bardzo różnią się od większości innych systemów.
W innych SCM łańcuch delta jest zwykle naprawiony. Może to być „do przodu” lub „do tyłu” i może ewoluować nieco podczas pracy z repozytorium, ale ogólnie jest to łańcuch zmian w pojedynczym pliku reprezentowanym jako pewnego rodzaju pojedynczy obiekt SCM. W CVS jest to oczywiście *,v
plik, a wiele innych systemów robi raczej podobne rzeczy.
Git również obsługuje łańcuchy delta, ale robi to dużo bardziej „luźno”. Nie ma stałej jednostki. Różnice są generowane dla dowolnej innej losowej wersji, którą git uważa za dobrego kandydata na deltę (z różnymi dość skutecznymi heurystykami) i nie ma absolutnie żadnych twardych reguł grupowania.
Generalnie jest to bardzo dobra rzecz. Jest to dobre z różnych powodów koncepcyjnych ( np. Git wewnętrznie nigdy nie musi nawet przejmować się całym łańcuchem wersji - tak naprawdę nie myśli w kategoriach delt), ale jest również świetny, ponieważ pozbycie się nieelastycznych reguł delta oznacza że git nie ma żadnych problemów ze scalaniem dwóch plików, na przykład - po prostu nie ma żadnych *,v
„plików wersji”, które mają jakieś ukryte znaczenie.
Oznacza to również, że wybór delt jest kwestią znacznie bardziej otwartą. Jeśli ograniczysz łańcuch delta do tylko jednego pliku, naprawdę nie masz dużego wyboru, co zrobić z deltami, ale w git naprawdę może to być zupełnie inny problem.
I tu pojawia się naprawdę źle nazwany --aggressive
. Chociaż git generalnie próbuje ponownie wykorzystać informacje delta (ponieważ jest to dobry pomysł i nie marnuje czasu procesora na ponowne znajdowanie wszystkich dobrych delt, które znaleźliśmy wcześniej), czasami chcesz powiedzieć „zacznijmy wszystko od nowa, z pustą planszą, zignoruj wszystkie poprzednie informacje o różnicach i spróbuj wygenerować nowy zestaw delt”.
Tak --aggressive
naprawdę nie chodzi o bycie agresywnym, ale o marnowanie czasu procesora na ponowne podejmowanie decyzji, którą już podjęliśmy wcześniej!
Czasami to dobrze. W szczególności niektóre narzędzia do importowania mogą generować naprawdę strasznie złe delty. Wszystko, co używagit fast-import
, prawdopodobnie nie ma świetnego układu delta, więc warto powiedzieć: „Chcę zacząć od czystej karty”.
Ale prawie zawsze, w innych przypadkach, jest to naprawdę złe. Spowoduje to stratę czasu procesora, a zwłaszcza jeśli wcześniej wykonałeś dobrą robotę przy deltaowaniu, wynik końcowy nie będzie ponownie wykorzystywał wszystkich dobrych delt, które już znalazłeś, więc tak naprawdę skończysz z dużo gorszy wynik końcowy!
Wyślę łatkę do Junio, aby po prostu usunąć git gc --aggressive
dokumentację. Może być przydatna, ale generalnie jest przydatna tylko wtedy, gdy naprawdę rozumiesz, na bardzo głębokim poziomie, co robi, a ta dokumentacja ci w tym nie pomaga.
Generalnie robienie przyrostowe git gc
jest właściwym podejściem i jest lepsze niż robienie git gc --aggressive
. Będzie ponownie używać starych delt, a kiedy nie można ich znaleźć (powód wykonywania przyrostowych GC w pierwszej kolejności!), Utworzy nowe.
Z drugiej strony, z pewnością prawdą jest, że „początkowy import długiej i zawiłej historii” to moment, w którym warto poświęcić dużo czasu na znalezienie naprawdę dobrych delt. Wtedy każdy użytkownik kiedykolwiek (o ile nie użyje go git gc --aggressive
do cofnięcia!) Otrzyma korzyść z tego jednorazowego zdarzenia. Dlatego szczególnie w przypadku dużych projektów z długą historią, prawdopodobnie warto wykonać dodatkową pracę, nakazując kodowi znajdującemu delta oszaleć.
Tak więc odpowiednikiem git gc --aggressive
- ale wykonanym prawidłowo - jest zrobienie (z dnia na dzień) czegoś takiego
git repack -a -d --depth=250 --window=250
gdzie ta kwestia głębi dotyczy tego, jak głębokie mogą być łańcuchy delta (wydłuż je dla starej historii - jest to warte przestrzeni narzutu), a sprawa okna dotyczy tego, jak duże okno obiektu chcemy przeskanować każdy kandydat na deltę.
I tutaj możesz chcieć dodać -f
flagę (która oznacza „porzucić wszystkie stare delty”, ponieważ teraz faktycznie próbujesz upewnić się, że ta faktycznie znajduje dobrych kandydatów.
A potem zajmie to wieczność i jeden dzień ( czyli „zrób to z dnia na dzień”). Ale końcowy rezultat jest taki, że wszyscy poniżej tego repozytorium otrzymają znacznie lepsze pakiety, bez konieczności poświęcania na to żadnego wysiłku.
Linus