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:
- A - B - C (HEAD, master)
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:
- A - B (HEAD, master) # - C is still here, but there's no branch pointing to it anymore
Exkurs: Dies unterscheidet sich von einer Kasse. Wenn du rennen würdest git checkout B
, würdest du folgendes bekommen:
- A - B (HEAD) - C (master)
Sie sind in einem getrennten HEAD-Zustand gelandet. HEAD
, Arbeitsbaum, Index alle übereinstimmen B
, aber der Hauptzweig wurde bei zurückgelassen C
. Wenn Sie D
zu diesem Zeitpunkt ein neues Commit durchführen , erhalten Sie dieses, was wahrscheinlich nicht das ist, was Sie wollen:
- A - B - C (master)
\
D (HEAD)
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 verloren C
. Es befindet sich immer noch im Repo, und Sie können es finden, indem Sie auf git reflog show HEAD
oder schauen git 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 einfaches git 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
bedeutet git 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ühren reset --hard
.
--mixed
ist die Standardeinstellung, dh git reset
bedeutet git 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 wie changes 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 Sie git 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 als git reset --merge
(Bedeutung git 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 befanden HEAD
, 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^
und HEAD~1
), die Sie erwähnen, ist lediglich eine Abkürzung für die Angabe von Commits, ohne einen Hash-Namen wie verwenden zu müssen 3ebe3f6
. 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ür HEAD~1
und bedeutet das erste übergeordnete Element des Commits. HEAD~2
bedeutet das erste Elternteil des Commits. Stellen Sie sich HEAD~n
"n Commits vor HEAD" oder "den Vorfahren der n-ten Generation von HEAD" vor.
HEAD^
(oder HEAD^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).
- Die
^
und ~
Betreiber können aneinandergereiht werden, wie in HEAD~3^2
den zweit Eltern des dritten Generation Vorfahren HEAD
, HEAD^^2
die zweite Mutter des ersten Elternteil HEAD
oder sogar HEAD^^^
, was gleichwertig ist HEAD~3
.