810 Stimmen

Was bedeutet "git reset" im Klartext?

Ich habe gesehen interessante Beiträge Erläuterung von Feinheiten über git reset .

Je mehr ich darüber lese, desto mehr stellt sich leider heraus, dass ich es nicht ganz verstehe. Ich komme aus einem SVN-Hintergrund und Git ist ein völlig neues Paradigma. Mercurial habe ich leicht verstanden, aber Git ist viel technischer.

Ich denke git reset ist nahe an hg revert aber es scheint Unterschiede zu geben.

Was genau bedeutet also git reset tun? Bitte geben Sie ausführliche Erklärungen zu folgenden Punkten:

  • die Optionen --hard , --soft y --merge ;
  • die seltsame Notation, die Sie mit HEAD wie zum Beispiel HEAD^ y HEAD~1 ;
  • konkrete Anwendungsfälle und Arbeitsabläufe;
  • Auswirkungen auf die Arbeitskopie, die HEAD und Ihr globales Stressniveau.

1148voto

Cascabel Punkte 449595

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

93voto

John Feminella Punkte 292907

Denken Sie daran, dass in git Sie haben:

  • die HEAD Zeiger die Ihnen mitteilt, an welcher Übergabe Sie gerade arbeiten
  • die Arbeitsbaum die den Zustand der Dateien auf Ihrem System darstellt
  • die Bereitstellungsraum (auch genannt die Index ), die Änderungen "stufenweise" vornimmt, so dass sie später zusammen übertragen werden können

Bitte fügen Sie ausführliche Erläuterungen zu folgenden Punkten bei:

--hard , --soft y --merge ;

In aufsteigender Reihenfolge der Gefährlichkeit:

  • --soft bewegt sich HEAD berührt aber nicht den Aufenthaltsbereich oder den Arbeitsbaum.
  • --mixed bewegt sich HEAD und aktualisiert den Bereitstellungsbereich, aber nicht den Arbeitsbaum.
  • --merge bewegt sich HEAD setzt den Bereitstellungsbereich zurück und versucht, alle Änderungen in Ihrem Arbeitsbaum in den neuen Arbeitsbaum zu verschieben.
  • --hard bewegt sich HEAD y passt Ihren Bereitstellungsbereich und Arbeitsbaum an die neue HEAD und wirft alles weg.

konkrete Anwendungsfälle und Arbeitsabläufe;

  • Utilice --soft wenn Sie zu einem anderen Commit wechseln und die Dinge in Ordnung bringen wollen, ohne "Ihren Platz zu verlieren". Es ist ziemlich selten, dass man das braucht.

--

# git reset --soft example
touch foo                            // Add a file, make some changes.
git add foo                          // 
git commit -m "bad commit message"   // Commit... D'oh, that was a mistake!
git reset --soft HEAD^               // Go back one commit and fix things.
git commit -m "good commit"          // There, now it's right.

--

  • Utilice --mixed (das ist die Standardeinstellung), wenn Sie sehen wollen, wie es bei einem anderen Commit aussieht, Sie aber keine Änderungen verlieren wollen, die Sie bereits vorgenommen haben.

  • Utilice --merge wenn Sie an eine neue Stelle wechseln wollen, aber die Änderungen, die Sie bereits vorgenommen haben, in den Arbeitsbaum übernehmen wollen.

  • Utilice --hard um alles zu löschen und bei der neuen Übertragung einen Neuanfang zu machen.

32voto

love Punkte 3203

Wenn Sie etwas an Git übergeben, müssen Sie Ihre Änderungen zunächst in den Index aufnehmen. Das bedeutet, dass Sie alle Dateien, die Sie in diese Übergabe einbeziehen wollen, mit Git hinzufügen müssen, bevor Git sie als Teil der Übergabe betrachtet. Werfen wir zunächst einen Blick auf das Bild eines Git-Repositoriums: enter image description here

Es ist also ganz einfach. Wir müssen im Arbeitsverzeichnis arbeiten, Dateien und Verzeichnisse erstellen und so weiter. Diese Änderungen sind nicht nachverfolgte Änderungen. Um sie nachverfolgen zu können, müssen wir sie dem Git-Index hinzufügen, indem wir Git hinzufügen Befehl. Sobald sie dem Git-Index hinzugefügt sind. Wir können diese Änderungen nun festschreiben, wenn wir sie in das Git-Repository übertragen wollen.

Doch plötzlich stellten wir beim Commit fest, dass wir eine zusätzliche Datei haben, die wir in den Index aufgenommen haben und die nicht in das Git-Repository übertragen werden soll. Das bedeutet, dass wir diese Datei nicht im Index haben wollen. Nun stellt sich die Frage, wie wir diese Datei aus dem Git-Index entfernen können, denn wir haben Git hinzufügen um sie in den Index aufzunehmen, wäre es logisch, die Git-Rm ? Falsch! Git-Rm wird die Datei einfach gelöscht und die Löschung in den Index aufgenommen. Was also ist jetzt zu tun?

Verwendung:-

Git-Reset

Es löscht Ihren Index und lässt Ihr Arbeitsverzeichnis unberührt. (es wird einfach alles gelöscht).

Es kann mit einer Reihe von Optionen verwendet werden. Es gibt drei Hauptoptionen für die Verwendung mit git reset: --hard, --soft und --mixed . Diese beeinflussen, was zusätzlich zum HEAD-Zeiger zurückgesetzt wird, wenn Sie zurücksetzen.

Erstens, --hart setzt alles zurück. Ihr aktuelles Verzeichnis wäre genau so, wie es wäre, wenn Sie die ganze Zeit diesem Zweig gefolgt wären. Das Arbeitsverzeichnis und der Index werden auf diesen Commit geändert. Dies ist die Version, die ich am häufigsten verwende. git reset --hard ist etwa so svn rückgängig machen .

Dann das genaue Gegenteil, -soft setzt weder den Arbeitsbaum noch den Index zurück. Es wird nur der HEAD-Zeiger verschoben. Dadurch bleibt Ihr aktueller Zustand mit allen Änderungen, die sich von dem Commit, zu dem Sie wechseln, unterscheiden, in Ihrem Verzeichnis erhalten und wird für das Commit "bereitgestellt". Wenn Sie einen Commit lokal durchführen, diesen aber noch nicht auf den Git-Server übertragen haben, können Sie auf den vorherigen Commit zurücksetzen und mit einer guten Commit-Meldung erneut committen.

Endlich, --mixed setzt den Index zurück, aber nicht den Arbeitsbaum. Die Änderungen sind also alle noch da, sind aber "unstaged" und müssten mit git add'ed oder git commit -a Wenn wir mit git commit -a mehr übertragen haben, als wir wollten, können wir die Übertragung mit git reset --mixed rückgängig machen, die Dinge hinzufügen, die wir übertragen wollen, und nur diese übertragen.

Unterschied zwischen git revert und git reset :-


Mit einfachen Worten, Git-Reset ist ein Befehl an "Fehler beheben-unverbindlich" y mit einem Git rückgängig machen ist ein Befehl an "korrigierter Fehler" .

Das heißt, wenn wir einen Fehler in einer Änderung gemacht haben und diese in das Git-Repositorium übertragen haben, dann mit einem Git rückgängig machen ist die Lösung. Und falls wir denselben Fehler vor dem Pushing/Commiting festgestellt haben, können wir Git-Reset um das Problem zu beheben.

Ich hoffe, es wird Ihnen helfen, Ihre Verwirrung zu beseitigen.

7voto

Snowcrash Punkte 73122

TL;DR

git reset setzt Staging auf die letzte Übertragung zurück. verwenden --hard um auch die Dateien in Ihrem Arbeitsverzeichnis auf die letzte Übertragung zurückzusetzen.

LÄNGERE AUSFÜHRUNG

Aber das ist natürlich sehr vereinfacht, daher die vielen ausführlichen Antworten. Für mich war es sinnvoller, mich zu informieren über git reset im Zusammenhang mit der Rückgängigmachung von Änderungen. Siehe z. B. dies:

Wenn git revert ein "sicherer" Weg ist, um Änderungen rückgängig zu machen, kann man sich git reset als die gefährliche Methode betrachten. Wenn Sie mit git reset rückgängig machen (und die Commits nicht mehr von einem Ref oder dem Reflog referenziert werden), gibt es gibt es keine Möglichkeit, die ursprüngliche Kopie wiederherzustellen - es handelt sich um eine permanente Rückgängigmachung. Vorsicht ist geboten Vorsicht walten lassen, da dies einer der einzigen Git-Befehle ist, bei dem Ihre Arbeit verloren gehen kann.

Von https://www.atlassian.com/git/tutorials/undoing-changes/git-reset

und dies

Auf der Commit-Ebene ist das Zurücksetzen eine Möglichkeit, die Spitze eines Zweigs auf einen anderen Commit zu verschieben. Dies kann verwendet werden, um Commits aus dem aktuellen Zweig zu entfernen.

Von https://www.atlassian.com/git/tutorials/resetting-checking-out-and-reverting/commit-level-operations

4voto

timhc22 Punkte 6691

Bitte beachten Sie, dass es sich hierbei um eine vereinfachte Erklärung handelt, die als erster Schritt zum Verständnis dieser komplexen Funktion gedacht ist.

Dies kann für visuelle Lernende hilfreich sein, die sich ein Bild davon machen wollen, wie ihr Projektstatus nach jedem dieser Befehle aussieht:


Für diejenigen, die Terminal mit eingeschalteter Farbe verwenden (git config --global color.ui auto):

git reset --soft A und Sie werden die Sachen von B und C in grün sehen (vorbereitet und bereit zur Übergabe)

git reset --mixed A (o git reset A ) und Sie werden die Sachen von B und C in rot sehen (unstaged und bereit für staged (grün) und dann committed)

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 Sachen von B und C im Bereich 'staged files' sehen, bereit zum Übertragen

git reset --mixed A (o git reset A ) und Sie werden die Dateien von B und C im Bereich "Unstaged Files" sehen, die bereit sind, in den Staged-Bereich verschoben und dann committed zu werden

git reset --hard A und Sie werden die Änderungen von B und C nirgendwo mehr sehen (als ob sie nie existiert hätten)

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X