Können Sie trotz der Tatsache, dass GIT keine Dateideltas speichert, immer noch auf frühere Dateiversionen zurücksetzen (unbegrenzt oft?)

14

Ich habe gelesen, dass Git keine Dateideltas speichert. Wenn dies zutrifft, wie unterstützt es das Zurücksetzen von Dateien auf frühere Versionen? Wenn die gesamte Datei gespeichert wird, muss der Repository-Speicherplatz auf der Festplatte unüberschaubar groß werden. Unterstützt Git Dateirollbacks und Diffs zurück zu Dateiversion 1? Unterstützt es überhaupt ein Versionskonzept in Bezug auf Dateien? Dies ist (meiner Meinung nach) wesentlich für mein Verständnis eines VCS / DVCS und meiner Bedürfnisse. Ich muss in der Lage sein, zu vergleichen, was ich einchecken werde, mit früheren Versionen.

Pete Alvin
quelle

Antworten:

44

Git wirft keine Informationen von sich aus weg *. Alle vorherigen Versionen jeder Datei sind immer für Zurücksetzungen, Unterschiede, Überprüfungen usw. verfügbar.

Gesamtbaum versus Einzeldateien

Was Sie möglicherweise versuchen, in Einklang zu bringen, ist die Idee, auf eine alte Version einer einzelnen Datei zuzugreifen, und nicht die Tatsache, dass sich das Verlaufsmodell von Git auf den gesamten Baum konzentriert. Die Vollbaumversionierung erfordert ein wenig mehr Arbeit, um (zum Beispiel) die existierende Version von foo.cvor zehn foo.cÄnderungen im Vergleich zu vor zehn Vollbaumänderungen zu sehen:

# 10 foo.c-changes ago
git show $(git rev-list -n 10 --reverse HEAD -- foo.c | head -1):foo.c

# 10 whole-tree-changes ago
git show HEAD~10:foo.c

Die Vorteile der Baumorientierung, vor allem die Fähigkeit, Commits als eine Einheit von voneinander abhängigen Änderungen anzuzeigen, die an verschiedenen Teilen des gesamten Baums vorgenommen wurden, überwiegen im Allgemeinen bei weitem die zusätzliche Typisierung (die durch Aliase, Skripte usw. verringert werden kann) und die CPU-Zeit verbrachte durch vergangene Commits zu graben.

Speichereffizienz

Wenn ein neues Objekt (z. B. eine Datei mit zuvor nicht sichtbarem Inhalt) in das System eingeht, wird es mit einfacher (zlib) Komprimierung als „loses Objekt“ gespeichert. Wenn sich genügend lose Objekte ansammeln (basierend auf der gc.autoKonfigurationsoption; oder wenn der Benutzer git gc oder einen der Packbefehle einer niedrigeren Ebene ausführt ), sammelt Git viele lose Objekte in einer einzigen "Packdatei".

Objekte in einer Packdatei können entweder als einfache komprimierte Daten (wie lose Objekte, die nur mit anderen Objekten gebündelt sind) oder als komprimierte Deltas für ein anderes Objekt gespeichert werden. Deltas können zu konfigurierbaren Tiefen verkettet werden ( pack.depth) und können für jedes geeignete Objekt erstellt werden ( pack.windowsteuert, wie häufig Git nach der besten Delta-Basis sucht; eine Version einer historisch nicht verwandten Datei kann als Basis verwendet werden, wenn dies zu a führen würde) gute Delta-Komprimierung). Der Spielraum, den die Tiefen- und Fenstergrößenkonfigurationen der Delta-Komprimierungs-Engine bieten, führt häufig zu einer besseren Delta-Komprimierung als die einfache Diff-Komprimierung im CVS-Stil (eine Version gegen die nächste / vorherige Version).

Diese aggressive Delta-Komprimierung (kombiniert mit normaler Zlib-Komprimierung) kann dazu führen, dass ein Git-Repository (mit vollem Verlauf und einem nicht komprimierten Arbeitsbaum) weniger Speicherplatz beansprucht als eine einzelne SVN-Prüfung (mit nicht komprimiertem Arbeitsbaum und unberührter Kopie).

Weitere Informationen finden Sie in den Abschnitten Speichern von Objekten und Packdateien in The Git Community Book . Auch die Manpage git pack-objects .

* Sie können Git anweisen, Commits wegzuwerfen, indem Sie den Verlauf neu schreiben und Befehle wie " git reset " ausführen . Aber auch in diesen Fällen "hängt" Git eine Weile an den neu verworfenen Commits, nur für den Fall, dass Sie sie benötigen. Siehe git reflog und git prune .

Chris Johnsen
quelle
3
+1 nur für die Menge und Details der von Ihnen bereitgestellten Informationen.
Tamara Wijsman
3
Da Git Snapshots von Dateien anstelle von Deltas verwendet, ist es auch einfacher, einen langen Weg in der Geschichte zurückzulegen. Stellen Sie sich vor, Sie möchten eine Datei von vor 20 Commits sehen. Bei Deltas müssen Sie 20 Änderungssätze rückgängig machen. Mit Schnappschüssen nehmen Sie einfach den richtigen Schnappschuss. Je länger Ihre Geschichte ist, desto größer ist der Vorteil. Und wenn Sie den Unterschied zwischen der aktuellen Version und dieser sehen möchten, ist es nur ein einzelner Unterschied, anstatt zu entscheiden, was getan, rückgängig gemacht, wiederholt usw. wurde
Nathan Long
Chris, du scheinst ziemlich gut mit Git-Interna zurechtzukommen. Gibt es eine Chance, dass Sie sich daran beteiligen? stackoverflow.com/questions/5176225/…
Nathan Long
@ ChrisJohnsen Bitte hilf mir das zu verstehen. Kann Git basierend auf Ihren Aussagen eine ähnliche (oder bessere) Speichereffizienz erzielen als Subversion? Ich weiß, dass bei mehrmaligem Festschreiben einer Datei mit geringen Änderungen Daten im Wert von 1 GB in 100 MB gespeichert werden können. Kann Git dasselbe tun?
Alireza Noori
@AlirezaNoori: Alles hängt von der Art der Daten und den erfassten Änderungen ab (Größe der Datei, Komprimierbarkeit der Datei, Größe und Speicherort der Änderungen usw.). So etwas sollte auf jeden Fall möglich sein (abhängig von den Besonderheiten). Im Allgemeinen können die Packdateien von Git aus einer größeren Auswahl von Grundlagen für die Delta-Komprimierung stammen als die streng umgekehrt chronologischen Deltas, die SVN-Server verwenden (verwendet? Ich verfolge die SVN-Entwicklung nicht ...). Wenn Sie eine bestimmte Frage haben, sollten Sie überlegen, eine neue Frage zu stellen, die alle relevanten Details enthält.
Chris Johnsen
1

Es kann auf derselben Seite gelesen werden:

...

Folglich zeichnet Git Dateirevisionsbeziehungen auf keiner Ebene unterhalb der Quellcodebaumstruktur explizit auf.

...

Die Überprüfung des Änderungsverlaufs einer einzelnen Datei ist etwas teurer als das gesamte Projekt. Um einen Verlauf von Änderungen zu erhalten, die sich auf eine bestimmte Datei auswirken, muss Git den globalen Verlauf durchgehen und dann feststellen, ob jede Änderung diese Datei geändert hat. Mit dieser Methode zur Überprüfung des Verlaufs kann Git jedoch mit gleicher Effizienz einen einzelnen Verlauf erstellen, der die Änderungen an einem beliebigen Satz von Dateien zeigt. Beispielsweise ist ein Unterverzeichnis des Quellbaums plus einer zugehörigen globalen Header-Datei ein sehr häufiger Fall.

...

Auf diese Weise können Sie zu früheren Versionen einer Datei zurückkehren und zwei Dateien vergleichen.

Tamara Wijsman
quelle
1

git speichert tatsächlich Deltas von Dateien, aber es speichert sie als Delta des gesamten Dateibaums.

Führen Sie einen der folgenden Schritte aus, um die Unterschiede zwischen den Versionen festzustellen:

  1. git diff - Zeigt die Unterschiede zwischen der zuletzt eingecheckten Version und den Dateien an, die geändert wurden, aber noch nicht hattengit add ausgeführt wurden.
  2. Git Diff - zwischengespeichert - zwischengespeichert - zeigt die Unterschiede zwischen der vorherigen Version und allen Dateien, die git addausgeführt, aber noch nicht festgeschrieben wurden
  3. Git Diff Commit - die Unterschiede zwischen dem aktuellen Arbeitsverzeichnis und einem vorherigen Commit an, wie im Commit angegeben
  4. git diff commita..commitb - zeigt die Unterschiede zwischen zwei Commits, a und b. Die Commits können auch symbolische Namen wie Zweige oder Tags sein.
Kantenschneider
quelle
Diese Antwort ist nicht wirklich richtig. Alle diese Befehle können auf einen beliebigen Satz von Dateien sowie auf den gesamten Baum angewendet werden - fügen Sie einfach die Dateinamen am Ende hinzu ...
naught101