Generell, git reset
hat die Aufgabe, die aktuelle Verzweigung zurückzusetzen, so dass sie auf einen anderen Ort zeigt, und möglicherweise den Index und den Arbeitsbaum mitzunehmen. Konkreter gesagt, wenn Ihr Master-Zweig (derzeit ausgecheckt) so aussieht:
- A - B - C (HEAD, master)
und Sie merken, dass der Master auf B und nicht auf C zeigen soll, verwenden Sie git reset B
um es dorthin zu bringen:
- A - B (HEAD, master) # - C is still here, but there's no branch pointing to it anymore
Abschweifung: Dies ist etwas anderes als ein Checkout. Wenn Sie git checkout B
würden Sie dies erhalten:
- A - B (HEAD) - C (master)
Sie sind in einem losgelösten HEAD-Zustand gelandet. HEAD
, Arbeitsbaum, Index alle übereinstimmen B
aber der Hauptzweig blieb zurück bei C
. Wenn Sie eine neue Übertragung vornehmen D
an dieser Stelle erhalten Sie dies, was wahrscheinlich nicht das ist, was Sie wollen:
- A - B - C (master)
\
D (HEAD)
Denken Sie daran, dass reset keine Commits macht, sondern nur einen Branch (der ein Zeiger auf einen Commit ist) aktualisiert, um auf einen anderen Commit zu zeigen. Der Rest sind nur Details darüber, was mit Ihrem Index und Arbeitsbaum passiert.
Anwendungsfälle
Ich behandle viele der wichtigsten Anwendungsfälle für git reset
im Rahmen meiner Beschreibungen der verschiedenen Optionen im nächsten Abschnitt. Es kann wirklich für eine Vielzahl von Dingen verwendet werden; der gemeinsame Nenner ist, dass sie alle das Zurücksetzen des Zweigs, des Index und/oder des Arbeitsbaums beinhalten, um auf einen bestimmten Commit zu zeigen/zu passen.
Dinge, auf die man achten sollte
-
--hard
kann dazu führen, dass Sie wirklich Arbeit verlieren. Es verändert Ihren Arbeitsbaum.
-
git reset [options] commit
kann dazu führen, dass Sie Commits (gewissermaßen) verlieren. In dem obigen Beispiel haben wir Commit verloren C
. Es ist immer noch in der Repo, und Sie können es finden, indem Sie auf git reflog show HEAD
o git reflog show master
aber sie ist eigentlich von keiner Zweigstelle mehr zugänglich.
-
Git löscht solche Commits nach 30 Tagen dauerhaft, aber bis dahin können Sie C wiederherstellen, indem Sie erneut einen Branch darauf verweisen ( git checkout C; git branch <new branch name>
).
Argumente
Um die Manpage zu paraphrasieren, ist die gebräuchlichste Verwendung die Form git reset [<commit>] [paths...]
die die angegebenen Pfade auf den Zustand vor der angegebenen Übergabe zurücksetzt. Wenn die Pfade nicht angegeben werden, wird der gesamte Baum zurückgesetzt, und wenn der Commit nicht angegeben wird, wird er als HEAD (der aktuelle Commit) angenommen. Dies ist ein gängiges Muster bei allen Git-Befehlen (z.B. checkout, diff, log, obwohl die genaue Semantik variiert), also sollte es nicht allzu überraschend sein.
Zum Beispiel, git reset other-branch path/to/foo
setzt alles in path/to/foo auf den Zustand in other-branch zurück, git reset -- .
setzt das aktuelle Verzeichnis auf seinen Zustand in HEAD zurück, und eine einfache git reset
setzt alles auf den Zustand in HEAD zurück.
Der Hauptarbeitsbaum und die Indexoptionen
Es gibt vier Hauptoptionen, um zu steuern, was mit Ihrem Arbeitsbaum und Index während des Zurücksetzens geschieht.
Denken Sie daran, dass der Index Gits "Bereitstellungsbereich" ist - er ist der Ort, an dem die Dinge landen, wenn Sie sagen git add
in Vorbereitung auf ein Engagement.
-
--hard
stellt alles auf den Commit ein, auf den Sie zurückgesetzt haben. Dies ist wahrscheinlich am einfachsten zu verstehen. Alle Ihre lokalen Änderungen werden überschrieben. Eine Hauptanwendung ist es, Ihre Arbeit wegzublasen, aber nicht die Commits zu wechseln: git reset --hard
bedeutet git reset --hard HEAD
d.h. der Zweig wird nicht geändert, aber alle lokalen Änderungen werden entfernt. Die andere Möglichkeit besteht darin, einen Zweig einfach von einem Ort zum anderen zu verschieben und dabei Index und Arbeitsbaum synchron zu halten. Dies ist diejenige, die Sie wirklich um Arbeit bringen kann, weil sie Ihren Arbeitsbaum verändert. Seien Sie sich sehr sicher, dass Sie die Arbeit vor Ort wegwerfen wollen, bevor Sie etwas tun. reset --hard
.
-
--mixed
ist der Standard, d.h. git reset
bedeutet git reset --mixed
. Dabei wird der Index zurückgesetzt, nicht aber der Arbeitsbaum. Das bedeutet, dass alle Ihre Dateien intakt sind, aber alle Unterschiede zwischen dem ursprünglichen Commit und dem, auf den Sie zurücksetzen, werden als lokale Änderungen (oder nicht verfolgte Dateien) mit Git-Status angezeigt. Verwenden Sie diese Methode, wenn Sie feststellen, dass Sie einige schlechte Übertragungen gemacht haben, aber Sie möchten die ganze Arbeit, die Sie gemacht haben, behalten, um sie zu korrigieren und erneut zu übertragen. Um eine Übergabe durchzuführen, müssen Sie die Dateien erneut in den Index aufnehmen ( git add ...
).
-
--soft
berührt den Index nicht oder Arbeitsbaum. Alle Ihre Dateien sind intakt wie bei --mixed
, aber alle Änderungen werden angezeigt als changes to be committed
mit Git-Status (d.h. eingecheckt in Vorbereitung auf die Übergabe). Verwenden Sie diese Option, wenn Sie feststellen, dass Sie einige schlechte Übertragungen vorgenommen haben, die Arbeit aber in Ordnung ist - Sie müssen sie nur anders übertragen. Der Index bleibt unangetastet, Sie können also sofort committen, wenn Sie wollen - der resultierende Commit hat den gleichen Inhalt wie vor dem Zurücksetzen.
-
--merge
wurde kürzlich hinzugefügt und soll Ihnen helfen, eine fehlgeschlagene Zusammenführung abzubrechen. Dies ist notwendig, weil git merge
lässt Sie tatsächlich einen Zusammenführungsversuch mit einem schmutzigen Arbeitsbaum (einem mit lokalen Änderungen) durchführen, solange diese Änderungen in Dateien liegen, die von der Zusammenführung nicht betroffen sind. git reset --merge
setzt den Index zurück (wie --mixed
- alle Änderungen werden als lokale Modifikationen angezeigt), und setzt die von der Zusammenführung betroffenen Dateien zurück, lässt die anderen aber in Ruhe. Dadurch wird hoffentlich alles so wiederhergestellt, wie es vor der fehlerhaften Zusammenführung war. Normalerweise verwenden Sie es als git reset --merge
(Bedeutung git reset --merge HEAD
), weil Sie nur die Zusammenführung zurücksetzen, nicht aber den Zweig verschieben wollen. ( HEAD
wurde noch nicht aktualisiert, da die Zusammenführung fehlgeschlagen ist)
Um konkreter zu werden, nehmen wir an, Sie haben die Dateien A und B geändert und versuchen, einen Zweig zusammenzuführen, der die Dateien C und D geändert hat. Sie verwenden git reset --merge
. Sie bringt C und D wieder in den Zustand, in dem sie sich vor HEAD
, lässt aber Ihre Änderungen an A und B unberücksichtigt, da sie nicht Teil der versuchten Zusammenführung waren.
Möchten Sie mehr erfahren?
Ich glaube man git reset
ist wirklich sehr gut dafür geeignet - vielleicht braucht man ein wenig Verständnis für die Funktionsweise von Git, um sie wirklich zu verstehen. Wenn Sie sich die Zeit nehmen, sie sorgfältig zu lesen, sind vor allem die Tabellen mit den Zuständen der Dateien im Index und im Arbeitsbaum für alle verschiedenen Optionen und Fälle sehr hilfreich. (Aber ja, sie sind sehr dicht - sie vermitteln eine ganze Menge der oben genannten Informationen in einer sehr prägnanten Form).
Seltsame Notation
Die "seltsame Notation" ( HEAD^
y HEAD~1
), die Sie erwähnen, ist einfach eine Abkürzung für die Angabe von Übertragungen, ohne dass ein Hash-Name wie 3ebe3f6
. Es ist vollständig dokumentiert in der "Abschnitt "Spezifizierung der Revisionen der Manpage für git-rev-parse, mit vielen Beispielen und verwandter Syntax. Das Caret und die Tilde bedeuten eigentlich verschiedene Dinge :
HEAD~
ist die Abkürzung für HEAD~1
und bedeutet den ersten Elternteil der Übergabe. HEAD~2
bedeutet der erste Elternteil des ersten Elternteils des Commit. Denken Sie an HEAD~n
als "n Commits vor HEAD" oder "der Vorfahre der n-ten Generation von HEAD".
HEAD^
(o HEAD^1
) ist auch der erste Elternteil der Übergabe. HEAD^2
bedeutet, dass der Commit zweite Elternteil. Denken Sie daran, dass ein normaler Merge-Commit zwei Elternteile hat - der erste Elternteil ist der Commit, in den zusammengeführt wird, und der zweite Elternteil ist der Commit, der zusammengeführt wurde. Im Allgemeinen können Zusammenführungen beliebig viele Eltern haben (Oktopus-Zusammenführungen).
- El
^
y ~
Operatoren können aneinandergereiht werden, wie in HEAD~3^2
, der zweite Elternteil des Vorfahren der dritten Generation von HEAD
, HEAD^^2
der zweite Elternteil des ersten Elternteils von HEAD
oder sogar HEAD^^^
, was gleichbedeutend ist mit HEAD~3
.
![caret and tilde]()