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.
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?
Bearbeiten: Ich denke, ich kann die Terminologie verwirren. Ist eine "inszenierte" Datei dasselbe wie eine "verfolgte" Datei?
Antworten:
Wenn Sie ein Commit durchführen, werden nur die Änderungen im Index (die "bereitgestellten" Dateien) festgeschrieben. Es gibt viele Verwendungsmöglichkeiten dafür, aber das offensichtlichste ist, Ihre Arbeitsänderungen in kleinere, in sich geschlossene Teile aufzuteilen. Möglicherweise haben Sie einen Fehler behoben, während Sie eine Funktion implementiert haben. Sie können
git add
nur diese Datei (odergit add -p
nur einen Teil einer Datei hinzufügen!) Und dann diesen Bugfix festschreiben, bevor Sie alles andere festschreiben. Wenn Sie verwenden,git commit -a
erzwingen Sie nur einesadd
von allem direkt vor dem Festschreiben. Nicht verwenden,-a
wenn Sie Staging-Dateien nutzen möchten.Sie können die bereitgestellten Dateien auch als Zwischenarbeitskopie mit den
--cached
zu vielen Befehlen behandeln.git diff --cached
Zeigen Sie beispielsweise, wie sich die Phase von der Phase unterscheidet,HEAD
damit Sie sehen können, was Sie festlegen möchten, ohne Ihre anderen Arbeitsänderungen zu berücksichtigen.quelle
git reset --hard
.git diff --staged
überprüfen , welche Dateien Sie wo geändert haben, und nehmen Sie weitere Änderungen vor.quelle
Ein praktischer Zweck des Staging ist die logische Trennung von Datei-Commits.
Da Sie durch Staging weiterhin Änderungen am Dateiverzeichnis / Arbeitsverzeichnis vornehmen und Teile festschreiben können, wenn Sie der Meinung sind, dass die Dinge fertig sind, können Sie separate Stufen für logisch nicht zusammenhängende Änderungen verwenden.
Angenommen , Sie 4 Dateien haben
fileA.html
,fileB.html
,fileC.html
undfileD.html
. Sie nehmen Änderungen an allen 4 Dateien vor und sind bereit zum Festschreiben, aber Änderungen infileA.html
undfileB.html
sind logisch miteinander verbunden (z. B. dieselbe neue Funktionsimplementierung in beiden Dateien), während Änderungen infileC.html
undfileD.html
getrennt sind und logisch nicht mit früheren Dateien zusammenhängen. Sie können erste Stufe DateienfileA.html
undfileB.html
und begehen diejenigen.Im nächsten Schritt stellen Sie Änderungen an den verbleibenden zwei Dateien fest und übernehmen diese.
quelle
git commit -m "Implemented new feature XYZ" fileA.html fileB.html
würde gut funktionieren, ohne die Befehle git add zu benötigen. Ich komme aus der Subversion-Welt, in der Inszenierung kein Konzept ist, daher bin ich nicht von der Nützlichkeit der Git-Inszenierung überzeugtEs ist einfacher, die Verwendung der git-Befehle zu verstehen,
add
undcommit
wenn Sie sich vorstellen, dass eine Protokolldatei in Ihrem Repository auf Github verwaltet wird. Die Protokolldatei eines typischen Projekts sieht für mich möglicherweise folgendermaßen aus:Normalerweise beginne ich meinen Tag mit einer
git pull
Anfrage und beende ihn mit einergit push
Anfrage. Alles in einem Tagesbericht entspricht also dem, was zwischen ihnen passiert. Während eines jeden Tages erledige ich eine oder mehrere logische Aufgaben , bei denen einige Dateien geändert werden müssen. Die während dieser Aufgabe bearbeiteten Dateien werden in einem Index aufgelistet.Jede dieser Unteraufgaben (Aufgabe A und Aufgabe B hier) sind individuelle Commits. Der
git add
Befehl fügt Dateien zur Liste "Index der geänderten Dateien" hinzu. Dieser Vorgang wird auch als Staging bezeichnet. Dergit commit
Befehl zeichnet die Änderungen und die entsprechende Indexliste zusammen mit einer benutzerdefinierten Nachricht auf / schließt sie ab.Denken Sie daran, dass Sie immer noch nur die lokale Kopie Ihres Repositorys ändern und nicht die auf Github. Danach werden alle aufgezeichneten Änderungen zusammen mit Ihren Indexdateien für jedes Commit im Hauptrepository (auf Github) protokolliert, wenn Sie einen "Git-Push" ausführen.
Um beispielsweise den zweiten Eintrag in dieser imaginären Protokolldatei zu erhalten, hätte ich Folgendes getan:
Kurz gesagt,
git add
undgit commit
Sie können eine Änderung am Haupt-Repository in systematische logische Unteränderungen aufteilen. Wie andere Antworten und Kommentare gezeigt haben, gibt es natürlich noch viel mehr Verwendungszwecke. Dies ist jedoch eine der häufigsten Verwendungen und ein treibendes Prinzip hinter Git, das im Gegensatz zu anderen populären Systemen wie Svn ein mehrstufiges Revisionskontrollsystem ist.quelle
Der Bereitstellungsbereich hilft uns dabei, die Commits flexibler zu gestalten. Mit Basteln meine ich, die Commits in logische Einheiten aufzuteilen. Dies ist sehr wichtig, wenn Sie eine wartbare Software wünschen. Der naheliegendste Weg, dies zu erreichen:
Sie können mehrere Funktionen / Fehler in einem einzigen Arbeitsverzeichnis bearbeiten und dennoch aussagekräftige Commits erstellen. Es ist auch sehr praktisch, ein einziges Arbeitsverzeichnis zu haben, das alle unsere aktiven Arbeiten enthält. (Dies kann nur ohne Staging-Bereich erfolgen, solange sich die Änderungen niemals mit einer Datei überschneiden. Außerdem haben Sie die zusätzliche Verantwortung, manuell zu verfolgen, ob sie sich überschneiden.)
Weitere Beispiele finden Sie hier: Verwendung des Index
Und das Beste daran ist, dass die Vorteile bei dieser Liste von Workflows nicht aufhören. Wenn ein eindeutiger Workflow angezeigt wird, können Sie fast sicher sein, dass der Staging-Bereich Ihnen dabei hilft.
quelle
Ich sehe den Sinn darin, die Bühne zu verwenden, um Commits kleiner zu machen, wie von @Ben Jackson und @Tapashee Tabassum Urmi erwähnt, und manchmal benutze ich es für diesen Zweck, aber ich benutze es hauptsächlich, um meine Commits größer zu machen! Hier ist mein Punkt:
Angenommen, ich möchte eine kleine Funktion hinzufügen, für die mehrere kleinere Schritte erforderlich sind. Ich sehe keinen Grund darin, ein separates Commit für kleinere Schritte durchzuführen und meine Zeitleiste zu überfluten. Ich möchte jedoch jeden Schritt speichern und gegebenenfalls zurückgehen.
Ich inszeniere einfach die kleineren Schritte übereinander und wenn ich der Meinung bin, dass es eines Commits würdig ist, verpflichte ich mich. Auf diese Weise entferne ich die unnötigen Commits von der Timeline und kann den letzten Schritt rückgängig machen (auschecken).
Ich sehe andere Möglichkeiten, dies zu tun (Vereinfachung des Git-Verlaufs), die Sie je nach Ihren Vorlieben verwenden können:
quelle
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 .)
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.
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 add
Schritt, der über den allerersten hinausgeht, in dem eine brandneue Datei eingeführt wird. Bei Mercurial verwenden Sie denhg
Befehl, der ein Commit auswählt. Dann erledigen Sie Ihre Arbeit, führen es aushg commit
und sind fertig. Mit Git verwenden Siegit checkout
, 1 dann tun Sie Ihre Arbeit, dann laufen Siegit add
und danngit commit
. Warum der zusätzlichegit add
Schritt?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.
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 switch
anstelle von verwendengit checkout
. In diesem speziellen Fall machen diese beiden Befehle genau dasselbe. Der neue Befehl existiert, weilgit checkout
er mit zu vielen Dingen überfüllt war. sie wurde in zwei getrennte Befehle aufzuschlüsseln,git switch
undgit restore
es 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
.git
Verzeichnis 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 add
Befehl 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 verwendengit 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 checkout
zunä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 ingit add
diesen ändern , stimmen nun der Index und Ihr Arbeitsbaum überein. Dann laufen Siegit commit
und 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 --stage
undgit update-index
insbesondere -, können Sie sich das einfach als Kopie vorstellen.3 Der
git ls-files --stage
Befehl 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 status
Befehl funktioniert tatsächlich, indem zwei separategit diff
Befehle 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 diff
vergleicht 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 nichtsub.py
drin, aber der Index nicht habensub.py
darin, 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 rm
vielleicht).Der zweite
git diff
vergleicht 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 Dateiuntracked
in Ihrem Arbeitsbaum vorhanden ist, jedoch nicht im Git-Index, fügt Git sie nur der Liste der nicht verfolgten Dateien hinzu . 4Am Ende, nachdem diese untracked Dateien in einer Liste angesammelt hat ,
git status
bekannt geben , diejenigen zu Dateien Namen, aber es gibt eine spezielle Ausnahme: wenn die Name eine Datei in einer aufgeführte.gitignore
Datei, die dieses letzte Angebot unterdrückt. Beachten Sie, dass das Auflisten einer verfolgten Datei - eine, die im Git-Index enthalten ist - in a.gitignore
keine 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". 54 Wenn Sie die Kurzversion von
git status
-git status -s
verwenden, sind die nicht verfolgten Dateien nicht so getrennt, aber das Prinzip ist dasselbe. Wenn Sie die Dateien auf diese Weise akkumulieren, können Sie auchgit status
eine Reihe von nicht verfolgten Dateinamen zusammenfassen, indem Sie manchmal nur einen Verzeichnisnamen drucken. Verwenden Siegit status -uall
oder, um die vollständige Liste zu erhaltengit status -u
.5 Durch das Auflisten einer Datei können auch viele Dateivorgänge wie die nicht verfolgte Datei massenweise hinzugefügt
git add .
odergit add *
übersprungen werden. Dieser Teil wird etwas komplizierter, da Sie damitgit add --force
eine 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.gitignore
möglicherweise besser aufgerufen.git-do-not-complain-about-these-untracked-files-and-do-not-auto-add-them
oder ist ebenfalls unhandlich. Aber das ist zu lächerlich, so ist.gitignore
es.git add -u
,git commit -a
Usw.Hier gibt es einige nützliche Verknüpfungen:
git add .
fügt alle aktualisierten Dateien im aktuellen Verzeichnis und in jedem Unterverzeichnis hinzu. Dies.gitignore
gilt. Wenn also eine Datei, die derzeit nicht verfolgt wird, nicht beanstandet wirdgit status
, wird sie nicht automatisch hinzugefügt.git add -u
fü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 (diesgit add
führt dazu, dass der Index mit dem Arbeitsbaum übereinstimmt ).git add -A
ist wie das Laufengit 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 laufengit add -u
und danngit commit
. Das heißt, Sie erhalten das gleiche Verhalten, das in Mercurial praktisch ist.Ich rate generell von dem
git commit -a
Muster ab: Ich finde, dass es besser ist, esgit status
häufig zu verwenden , die Ausgabe genau zu betrachten und herauszufinden, warum dies der Fall ist, wenn der Status nicht Ihren Erwartungen entspricht. Mitgit commit -a
ist 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 -u
nur im aktuellen Verzeichnis und in den Unterverzeichnissen. Sie müssen also zuerst auf die oberste Ebene Ihres Arbeitsbaums klettern. Diegit add -A
Option hat ein ähnliches Problem.7 Ich sage ungefähr gleichwertig, weil
git commit -a
tatsä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ührengit 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 gespeichertgit 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 --only
hier 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, separategit add
Operationen zu verwenden.quelle
Es ist wie ein Kontrollkästchen, mit dem Sie auswählen können, welche Dateien festgeschrieben werden sollen.
Zum Beispiel, wenn ich bearbeitet habe
fileA.txt
undfileB.txt
.Aber ich möchtefileA.txt
nur Änderungen von festschreiben . weil ich noch nicht fertig bin mitfileB.txt
.Ich kann einfach verwenden
git add fileA.txt
und festschreibengit commit -m "changed fileA.txt"
und weiterarbeitenfileB.txt
und nach Abschluss kann ichfileB.txt
leicht festschreibenquelle