Um die Antwort von Ben Jackson zu erweitern , die in Ordnung ist, schauen wir uns die ursprüngliche Frage genau an. (In seiner Antwort erfahren Sie, warum Sie Fragen stellen müssen. Hier geht es mehr darum, was los ist .)
Ich bin neu in der Versionskontrolle und verstehe, dass beim "Festschreiben" im Wesentlichen ein Backup erstellt wird, während die neue "aktuelle" Version Ihrer Arbeit aktualisiert wird.
Das ist nicht ganz richtig. Backups und Versionskontrolle hängen sicherlich zusammen - genau wie stark sie von einigen Dingen abhängen, die in gewissem Maße Meinungsfragen sind -, aber es gibt sicherlich einige Unterschiede, wenn auch nur in der Absicht: Backups sind normalerweise für die Notfallwiederherstellung konzipiert (Computer fällt aus, Feuer zerstört gesamtes Gebäude einschließlich aller Speichermedien usw.). Die Versionskontrolle ist in der Regel für feinkörnigere Interaktionen konzipiert und bietet Funktionen, die Backups nicht bieten. Backups werden normalerweise einige Zeit gespeichert und dann als "zu alt" abgeworfen: Ein frischeres Backup ist alles, was zählt. Die Versionskontrolle speichert normalerweise jede festgeschriebene Version für immer.
Was ich nicht verstehe, ist, wofür Inszenierung aus praktischer Sicht ist. Ist die Inszenierung etwas, das nur im Namen existiert, oder erfüllt es einen Zweck? Wenn Sie sich verpflichten, wird es sowieso alles festlegen, oder?
Ja und nein. Gits Design hier ist etwas eigenartig. Es gibt Versionskontrollsysteme, für die kein separater Staging-Schritt erforderlich ist. Zum Beispiel erfordert Mercurial, das in Bezug auf die Verwendung Git sehr ähnlich ist, keinen separaten hg addSchritt, der über den allerersten hinausgeht, in dem eine brandneue Datei eingeführt wird. Bei Mercurial verwenden Sie den hgBefehl, der ein Commit auswählt. Dann erledigen Sie Ihre Arbeit, führen es aus hg commitund sind fertig. Mit Git verwenden Sie git checkout, 1 dann tun Sie Ihre Arbeit, dann laufen Sie git addund dann git commit. Warum der zusätzliche git addSchritt?
Das Geheimnis hier ist das, was Git auf verschiedene Weise den Index oder den Staging-Bereich oder manchmal - heutzutage selten - den Cache nennt . Dies sind alles Namen für dasselbe.
Bearbeiten: Ich denke, ich kann die Terminologie verwirren. Ist eine "inszenierte" Datei dasselbe wie eine "verfolgte" Datei?
Nein, aber diese sind verwandt. Eine verfolgte Datei ist eine, die im Git-Index vorhanden ist. Um den Index richtig zu verstehen, sollten Sie zunächst die Commits verstehen.
Seit Git Version 2.23 können Sie git switchanstelle von verwenden git checkout. In diesem speziellen Fall machen diese beiden Befehle genau dasselbe. Der neue Befehl existiert, weil git checkouter mit zu vielen Dingen überfüllt war. sie wurde in zwei getrennte Befehle aufzuschlüsseln, git switchund git restorees einfacher und sicherer zu bedienen Git zu machen.
Commits
In Git speichert ein Commit einen vollständigen Snapshot jeder Datei, die Git kennt. (Welche Dateien kennt Git? Wir werden das im nächsten Abschnitt sehen.) Diese Schnappschüsse werden in einer speziellen, schreibgeschützten, schreibgeschützten, komprimierten und duplizierten Form gespeichert, die im Allgemeinen nur Git selbst lesen kann . (In jedem Commit steckt mehr Material als nur dieser Schnappschuss, aber das ist alles, was wir hier behandeln werden.)
Die Deduplizierung hilft beim Speicherplatz: Normalerweise ändern wir nur einige Dateien und führen dann ein neues Commit durch. Daher sind die meisten Dateien in einem Commit meistens dieselben wie die Dateien im vorherigen Commit. Durch die direkte Wiederverwendung dieser Dateien spart Git viel Platz: Wenn wir nur eine Datei berührt haben, nimmt das neue Commit nur Platz für eine neue Kopie. Selbst dann ist es komprimiert - manchmal sehr komprimiert, obwohl dies tatsächlich später geschieht -, sodass ein .gitVerzeichnis tatsächlich kleiner sein kann als die darin enthaltenen Dateien, sobald sie zu normalen Alltagsdateien erweitert wurden. Die Deduplizierung ist sicher, da die festgeschriebenen Dateien für alle Zeiten eingefroren sind. Niemand kann einen ändern, daher ist es sicher, dass Commits von den Kopien des jeweils anderen abhängen.
Da die gespeicherten Dateien in diesem speziellen sind, frozen-for-all-time, Git-nur - Format, obwohl, hat Git zu erweitern heraus jede Datei in eine gewöhnliche Alltag Kopie. Diese gewöhnliche Kopie ist nicht Gits Kopie: Es ist Ihre Kopie, damit zu tun, wie Sie wollen. Git schreibt nur dann an diese, wenn Sie es dazu auffordern, damit Sie mit Ihren Kopien arbeiten können. Diese verwendbaren Kopien befinden sich in Ihrem Arbeitsbaum oder Arbeitsbaum .
Dies bedeutet, dass beim Auschecken eines bestimmten Commits automatisch zwei Kopien jeder Datei vorhanden sind:
Git hat eine für alle Zeiten eingefrorene, Git-ified-Kopie im aktuellen Commit . Sie können diese Kopie nicht ändern (obwohl Sie natürlich ein anderes Commit auswählen oder ein neues Commit durchführen können).
Sie haben in Ihrem Arbeitsbaum eine Kopie im Normalformat. Sie können alles Mögliche tun, indem Sie einen der Befehle auf Ihrem Computer verwenden.
Andere Versionskontrollsysteme (einschließlich Mercurial wie oben erwähnt) hören hier mit diesen beiden Kopien auf. Sie ändern einfach Ihre Arbeitsbaumkopie und schreiben sie fest. Git ... nicht.
Der Index
Zwischen diesen beiden Kopien speichert Git eine dritte Kopie 2 jeder Datei. Diese dritte Kopie hat das eingefrorene Format , aber im Gegensatz zur eingefrorenen Kopie im Commit können Sie sie ändern. Um es zu ändern, verwenden Sie git add.
Der git addBefehl bedeutet, dass die Indexkopie der Datei mit der Arbeitsbaumkopie übereinstimmt . Das heißt, Sie sagen Git: Ersetzen Sie die im Index enthaltene, nicht duplizierte Kopie im eingefrorenen Format, indem Sie meine aktualisierte Arbeitsbaumkopie komprimieren, sie duplizieren und sie für das Einfrieren in ein neues Commit vorbereiten. Wenn Sie nicht verwenden git add, enthält der Index weiterhin die Kopie im eingefrorenen Format aus dem aktuellen Commit.
Wenn Sie ausführen git commit, packt Git alles, was sich im Index befindet, richtig zusammen , um es als neuen Snapshot zu verwenden. Da Git bereits im eingefrorenen Format vorliegt und vorab dupliziert wurde, muss Git nicht viel zusätzliche Arbeit leisten.
Dies erklärt auch, worum es bei nicht verfolgten Dateien geht. Eine untracked - Datei ist eine Datei , die in Ihrer Arbeit Baum ist aber nicht in Git-Index jetzt . Es spielt keine Rolle, wie die Datei in diesem Zustand endete. Vielleicht haben Sie es von einem anderen Ort auf Ihrem Computer in Ihren Arbeitsbaum kopiert. Vielleicht hast du es hier frisch gemacht. Vielleicht gab es eine Kopie in Gits Index, aber Sie haben diese Kopie mit entfernt git rm --cached. Auf die eine oder andere Weise gibt es hier in Ihrem Arbeitsbaum eine Kopie, aber keine Kopie in Gits Index. Wenn Sie jetzt ein neues Commit durchführen, befindet sich diese Datei nicht im neuen Commit.
Beachten Sie, dass git checkoutzunächst in füllt Git-Index aus der Sie verpflichten überprüfen. Der Index beginnt also mit dem Commit. Git füllt auch Ihren Arbeitsbaum aus derselben Quelle aus. Zunächst stimmen also alle drei überein. Wenn Sie Dateien in Ihrem Arbeitsbaum und in git adddiesen ändern , stimmen nun der Index und Ihr Arbeitsbaum überein. Dann laufen Sie git commitund Git macht ein neues Commit aus dem Index, und jetzt stimmen alle drei wieder überein.
Da Git neue Commits aus dem Index erstellt, können wir die Dinge so formulieren: Der Git-Index enthält das nächste Commit, das Sie planen. Dies ignoriert die erweiterte Rolle, die Gits Index während einer Konfliktzusammenführung übernimmt, aber wir möchten dies vorerst trotzdem ignorieren. :-)
Das ist alles - aber es ist immer noch ziemlich kompliziert! Es ist besonders schwierig, weil es keine einfache Möglichkeit gibt, genau zu sehen, was in Gits Index enthalten ist. 3 Aber es gibt einen Git-Befehl, der Ihnen auf eine ziemlich nützliche Weise sagt, was los ist, und dieser Befehl ist es git status.
2 Technisch gesehen ist dies überhaupt keine Kopie . Stattdessen ist es ein Verweis auf die Git-ified-Datei, vordupliziert und alles. Hier gibt es noch mehr Dinge, wie den Modus, den Dateinamen, eine Staging-Nummer und einige Cache-Daten, damit Git schnell geht. Aber wenn Sie nicht mit einigen der einfachen Befehle von Git arbeiten - git ls-files --stageund git update-indexinsbesondere -, können Sie sich das einfach als Kopie vorstellen.
3 Der git ls-files --stageBefehl zeigt Ihnen die Namen und Staging-Nummern jeder Datei im Git-Index an, aber normalerweise ist dies sowieso nicht sehr nützlich.
git status
Der git statusBefehl funktioniert tatsächlich, indem zwei separate git diffBefehle für Sie ausgeführt werden (und auch einige andere nützliche Dinge ausgeführt werden, z. B. die Angabe, in welchem Zweig Sie sich befinden).
Der erste git diffvergleicht das aktuelle Commit - das für alle Zeiten eingefroren ist - mit dem, was in Gits Index enthalten ist. Für Dateien, die gleich sind , sagt Git überhaupt nichts. Bei Dateien , die sind anders , wird Git Ihnen sagen , dass diese Datei für begehen inszeniert . Dazu gehören alle neuen Dateien-wenn der Commit muss nicht sub.pydrin, aber der Index nicht haben sub.pydarin, so wird diese Datei hinzugefügt-und alle gelöschten Dateien, die waren (und sind) in der begehen , sind aber nicht in der Index nicht mehr ( git rmvielleicht).
Der zweite git diffvergleicht alle Dateien im Git-Index mit den Dateien in Ihrem Arbeitsbaum. Für Dateien, die gleich sind , sagt Git überhaupt nichts. Bei Dateien , die sind anders , wird Git Ihnen sagen , dass diese Datei nicht begehen inszeniert . Im Gegensatz zum ersten Diff enthält diese Liste keine brandneuen Dateien: Wenn die Datei untrackedin Ihrem Arbeitsbaum vorhanden ist, jedoch nicht im Git-Index, fügt Git sie nur der Liste der nicht verfolgten Dateien hinzu . 4
Am Ende, nachdem diese untracked Dateien in einer Liste angesammelt hat , git statusbekannt geben , diejenigen zu Dateien Namen, aber es gibt eine spezielle Ausnahme: wenn die Name eine Datei in einer aufgeführte .gitignoreDatei, die dieses letzte Angebot unterdrückt. Beachten Sie, dass das Auflisten einer verfolgten Datei - eine, die im Git-Index enthalten ist - in a .gitignorekeine Auswirkung hat : Die Datei befindet sich im Index, wird also verglichen und festgeschrieben, selbst wenn sie in aufgeführt ist .gitignore. Die Ignorierdatei unterdrückt nur die Beschwerden über "nicht verfolgte Datei". 5
4 Wenn Sie die Kurzversion von git status- git status -sverwenden, sind die nicht verfolgten Dateien nicht so getrennt, aber das Prinzip ist dasselbe. Wenn Sie die Dateien auf diese Weise akkumulieren, können Sie auch git statuseine Reihe von nicht verfolgten Dateinamen zusammenfassen, indem Sie manchmal nur einen Verzeichnisnamen drucken. Verwenden Sie git status -ualloder, um die vollständige Liste zu erhalten git status -u.
5 Durch das Auflisten einer Datei können auch viele Dateivorgänge wie die nicht verfolgte Datei massenweise hinzugefügtgit add . oder git add *übersprungen werden. Dieser Teil wird etwas komplizierter, da Sie damit git add --forceeine Datei hinzufügen können, die normalerweise übersprungen wird. Es gibt einige andere normalerweise geringfügige Sonderfälle, die sich alle dazu summieren: Die Datei wird .gitignoremöglicherweise besser aufgerufen .git-do-not-complain-about-these-untracked-files-and-do-not-auto-add-themoder ist ebenfalls unhandlich. Aber das ist zu lächerlich, so ist .gitignorees.
git add -u, git commit -aUsw.
Hier gibt es einige nützliche Verknüpfungen:
git add .fügt alle aktualisierten Dateien im aktuellen Verzeichnis und in jedem Unterverzeichnis hinzu. Dies .gitignoregilt. Wenn also eine Datei, die derzeit nicht verfolgt wird, nicht beanstandet wird git status, wird sie nicht automatisch hinzugefügt.
git add -ufügt automatisch alle aktualisierten Dateien an einer beliebigen Stelle in Ihrem Arbeitsbaum hinzu . 6 Dies betrifft nur nachverfolgte Dateien. Beachten Sie, dass beim Entfernen der Arbeitsbaumkopie auch die Indexkopie entfernt wird (dies git addführt dazu, dass der Index mit dem Arbeitsbaum übereinstimmt ).
git add -Aist wie das Laufen git add .von der obersten Ebene Ihres Arbeitsbaums (siehe jedoch Fußnote 6).
Neben diesen können Sie laufen git commit -a, was entspricht in etwa 7 zu laufen git add -uund dann git commit. Das heißt, Sie erhalten das gleiche Verhalten, das in Mercurial praktisch ist.
Ich rate generell von dem git commit -aMuster ab: Ich finde, dass es besser ist, es git statushäufig zu verwenden , die Ausgabe genau zu betrachten und herauszufinden, warum dies der Fall ist, wenn der Status nicht Ihren Erwartungen entspricht. Mit git commit -aist es zu einfach, versehentlich eine Datei zu ändern und eine Änderung festzuschreiben, die Sie nicht festschreiben wollten. Dies ist jedoch meistens eine Frage des Geschmacks / der Meinung.
6 Wenn Ihre Git-Version älter als Git 2.0 ist, seien Sie hier vorsichtig: Funktioniert git add -unur im aktuellen Verzeichnis und in den Unterverzeichnissen. Sie müssen also zuerst auf die oberste Ebene Ihres Arbeitsbaums klettern. Die git add -AOption hat ein ähnliches Problem.
7 Ich sage ungefähr gleichwertig, weil git commit -atatsächlich ein zusätzlicher Index erstellt und dieser andere Index für das Commit verwendet wird. Wenn das Festschreiben funktioniert , erhalten Sie den gleichen Effekt wie beim Ausführen git add -u && git commit. Wenn das Commit nicht funktioniert - wenn Sie Git dazu bringen, das Commit auf eine der vielen Arten zu überspringen, die Sie tun können -, werden danach keine Dateien mehr gespeichert git add, da Git den temporären zusätzlichen Index löscht und wieder den Hauptindex verwendet .
Es gibt zusätzliche Komplikationen, die auftreten, wenn Sie git commit --onlyhier verwenden. In diesem Fall erstellt Git einen dritten Index, und die Dinge werden sehr schwierig, insbesondere wenn Sie Pre-Commit-Hooks verwenden. Dies ist ein weiterer Grund, separate git addOperationen zu verwenden.