Für mich ist es leicht zu verstehen, wie Git-Commits implementiert werden, aber es ist schwierig zu verstehen, wie andere Commits sehen. Also habe ich anderen auf Mastodon einige Fragen gestellt.
Ich habe eine sehr unwissenschaftliche Umfrage durchgeführt und die Leute gefragt, was sie von Git-Commits halten: Ist es ein Snapshot, ein Diff oder eine Liste aller vorherigen Commits? (Natürlich ist es vernünftig, sich alle drei vorzustellen, aber ich bin neugierig auf die wichtigsten
der LeuteDas Ergebnis ist:
Ich bin überrascht, wie nahe die Verhältnisse der beiden Optionen in Differenz und Schnappschuss liegen. Die Leute haben auch einige interessante, aber widersprüchliche Punkte angesprochen, wie
„Mir scheint, dass ein Commit ein Diff ist, aber ich denke, dass er tatsächlich als Snapshot implementiert ist“ und
„Mir scheint, dass ein Commit ein Snapshot ist, aber ich denke es kommt tatsächlich in Form eines Unterschieds vor.“ Wir werden später mehr darüber sprechen, wie die Einreichung tatsächlich umgesetzt wird.
Bevor wir weitermachen: Was meinen wir mit „einem Unterschied“ oder „einer Momentaufnahme“?
Der „Unterschied“, von dem ich spreche, ist wahrscheinlich ziemlich offensichtlich: Der Unterschied besteht darin, was man bekommt, wenn man läuft git show COMMIT_ID
. Hier ist zum Beispiel eine Tippfehlerkorrektur im rbspy-Projekt:
diff --git a/src/ui/summary.rs b/src/ui/summary.rs index 5c4ff9c..3ce9b3b 100644 --- a/src/ui/summary.rs +++ b/src/ui/summary.rs @@ -160,7 +160,7 @@ mod tests { "; let mut buf: Vec = Vec::new(); -stats.write(&mut buf).expect("Callgrind write failed"); +stats.write(&mut buf).expect("summary write failed"); let actual = String::from_utf8(buf).expect("summary output not utf8"); assert_eq!(actual, expected, "Unexpected summary output"); }
Sie können es auf GitHub sehen: https://github.com/rbspy/rbspy/commit/24ad81d2439f9e63dd91cc1126ca1bb5d3a4da5b
Mit „Schnappschuss“ meine ich „alle Dateien, die Sie erhalten, wenn Sie git checkout COMMIT_ID
ausführen“.
Git bezeichnet die Liste der übermittelten Dateien normalerweise als „Baum“ (z. B. einen „Verzeichnisbaum“), und Sie können alle oben übermittelten Dateien auf GitHub sehen:
https://github.com/rbspy/rbspy/tree/24ad81d2439f9e63dd91cc1126ca1bb5d3a4da5b (es ist /tree/
而不是 /commit/
)
Der Rat, den ich zum Erlernen von Git am häufigsten höre, ist wahrscheinlich: „Lernen Sie einfach, wie Git die Dinge intern darstellt, und alles wird klarer.“ Ich liebe diese Perspektive offensichtlich sehr (wenn Sie einige Zeit damit verbracht haben, diesen Blog zu lesen, wissen Sie, dass ich sie liebe
Aber als Möglichkeit, Git zu lernen, hat es nicht so gut geklappt, wie ich gehofft hatte! Normalerweise würde ich aufgeregt anfangen zu erklären: „Okay, also Git
ein Commit ist ein Snapshot, es hat einen Zeiger auf seinen übergeordneten Commit, dann ist ein Zweig ein Zeiger auf den Commit, dann ...“, aber ich versuche zu helfen Die Leute werden mir sagen, dass sie diese Erklärung nicht wirklich hilfreich fanden und sie immer noch nicht verstehen. Deshalb habe ich mir andere Optionen angesehen.
Aber lassen Sie uns zunächst über die interne Umsetzung sprechen.
Intern stellt Git Commits als Snapshots dar (es speichert einen „Baum“ der aktuellen Version jeder Datei). Ich befinde mich in einem Git-Repository. Wo sind Ihre Dateien? Ich habe darüber in geschrieben, aber hier ist ein sehr kurzer Überblick über das interne Format.
Dies ist eine Einreichungsdarstellung:
$ git cat-file -p 24ad81d2439f9e63dd91cc1126ca1bb5d3a4da5b tree e197a79bef523842c91ee06fa19a51446975ec35 parent 26707359cdf0c2db66eb1216bf7ff00eac782f65 author Adam Jensen1672104452 -0500 committer Adam Jensen1672104890 -0500 Fix typo in expectation message
Und wenn wir uns dieses Baumobjekt ansehen, sehen wir eine Liste aller Dateien/Unterverzeichnisse im Stammverzeichnis des Repositorys in diesem Commit:
$ git cat-file -p e197a79bef523842c91ee06fa19a51446975ec35 040000 tree 2fcc102acd27df8f24ddc3867b6756ac554b33ef.cargo 040000 tree 7714769e97c483edb052ea14e7500735c04713eb.github 100644 blob ebb410eb8266a8d6fbde8a9ffaf5db54a5fc979a.gitignore 100644 blob fa1edfb73ce93054fe32d4eb35a5c4bee68c5bf5ARCHITECTURE.md 100644 blob 9c1883ee31f4fa8b6546a7226754cfc84ada5726CODE_OF_CONDUCT.md 100644 blob 9fac1017cb65883554f821914fac3fb713008a34CONTRIBUTORS.md 100644 blob b009175dbcbc186fb8066344c0e899c3104f43e5Cargo.lock 100644 blob 94b87cd2940697288e4f18530c5933f3110b405bCargo.toml
Das bedeutet, dass das Auschecken eines Git-Commits immer schnell geht: Es ist für Git genauso einfach, den Commit von gestern auszuchecken, wie das Auschecken von Commits von vor einer Million. Git muss nie 10.000 Diffs erneut anwenden, um den aktuellen Status zu ermitteln, da Commits nie als Diffs gespeichert werden.
Ich habe gerade erwähnt, dass ein Git-Commit ein Snapshot ist, aber wenn jemand sagt „Meiner Meinung nach ist ein Commit ein Snapshot, aber ich denke, es ist ein Unterschied in der Implementierung“
, dann stimmt das tatsächlich auch! Git-Commits
werden nicht in der Form von Diffs dargestellt, an die Sie vielleicht gewöhnt sind (sie werden nicht als Diff zum vorherigen Commit auf der Festplatte gespeichert), aber die grundlegende Intuition ist, dass Sie 10.000
ausführen möchten line file 500 Mal zu bearbeiten und dann 500 Dateien zu speichern, ist ineffizient.
Git bietet eine Möglichkeit, Dateien als Diffs zu speichern. Dies wird als „Packdatei“ bezeichnet und Git sammelt Ihre Daten regelmäßig in einer Packdatei, um Speicherplatz zu sparen. Git komprimiert auch Daten, wenn Sie ein Repository erstellen. git clone
ausführen, um den Unterschied eines Commits zu sehen, ist ein wenig kontraintuitiv. Mein Verständnis ist: git show SOME_COMMIT
Trotzdem denke ich, dass Git-Speicher-Commits als Snapshots und Packfile nur ein Implementierungsdetail sind, um Speicherplatz zu sparen und das Klonen zu beschleunigen. Ich musste eigentlich nie wissen, wie Packfile funktioniert, aber es hilft mir zu verstehen, wie Git Snapshots festschreibt, ohne zu viel Speicherplatz zu beanspruchen.
Ich denke, dieses Missverständnis ist manchmal sehr nützlich und scheint für den täglichen Git-Gebrauch kein Problem zu sein. Mir gefällt wirklich, dass es die Dinge, die wir am häufigsten verwenden (Unterschiede), zu den grundlegendsten Elementen macht – es ist für mich sehr intuitiv.
Ich habe auch über einige andere nützliche, aber „falsche“ Verständnisse von Git nachgedacht, wie zum Beispiel:
Ich denke, es gibt eine Reihe „falscher“ Verständnisse von Git, die sehr sinnvoll sind, von der Git-Benutzeroberfläche weitgehend unterstützt werden und in den meisten Fällen keine Probleme verursachen. Es kann jedoch verwirrend werden, wenn Sie eine Änderung rückgängig machen möchten oder etwas schief geht.
Obwohl ich weiß, dass Commits Snapshots in Git sind, behandle ich sie wahrscheinlich die meiste Zeit als Diffs, weil:
git show
verwenden, also ist es einfach etwas, was ich gewohnt bin zu sehen Aber manchmal stelle ich mir Commits auch als Schnappschüsse vor, weil:
git checkout COMMIT_ID
tut (der Gedanke, 10.000 Commits erneut anzuwenden, stresst mich) Einige Antworten von Mastodon erwähnten auch:
Einige andere Wörter, die Leute verwenden, wenn sie über Commits sprechen, die möglicherweise weniger mehrdeutig sind:
Es fällt mir schwer, die unterschiedlichen Vorstellungen der Menschen von Git zu verstehen. Besonders heikel ist, dass, obwohl „falsche“ Verständnisse oft sehr nützlich sind, die Menschen so sehr auf der Hut vor „falschen“ mentalen Modellen sind, dass sie ihre „falschen“ Ideen nur ungern mitteilen, aus Angst, dass irgendein Git-Interpreter aufsteht. Kommen Sie heraus und erklären Sie ihnen, warum sie falsch liegen. (Diese Git
-Interpreter meinen es normalerweise gut, aber es kann trotzdem negative Auswirkungen haben)
Vielen Dank an Marco Rogers, Marie Flanagan und alle bei Mastodon, die mit mir über Git-Commits gesprochen haben.
Das obige ist der detaillierte Inhalt vonSind Git-Commits Unterschiede, Snapshots oder Verlauf?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!