Linus schlug vor (siehe unten für den vollständigen Beitrag auf der Mailingliste), git gc --aggressive
nur dann zu verwenden, wenn Sie in seinen Worten "eine wirklich schlechte Packung" oder "wirklich schrecklich schlechte Deltas" haben, aber "fast immer, in anderen Fällen ist es tatsächlich eine wirklich schlechte." etwas zu tun." Das Ergebnis kann sogar dazu führen, dass sich Ihr Repository in einem schlechteren Zustand befindet als zu Beginn!
Der Befehl, den er vorschlägt, um dies richtig zu tun, nachdem er „eine lange und involvierte Geschichte“ importiert hat, lautet
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: <[email protected]>
Message-ID: <[email protected]>
References: <[email protected]>
<[email protected]>
<[email protected]>
<[email protected]>
<[email protected]>
Am 6. Dezember 2007 schrieb Daniel Berlin:
Tatsächlich stellt sich heraus, dass git-gc --aggressive
dies manchmal dumm ist, Dateien zu packen, unabhängig davon, ob Sie von einem SVN-Repo konvertiert haben oder nicht.
Absolut. git --aggressive
ist meistens dumm. Es ist wirklich nur für den Fall nützlich: "Ich weiß, dass ich eine wirklich schlechte Packung habe, und ich möchte alle schlechten Packungsentscheidungen, die ich getroffen habe, wegwerfen."
Um dies zu erklären, lohnt es sich zu erklären (Sie sind sich wahrscheinlich dessen bewusst, aber lassen Sie mich trotzdem die Grundlagen durchgehen), wie Git-Delta-Ketten funktionieren und wie sie sich von den meisten anderen Systemen unterscheiden.
In anderen SCMs ist im Allgemeinen eine Delta-Kette festgelegt. Es kann "vorwärts" oder "rückwärts" sein und sich während der Arbeit mit dem Repository etwas weiterentwickeln, aber im Allgemeinen handelt es sich um eine Kette von Änderungen an einer einzelnen Datei, die als eine Art einzelne SCM-Entität dargestellt wird. In CVS ist es offensichtlich die *,v
Datei, und viele andere Systeme tun ziemlich ähnliche Dinge.
Git macht auch Delta-Ketten, aber es macht sie viel "lockerer". Es gibt keine feste Einheit. Deltas werden gegen jede andere zufällige Version generiert, die git als guten Delta-Kandidaten erachtet (mit verschiedenen ziemlich erfolgreichen Heuristiken), und es gibt absolut keine harten Gruppierungsregeln.
Dies ist im Allgemeinen eine sehr gute Sache. Es ist aus verschiedenen konzeptionellen Gründen gut ( dh Git muss sich intern nie wirklich um die gesamte Revisionskette kümmern - es denkt überhaupt nicht wirklich in Deltas), aber es ist auch großartig, weil es bedeutet, die unflexiblen Delta-Regeln loszuwerden Dieser Git hat zum Beispiel überhaupt keine Probleme beim Zusammenführen von zwei Dateien - es gibt einfach keine willkürlichen *,v
„Revisionsdateien“, die eine versteckte Bedeutung haben.
Dies bedeutet auch, dass die Wahl der Deltas eine viel offenere Frage ist. Wenn Sie die Delta-Kette auf nur eine Datei beschränken, haben Sie wirklich nicht viele Möglichkeiten, was Sie mit Deltas tun sollen, aber in Git kann es wirklich ein ganz anderes Problem sein.
Und hier kommt der wirklich schlecht benannte ins --aggressive
Spiel. Während Git im Allgemeinen versucht, Delta-Informationen wiederzuverwenden (weil es eine gute Idee ist und keine CPU-Zeit damit verschwendet, alle guten Deltas wiederzufinden, die wir zuvor gefunden haben), manchmal Sie Ich möchte sagen: "Beginnen wir von vorne mit einer leeren Tafel und ignorieren alle vorherigen Delta-Informationen und versuchen, einen neuen Satz von Deltas zu generieren."
Es geht also --aggressive
nicht wirklich darum, aggressiv zu sein, sondern darum, CPU-Zeit zu verschwenden, um eine Entscheidung zu wiederholen, die wir bereits zuvor getroffen haben!
Manchmal ist das eine gute Sache. Insbesondere einige Importwerkzeuge könnten wirklich schrecklich schlechte Deltas erzeugen. Alles git fast-import
, was zum Beispiel verwendet wird, hat wahrscheinlich nicht viel von einem großartigen Delta-Layout, daher könnte es sich lohnen zu sagen: "Ich möchte von einer sauberen Tafel ausgehen."
Aber in anderen Fällen ist es fast immer eine wirklich schlechte Sache. Es wird CPU-Zeit verschwenden, und besonders wenn Sie beim Deltaing früher gute Arbeit geleistet haben, wird das Endergebnis nicht alle guten Deltas wiederverwenden, die Sie bereits gefunden haben, sodass Sie am Ende tatsächlich viel haben schlechteres Endergebnis auch!
Ich werde einen Patch an Junio senden, um nur die git gc --aggressive
Dokumentation zu entfernen . Es kann nützlich sein, aber es ist im Allgemeinen nur dann nützlich, wenn Sie auf einer sehr tiefen Ebene wirklich verstehen, was es tut, und diese Dokumentation Ihnen dabei nicht hilft.
Inkrementell git gc
ist im Allgemeinen der richtige Ansatz und besser als inkrementell git gc --aggressive
. Alte Deltas werden wiederverwendet, und wenn diese alten Deltas nicht gefunden werden können (der Grund für die erstmalige inkrementelle GC!), Werden neue erstellt.
Auf der anderen Seite ist es definitiv wahr, dass ein „anfänglicher Import einer langen und involvierten Geschichte“ ein Punkt ist, an dem es sich lohnen kann, viel Zeit damit zu verbringen, die wirklich guten Deltas zu finden. Dann git gc --aggressive
erhält jeder Benutzer (solange er es nicht zum Rückgängigmachen verwendet!) Den Vorteil dieses einmaligen Ereignisses. Insbesondere für große Projekte mit einer langen Geschichte lohnt es sich wahrscheinlich, zusätzliche Arbeit zu leisten und dem Delta-Finding-Code zu sagen, dass er wild werden soll.
Das Äquivalent von git gc --aggressive
- aber richtig gemacht - ist also, (über Nacht) so etwas zu tun
git repack -a -d --depth=250 --window=250
Bei dieser Tiefe geht es nur darum, wie tief die Delta-Ketten sein können (verlängern Sie sie für die alte Geschichte - es lohnt sich der Platzaufwand), und bei der Fenstersache geht es darum, wie groß ein Objektfenster ist, das jeder Delta-Kandidat scannen soll.
Und hier möchten Sie vielleicht die -f
Flagge hinzufügen (dies ist das "alle alten Deltas fallen lassen", da Sie jetzt tatsächlich versuchen, sicherzustellen, dass diese tatsächlich gute Kandidaten findet.
Und dann wird es ewig und einen Tag dauern ( dh eine Sache, die man über Nacht macht). Das Endergebnis ist jedoch, dass jeder, der diesem Repository nachgeschaltet ist, viel bessere Pakete erhält, ohne sich selbst darum kümmern zu müssen.
Linus
Wie ich in " Git Garbage Collection scheint nicht vollständig zu funktionieren " erwähnt habe,
git gc --aggressive
ist a für sich allein weder ausreichend noch ausreichend.Und, wie ich weiter unten erläutere , oft nicht benötigt.
Die effektivste Kombination wäre das Hinzufügen
git repack
, aber auchgit prune
:Hinweis: Git 2.11 (Q4 2016) setzt die Standardtiefe
gc aggressive
auf 50Siehe Commit 07e7dbf (11. August 2016) von Jeff King (
peff
) .(Zusammengeführt von Junio C Hamano -
gitster
- in Commit 0952ca8 , 21. September 2016)(Siehe Commit für Studie )
Apropos CPU-Einsparung: "
git repack
" hat gelernt, die--threads=<n>
Option zu akzeptieren und an Packobjekte zu übergeben.Siehe Commit 40bcf31 (26. April 2017) von Junio C Hamano (
gitster
) .(Zusammengeführt von Junio C Hamano -
gitster
- in Commit 31fb6f4 , 29. Mai 2017)Wir tun dies bereits für
--window=<n>
und--depth=<n>
; Dies ist hilfreich, wenn der Benutzer--threads=1
reproduzierbare Tests erzwingen möchte, ohne von mehreren Threads betroffen zu sein.quelle
git gc --aggressive
dies zweimal behoben wurde: Erstens, um das zu tun, was Linus 2007 als "bessere Verpackungsmethode" vorgeschlagen hat. Und dann in Git 2.11, um die von Linus vorgeschlagene übermäßige Objekttiefe zu vermeiden, die sich jedoch als schädlich herausstellte (verlangsamt alle zukünftigen Git-Operationen und spart keinen nennenswerten Platz).man git-repack
sagt für-d
: `Führen Sie auch git prune-packed aus, um redundante lose Objektdateien zu entfernen .` Oder macht dasgit prune
auch?man git-prune
sagtIn most cases, users should run git gc, which calls git prune.
, was nützt es danachgit gc
? Wäre es nicht besser oder ausreichend, nur zu verwendengit repack -Ad && git gc
?Das Problem dabei
git gc --aggressive
ist, dass der Optionsname und die Dokumentation irreführend sind.Wie Linus selbst in dieser Mail erklärt ,
git gc --aggressive
ist dies im Wesentlichen Folgendes:Normalerweise besteht keine Notwendigkeit, Deltas in Git neu zu berechnen, da Git diese Deltas als sehr flexibel bestimmt. Es macht nur Sinn, wenn Sie wissen, dass Sie wirklich, wirklich schlechte Deltas haben. Wie Linus erklärt, fallen hauptsächlich Werkzeuge, die davon Gebrauch machen,
git fast-import
in diese Kategorie.Meistens leistet git ziemlich gute Arbeit bei der Ermittlung nützlicher Deltas. Wenn Sie diese verwenden
git gc --aggressive
, erhalten Sie Deltas, die möglicherweise noch schlimmer sind, während Sie viel CPU-Zeit verschwenden.Linus beendet seine Mail mit der Schlussfolgerung, dass
git repack
mit einem großen--depth
und--window
in den meisten Fällen die bessere Wahl ist; vor allem nachdem du ein großes projekt importiert hast und sicherstellen willst, dass git gute deltas findet.quelle
Vorsicht. Führen Sie es nicht
git gc --agressive
mit einem Repository aus, das nicht mit Remote synchronisiert ist, wenn Sie keine Backups haben.Dieser Vorgang erstellt Deltas von Grund auf neu und kann bei ordnungsgemäßer Unterbrechung zu Datenverlust führen.
Für meinen 8-GB-Computer ging dem aggressiven GC der Speicher im 1-GB-Repository mit 10.000 kleinen Commits aus. Als der OOM-Killer den Git-Prozess beendete, blieb mir ein fast leeres Repository übrig, nur ein funktionierender Baum und wenige Deltas überlebten.
Natürlich war es nicht die einzige Kopie des Repositorys, also habe ich es einfach neu erstellt und von der Fernbedienung abgerufen (Fetch funktionierte nicht bei defektem Repo und war einige Male beim Schritt "Deltas auflösen" festgefahren), aber wenn Ihr Repo es ist lokales Repo für einzelne Entwickler ohne Fernbedienungen - sichern Sie es zuerst.
quelle
Hinweis: Achten Sie auf die Verwendung
git gc --aggressive
, wie in Git 2.22 (Q2 2019) erläutert.Sehen Sie verpflichten 0044f77 , begehen daecbf2 , begehen 7.384.504 , begehen 22d4e3b , begehen 080a448 , begehen 54d56f5 , begehen d257e0f , begehen b6a8d09 (7. April 2019) und begehen fc559fb , begehen cf9cd77 , begehen b11e856 (22. März 2019) von Ævar Arnfjord Bjarmason (
avar
) .(Zusammengeführt von Junio C Hamano -
gitster
- in Commit ac70c53 , 25. April 2019)Das bedeutet, dass die git-gc-Dokumentation jetzt Folgendes enthält :
Und ( Commit 080a448 ):
quelle