Ich habe interessante Beiträge gesehen , in denen Feinheiten erklärt wurden git reset
.
Je mehr ich darüber lese, desto mehr scheint es leider, dass ich es nicht vollständig verstehe. Ich komme aus einem SVN-Hintergrund und Git ist ein ganz neues Paradigma. Ich habe leicht Quecksilber bekommen, aber Git ist viel technischer.
Ich denke, git reset
ist nah dran hg revert
, aber es scheint, dass es Unterschiede gibt.
Was genau macht es git reset
also? Bitte geben Sie detaillierte Erklärungen zu:
- die Optionen
--hard
,--soft
und--merge
; - die seltsame Notation, die Sie mit
HEAD
solchen wieHEAD^
und verwendenHEAD~1
; - konkrete Anwendungsfälle und Arbeitsabläufe;
- Konsequenzen für die Arbeitskopie, das
HEAD
und Ihr globales Stresslevel.
Antworten:
Im Allgemeinen besteht
git reset
die Funktion darin, den aktuellen Zweig zu nehmen und ihn auf einen anderen Punkt zurückzusetzen und möglicherweise den Index und den Arbeitsbaum mitzubringen. Genauer gesagt, wenn Ihre Hauptniederlassung (derzeit ausgecheckt) so ist:und Sie erkennen, dass der Meister auf B und nicht auf C zeigen soll. Sie werden ihn verwenden
git reset B
, um ihn dorthin zu verschieben:Exkurs: Dies unterscheidet sich von einer Kasse. Wenn du rennen würdest
git checkout B
, würdest du folgendes bekommen:Sie sind in einem getrennten HEAD-Zustand gelandet.
HEAD
, Arbeitsbaum, Index alle übereinstimmenB
, aber der Hauptzweig wurde bei zurückgelassenC
. Wenn SieD
zu diesem Zeitpunkt ein neues Commit durchführen , erhalten Sie dieses, was wahrscheinlich nicht das ist, was Sie wollen:Denken Sie daran, dass beim Zurücksetzen keine Festschreibungen vorgenommen werden. Es wird lediglich ein Zweig (der ein Zeiger auf eine Festschreibung ist) aktualisiert, um auf eine andere Festschreibung zu verweisen. Der Rest ist nur ein Detail dessen, was mit Ihrem Index und Arbeitsbaum passiert.
Anwendungsfälle
Ich beschreibe viele der Hauptanwendungsfälle
git reset
in meinen Beschreibungen der verschiedenen Optionen im nächsten Abschnitt. Es kann wirklich für eine Vielzahl von Dingen verwendet werden; Der gemeinsame Thread besteht darin, dass bei allen der Zweig, der Index und / oder der Arbeitsbaum zurückgesetzt werden, um auf ein bestimmtes Commit zu verweisen oder mit diesem übereinzustimmen.Dinge, auf die man achten muss
--hard
kann dazu führen, dass Sie wirklich Arbeit verlieren. Es ändert Ihren Arbeitsbaum.git reset [options] commit
kann dazu führen, dass Sie Commits (irgendwie) verlieren. Im obigen Spielzeugbeispiel haben wir das Commit verlorenC
. Es befindet sich immer noch im Repo, und Sie können es finden, indem Sie aufgit reflog show HEAD
oder schauengit reflog show master
, aber es ist von keiner Filiale aus mehr zugänglich.Git löscht solche Commits nach 30 Tagen dauerhaft, aber bis dahin können Sie C wiederherstellen, indem Sie erneut auf einen Zweig zeigen (
git checkout C; git branch <new branch name>
).Argumente
Um die Manpage zu paraphrasieren, wird am häufigsten das Formular verwendet
git reset [<commit>] [paths...]
, mit dem die angegebenen Pfade aus dem angegebenen Commit auf ihren Status zurückgesetzt werden. Wenn die Pfade nicht bereitgestellt werden, wird der gesamte Baum zurückgesetzt, und wenn das Commit nicht bereitgestellt wird, wird es als HEAD (das aktuelle Commit) angesehen. Dies ist ein allgemeines Muster für Git-Befehle (z. B. Auschecken, Diff, Protokollieren, obwohl die genaue Semantik variiert), daher sollte es nicht allzu überraschend sein.Zum Beispiel
git reset other-branch path/to/foo
alles setzt in path / to / foo in seinen Zustand in anderem Zweig,git reset -- .
setzt das aktuelle Verzeichnis auf seinen Zustand in HEAD, und ein einfachesgit reset
setzt alles auf seinen Zustand in dem Kopf.Der Hauptarbeitsbaum und die Indexoptionen
Es gibt vier Hauptoptionen, um zu steuern, was während des Zurücksetzens mit Ihrem Arbeitsbaum und Index passiert.
Denken Sie daran, dass der Index der "Staging-Bereich" von git ist - hier gehen die Dinge, wenn Sie
git add
in Vorbereitung auf das Festschreiben sagen .--hard
passt alles zu dem Commit, auf das Sie zurückgesetzt haben. Dies ist wahrscheinlich am einfachsten zu verstehen. Alle Ihre lokalen Änderungen werden blockiert. Eine Hauptanwendung besteht darin, Ihre Arbeit wegzublasen, aber keine Commits zu wechseln:git reset --hard
bedeutetgit reset --hard HEAD
, dass Sie den Zweig nicht ändern, sondern alle lokalen Änderungen entfernen . Das andere ist einfach, einen Zweig von einem Ort zum anderen zu verschieben und den Index / Arbeitsbaum synchron zu halten. Dies ist derjenige, der Sie wirklich dazu bringen kann, Arbeit zu verlieren, weil er Ihren Arbeitsbaum ändert. Seien Sie sehr, sehr sicher, dass Sie lokale Arbeit wegwerfen möchten, bevor Sie welche ausführenreset --hard
.--mixed
ist die Standardeinstellung, dhgit reset
bedeutetgit reset --mixed
. Es setzt den Index zurück, aber nicht den Arbeitsbaum. Dies bedeutet, dass alle Ihre Dateien intakt sind, aber alle Unterschiede zwischen dem ursprünglichen Commit und dem, auf das Sie zurückgesetzt wurden, als lokale Änderungen (oder nicht verfolgte Dateien) mit Git-Status angezeigt werden. Verwenden Sie diese Option, wenn Sie feststellen, dass Sie einige schlechte Commits durchgeführt haben, aber die gesamte geleistete Arbeit beibehalten möchten, damit Sie sie beheben und erneut festlegen können. Zum Festschreiben müssen Sie dem Index erneut Dateien hinzufügen (git add ...
).--soft
Berührt den Index oder den Arbeitsbaum nicht. Alle Ihre Dateien sind wie bei intakt--mixed
, aber alle Änderungen werden wiechanges to be committed
beim Git-Status angezeigt (dh zur Vorbereitung auf das Festschreiben eingecheckt). Verwenden Sie diese Option, wenn Sie feststellen, dass Sie einige schlechte Verpflichtungen eingegangen sind, die Arbeit jedoch gut ist. Sie müssen sie lediglich anders festlegen. Der Index bleibt unberührt, sodass Sie sofort ein Commit durchführen können, wenn Sie möchten. Das resultierende Commit hat denselben Inhalt wie vor dem Zurücksetzen.--merge
wurde kürzlich hinzugefügt und soll Ihnen helfen, eine fehlgeschlagene Zusammenführung abzubrechen. Dies ist erforderlich, da Siegit merge
tatsächlich eine Zusammenführung mit einem Dirty-Work-Baum (einer mit lokalen Änderungen) versuchen können, solange sich diese Änderungen in Dateien befinden, die von der Zusammenführung nicht betroffen sind.git reset --merge
Setzt den Index zurück (wie--mixed
- alle Änderungen werden als lokale Änderungen angezeigt) und setzt die von der Zusammenführung betroffenen Dateien zurück, lässt die anderen jedoch in Ruhe. Dies wird hoffentlich alles wieder so machen, wie es vor der schlechten Zusammenführung war. Normalerweise verwenden Sie es alsgit reset --merge
(Bedeutunggit reset --merge HEAD
), da Sie nur die Zusammenführung zurücksetzen und den Zweig nicht verschieben möchten. (HEAD
wurde noch nicht aktualisiert, da die Zusammenführung fehlgeschlagen ist)Nehmen wir an, Sie haben die Dateien A und B geändert und versuchen, in einem Zweig zusammenzuführen, der die Dateien C und D geändert hat. Die Zusammenführung schlägt aus irgendeinem Grund fehl und Sie entscheiden, sie abzubrechen. Sie verwenden
git reset --merge
. Es bringt C und D zurück zu dem, in dem sie sich befandenHEAD
, lässt jedoch Ihre Änderungen an A und B in Ruhe, da sie nicht Teil der versuchten Zusammenführung waren.Möchten Sie mehr wissen?
Ich denke, das
man git reset
ist wirklich ziemlich gut dafür - vielleicht brauchst du ein bisschen Verständnis dafür, wie Git funktioniert, damit sie wirklich eintauchen. Insbesondere wenn Sie sich die Zeit nehmen, sie sorgfältig zu lesen, sind diese Tabellen, in denen der Status der Dateien im Index und im Arbeitsbaum für alle verschiedenen Optionen und Fälle aufgeführt ist, sehr, sehr hilfreich. (Aber ja, sie sind sehr dicht - sie vermitteln eine Menge der oben genannten Informationen in einer sehr präzisen Form.)Seltsame Notation
Die "seltsame Notation" (
HEAD^
undHEAD~1
), die Sie erwähnen, ist lediglich eine Abkürzung für die Angabe von Commits, ohne einen Hash-Namen wie verwenden zu müssen3ebe3f6
. Es ist vollständig dokumentiert im Abschnitt "Festlegen von Revisionen" der Manpage für git-rev-parse mit vielen Beispielen und zugehöriger Syntax. Das Caret und die Tilde bedeuten eigentlich verschiedene Dinge :HEAD~
ist die Abkürzung fürHEAD~1
und bedeutet das erste übergeordnete Element des Commits.HEAD~2
bedeutet das erste Elternteil des Commits. Stellen Sie sichHEAD~n
"n Commits vor HEAD" oder "den Vorfahren der n-ten Generation von HEAD" vor.HEAD^
(oderHEAD^1
) bedeutet auch das erste übergeordnete Element des Commits.HEAD^2
bedeutet das zweite übergeordnete Element des Commits . Denken Sie daran, dass ein normales Zusammenführungs-Commit zwei übergeordnete Elemente hat - das erste übergeordnete Element ist das zusammengeführte Commit und das zweite übergeordnete Element ist das festgeschriebene Commit. Im Allgemeinen können Zusammenführungen tatsächlich beliebig viele Eltern haben (Octopus-Zusammenführungen).^
und~
Betreiber können aneinandergereiht werden, wie inHEAD~3^2
den zweit Eltern des dritten Generation VorfahrenHEAD
,HEAD^^2
die zweite Mutter des ersten ElternteilHEAD
oder sogarHEAD^^^
, was gleichwertig istHEAD~3
.quelle
Denken
git
Sie daran, dass in Ihnen haben:HEAD
Zeiger , der Ihnen sagt, an welchem Commit Sie arbeitenIn aufsteigender Reihenfolge der Gefährlichkeit:
--soft
bewegt sichHEAD
, berührt aber nicht den Bereitstellungsbereich oder den Arbeitsbaum.--mixed
VerschiebtHEAD
und aktualisiert den Staging-Bereich, jedoch nicht den Arbeitsbaum.--merge
bewegtHEAD
, setzt den Staging - Bereich, und versucht , alle Änderungen in Ihrem Arbeits Baum in den neuen Arbeits Baum zu bewegen.--hard
VerschiebtHEAD
und passt Ihren Bereitstellungsbereich und Ihren Arbeitsbaum an den neuen anHEAD
und wirft alles weg.--soft
Sie diese Option, wenn Sie zu einem anderen Commit wechseln und die Dinge reparieren möchten, ohne "Ihren Platz zu verlieren". Es ist ziemlich selten, dass Sie das brauchen.- -
- -
Verwenden Sie
--mixed
(dies ist die Standardeinstellung), wenn Sie sehen möchten, wie die Dinge bei einem anderen Commit aussehen, aber keine Änderungen verlieren möchten, die Sie bereits haben.Verwenden
--merge
Sie diese Option, wenn Sie an einen neuen Ort wechseln möchten, die bereits vorhandenen Änderungen jedoch in den Arbeitsbaum integrieren möchten.Verwenden Sie
--hard
diese Option, um alles auszulöschen und beim neuen Commit eine neue Tabelle zu erstellen.quelle
reset --merge
. Es wird keine Drei-Wege-Zusammenführung durchgeführt. Es ist wirklich nur zum Zurücksetzen von Konflikten, wie in den Dokumenten beschrieben. Sie möchten verwendencheckout --merge
, um das zu tun, wovon Sie sprechen. Wenn Sie den Zweig auch verschieben möchten, besteht die einzige Möglichkeit meiner Meinung nach darin, ein Auschecken / Zurücksetzen durchzuführen, um ihn mit sich zu ziehen.reset --merge
mit einem anderen Ziel (der Standardeinstellung) arbeiten möchtenHEAD
, da es in Fällen, in denen es nicht nur zu einem Abbruch einer Konfliktzusammenführung kommt, weggeworfen wird Informationen, die Sie sonst speichern könnten.git reset
undgit reset -- .
.Der Beitrag Reset Demystified im Blog Pro Git bietet eine sehr einfache Erklärung zu
git reset
undgit checkout
.Nach all den hilfreichen Diskussionen oben in diesem Beitrag reduziert der Autor die Regeln auf die folgenden einfachen drei Schritte:
quelle
Wenn Sie etwas für Git festlegen, müssen Sie zuerst Ihre Änderungen inszenieren (zum Index hinzufügen). Dies bedeutet, dass Sie git alle Dateien hinzufügen müssen, die in dieses Commit aufgenommen werden sollen, bevor git sie als Teil des Commits betrachtet. Schauen wir uns zuerst das Bild eines Git-Repo an:
Also, es ist jetzt einfach. Wir müssen im Arbeitsverzeichnis arbeiten, Dateien, Verzeichnisse und alles erstellen. Diese Änderungen sind nicht verfolgte Änderungen. Um sie nachverfolgen zu können, müssen wir sie mit dem Befehl git add zum Git-Index hinzufügen . Sobald sie zum Git-Index hinzugefügt wurden. Wir können diese Änderungen jetzt festschreiben, wenn wir sie in das Git-Repository verschieben möchten.
Aber plötzlich erfuhren wir beim Festschreiben, dass wir eine zusätzliche Datei haben, die wir im Index hinzugefügt haben, die nicht erforderlich ist, um das Git-Repository einzuschieben. Das heißt, wir wollen diese Datei nicht im Index haben. Die Frage ist nun, wie diese Datei aus dem Git-Index entfernt werden kann. Da wir Git Add verwendet haben , um sie in den Index aufzunehmen, wäre es logisch, Git RM zu verwenden . Falsch! git rm löscht einfach die Datei und fügt die Löschung dem Index hinzu. Was ist jetzt zu tun?
Verwenden:-
Es löscht Ihren Index und lässt Ihr Arbeitsverzeichnis unberührt. (einfach alles aufheben).
Es kann mit einer Reihe von Optionen verwendet werden. Es gibt drei Hauptoptionen für das Zurücksetzen von Git: --hard, --soft und --mixed . Diese wirken sich beim Zurücksetzen zusätzlich zum HEAD-Zeiger auf das Zurücksetzen von get aus.
Erstens setzt --hard alles zurück. Ihr aktuelles Verzeichnis wäre genau so, als ob Sie diesem Zweig die ganze Zeit gefolgt wären. Das Arbeitsverzeichnis und der Index werden in dieses Commit geändert. Dies ist die Version, die ich am häufigsten benutze. git reset --hard ist so etwas wie svn revert .
Als nächstes setzt das genaue Gegenteil - Soft - weder den Arbeitsbaum noch den Index zurück. Es bewegt nur den HEAD-Zeiger. Dadurch bleiben in Ihrem aktuellen Status alle Änderungen, die sich von dem Commit unterscheiden, zu dem Sie wechseln, in Ihrem Verzeichnis gespeichert und für das Commit „inszeniert“. Wenn Sie lokal ein Commit durchführen, das Commit jedoch nicht auf den Git-Server übertragen haben, können Sie es auf das vorherige Commit zurücksetzen und mit einer guten Commit-Nachricht erneut festschreiben.
Schließlich setzt --mixed den Index zurück, nicht jedoch den Arbeitsbaum. Die Änderungen sind also alle noch vorhanden, aber "nicht inszeniert" und müssten git hinzugefügt oder git commit -a sein . Wir verwenden dies manchmal, wenn wir mit git commit -a mehr als beabsichtigt festgelegt haben. Wir können das Commit mit git reset --mixed zurücksetzen, die Dinge hinzufügen, die wir festschreiben möchten, und diese einfach festschreiben.
Unterschied zwischen Git Revert und Git Reset : -
Mit einfachen Worten, git reset ist ein Befehl zum Beheben von nicht festgeschriebenen Fehlern und git revert ist ein Befehl zum Beheben von festgeschriebenen Fehlern .
Es bedeutet, wenn wir bei einer Änderung einen Fehler gemacht und diesen festgeschrieben und auf git repo verschoben haben, dann ist git revert die Lösung. Und falls wir vor dem Push / Commit denselben Fehler festgestellt haben, können wir das Problem mit git reset beheben.
Ich hoffe, es wird Ihnen helfen, Ihre Verwirrung loszuwerden.
quelle
git reset HEAD
standardmäßig?--hard
,--soft
Oder--mixed
? Tolle Antwort übrigens.git reset --hard
dass Sie einige Daten verlieren. Und es gibt einen Punkt, der falsch sein könnte (obwohl ich nicht 100% sicher bin ... lerne noch!):--mixed
Wenn Sie über Sie sprechen, sagen Sie: "Wir verwenden dies manchmal, wenn wir mehr begangen haben, als wir mit git commit -a beabsichtigt hatten." Meinten Sie: "Wenn wir mehr inszenieren würden , als wir wolltengit stage .
"? Wenn Sie es wirklich begangen haben, denke ich, dass es zu spät ist (wie Sie am Ende sagen, ist Git Reset ein Befehl, um "nicht festgeschriebene Fehler zu beheben")TL; DR
LÄNGERE VERSION
Aber das ist offensichtlich simpel, daher die vielen ziemlich ausführlichen Antworten. Für mich war es sinnvoller,
git reset
im Zusammenhang mit dem Rückgängigmachen von Änderungen nachzulesen . ZB sehen Sie dies:Von https://www.atlassian.com/git/tutorials/undoing-changes/git-reset
und das
Unter https://www.atlassian.com/git/tutorials/resetting-checking-out-and-reverting/commit-level-operations
quelle
Bitte beachten Sie, dass dies eine vereinfachte Erklärung ist, die als erster Schritt zum Verständnis dieser komplexen Funktionalität gedacht ist.
Kann für visuelle Lernende hilfreich sein, die nach jedem dieser Befehle visualisieren möchten, wie ihr Projektstatus aussieht:
Für diejenigen, die Terminal mit aktivierter Farbe verwenden (git config --global color.ui auto):
git reset --soft A
und Sie werden B und Cs Zeug in Grün sehen (inszeniert und bereit zu begehen)git reset --mixed A
(odergit reset A
) und Sie werden B und Cs Zeug in Rot sehen (nicht inszeniert und bereit, inszeniert zu werden (grün) und dann festgeschrieben)git reset --hard A
und Sie werden die Änderungen von B und C nirgendwo mehr sehen (als ob sie nie existiert hätten)Oder für diejenigen, die ein GUI-Programm wie 'Tower' oder 'SourceTree' verwenden.
git reset --soft A
und Sie werden die Inhalte von B und C im Bereich "Bereitgestellte Dateien" sehen, die zum Festschreiben bereit sindgit reset --mixed A
(odergit reset A
) und Sie sehen die Inhalte von B und C im Bereich "Nicht bereitgestellte Dateien", die bereit sind, in "Bereitgestellt" verschoben und dann festgeschrieben zu werdengit reset --hard A
und Sie werden die Änderungen von B und C nirgendwo mehr sehen (als ob sie nie existiert hätten)quelle
Die Kasse zeigt den Kopf auf ein bestimmtes Commit.
Zurücksetzen zeigt einen Zweig auf ein bestimmtes Commit. (Ein Zweig ist ein Zeiger auf ein Commit.)
Übrigens, wenn Ihr Kopf nicht auf ein Commit zeigt, auf das auch ein Zweig zeigt, haben Sie einen abgetrennten Kopf.(stellte sich als falsch heraus. Siehe Kommentare ...)quelle