Was ist der Unterschied zwischen "Git Reset" und "Git Checkout"?

440

Ich habe immer git resetund git checkoutin dem Sinne daran gedacht , dass beide das Projekt zu einem bestimmten Commit zurückbringen. Ich bin jedoch der Meinung, dass sie nicht genau gleich sein können, da dies überflüssig wäre. Was ist der tatsächliche Unterschied zwischen den beiden? Ich bin etwas verwirrt, da der SVN nur svn codas Commit zurücksetzen muss .

HINZUGEFÜGT

VonC und Charles haben die Unterschiede zwischen git resetund git checkoutwirklich gut erklärt. Mein derzeitiges Verständnis ist, dass git resetalle Änderungen auf ein bestimmtes Commit zurückgesetzt werden, während git checkoutmehr oder weniger auf einen Zweig vorbereitet wird. Ich fand die folgenden zwei Diagramme sehr nützlich, um zu diesem Verständnis zu gelangen:

http://a.imageshack.us/img651/1559/86421927.png http://a.imageshack.us/img801/1986/resetr.png

HINZUGEFÜGT 3

Unter http://think-like-a-git.net/sections/rebase-from-the-ground-up/using-git-cherry-pick-to-simulate-git-rebase.html kann das Auschecken und Zurücksetzen emuliert werden die Rebase.

Geben Sie hier die Bildbeschreibung ein

git checkout bar 
git reset --hard newbar 
git branch -d newbar 

Geben Sie hier die Bildbeschreibung ein

prosseek
quelle
Werfen
Sie
Betreff: "Ist es falsch oder zu stark vereinfacht?" Ja, dieses erste Diagramm ist hinsichtlich des Unterschieds zwischen Auschecken und Zurücksetzen irreführend. (Es kann in Bezug auf die -- filesVarianten in Ordnung sein ; ich bin mir nicht sicher.) In diesem Diagramm sieht es so aus, als ob der Hauptunterschied darin besteht, ob sie den Index oder den WD beeinflussen. Siehe meine Antwort dazu. Das 2. und 3. Diagramm sind sehr hilfreich, um den tatsächlichen Unterschied zu erkennen. Das 4. und 5. Diagramm sind nützlich, um zu überprüfen, ob Sie verstehen, was diese Befehle bewirken, aber nicht wirklich dabei helfen, dorthin zu gelangen.
LarsH
Ich fand den Abschnitt "Check it out" in "Git Tools Reset Demystified", um die hilfreichste Zusammenfassung zu geben.
Josiah Yoder
1
prosseek: Wenn Sie @LarsH zustimmen, dass das erste Diagramm irreführend ist, können Sie es bitte entfernen?
Josiah Yoder
Bitte beachten Sie, dass das Auschecken und Zurücksetzen nur den 2. Teil der Rebase emuliert und zusätzliche Schritte (im verlinkten think-like-a-git.netArtikel angegeben) erforderlich sind, um Datenverlust zu vermeiden.
Cowlinator

Antworten:

198
  • git resetEs geht speziell darum, den Index zu aktualisieren und den HEAD zu verschieben.
  • git checkoutHier geht es darum, den Arbeitsbaum (auf den Index oder den angegebenen Baum) zu aktualisieren . Der HEAD wird nur aktualisiert, wenn Sie einen Zweig auschecken (wenn nicht, erhalten Sie einen abgetrennten HEAD ).
    (Mit Git 2.23 Q3 2019 wird dies git restorenicht unbedingt der Fall sein . git checkout)

Zum Vergleich: Da svn keinen Index hat, svn checkoutkopiert nur ein funktionierender Baum eine bestimmte Revision in ein separates Verzeichnis.
Das nähere Äquivalent für git checkoutwürde:

  • svn update (Wenn Sie sich in derselben Branche befinden, dh dieselbe SVN-URL)
  • svn switch (Wenn Sie zum Beispiel denselben Zweig auschecken, aber von einer anderen SVN-Repo-URL)

Alle diese drei Arbeits Baum Modifikationen ( svn checkout, update, switch) haben nur einen Befehl in git: git checkout.
Aber da Git auch den Begriff Index hat (diesen "Staging-Bereich" zwischen dem Repo und dem Arbeitsbaum), haben Sie auch git reset.


Thinkeye erwähnt in den Kommentaren den Artikel " Demystified zurücksetzen ".

Wenn wir zum Beispiel zwei Zweige haben, ' master' und ' develop', die auf unterschiedliche Commits zeigen, und wir gerade auf ' develop' sind (also zeigt HEAD darauf) und wir ausführen git reset master, wird ' develop' selbst jetzt auf dasselbe Commit zeigen, das '' master'tut.

Wenn wir stattdessen rennen git checkout master, developbewegt HEADsich ' ' nicht, sondern selbst. HEADwird jetzt auf ' master' zeigen.

In beiden Fällen versuchen wir also HEAD, auf Commit hinzuweisen A, aber wie wir das tun, ist sehr unterschiedlich. resetWenn Sie die Verzweigungspunkte verschieben HEAD, bewegt HEADsich die Kasse selbst, um auf eine andere Verzweigung zu zeigen.

http://git-scm.com/images/reset/reset-checkout.png

Zu diesen Punkten jedoch:

LarsH fügt in den Kommentaren hinzu :

Der erste Absatz dieser Antwort ist jedoch irreführend: " git checkout... aktualisiert den HEAD nur, wenn Sie einen Zweig auschecken (wenn nicht, erhalten Sie einen abgetrennten HEAD)".
Nicht wahr: git checkoutAktualisiert den HEAD, selbst wenn Sie ein Commit auschecken, das kein Zweig ist (und ja, Sie erhalten einen getrennten HEAD, der jedoch noch aktualisiert wurde).

git checkout a839e8f updates HEAD to point to commit a839e8f.

De Novo stimmt den Kommentaren zu :

@LarsH ist richtig.
Die zweite Aufzählung enthält ein Missverständnis darüber, in welchem ​​HEAD sich befindet. Der HEAD wird nur aktualisiert, wenn Sie einen Zweig auschecken.
KOPF geht, wo immer Sie sind, wie ein Schatten.
Durch das Auschecken eines nicht verzweigten Verweises (z. B. eines Tags) oder eines Commits direkt wird HEAD verschoben. Abgelöster Kopf bedeutet nicht, dass Sie sich vom KOPF gelöst haben, sondern dass sich der Kopf von einem Zweigreflex gelöst hat, von dem aus Sie z git log --pretty=format:"%d" -1.

  • Angehängte Kopfzustände beginnen mit (HEAD ->,
  • Abgelöst wird weiterhin angezeigt (HEAD, es wird jedoch kein Pfeil zu einer Verzweigungsreferenz angezeigt.
VonC
quelle
7
Ich würde sagen, dass git resetes darum geht, das "Label" des Zweigs zu ändern und optional den Index oder den Arbeitsbaum als Nebeneffekt zu aktualisieren. git checkoutHier geht es darum, den Arbeitsbaum zu aktualisieren und den aktuell "ausgewählten" Zweig (den HEAD) zu wechseln .
Mikko Rantalainen
2
@ MikkoRantalainen nein. git resetist 100% über die HEAD. Es funktioniert auch in einem getrennten HEAD-Modus ( stackoverflow.com/a/3965714/6309 ), dh es gibt keinen Zweig (!). git checkout funktioniert auch in einem getrennten HEAD-Modus oder kann zum Auschecken eines SHA1 in einem getrennten HEAD-Modus verwendet werden: Auch in diesem Fall ist kein Zweig beteiligt.
VonC
3
Ich denke, es lohnt sich, weiter zu lesen für alle verlorenen Seelen, die von einer Suchmaschine hierher geschickt wurden: git-scm.com/blog/2011/07/11/reset.html
Thinkeye
2
@ Thinkeye gute Referenz. Ich habe es zusammen mit einem relevanten Auszug in die Antwort für mehr Sichtbarkeit aufgenommen.
VonC
2
Die Erklärung von Reset Demystified ist ausgezeichnet. Der erste Absatz dieser Antwort ist jedoch irreführend: "git checkout ... aktualisiert den HEAD nur, wenn Sie einen Zweig auschecken (wenn nicht, erhalten Sie einen abgetrennten HEAD)". Nicht wahr ... git checkout aktualisiert den HEAD auch dann, wenn Sie ein Commit auschecken, das kein Zweig ist (und ja, Sie erhalten einen getrennten HEAD, der jedoch noch aktualisiert wurde). Vielleicht verstehe ich falsch, was Sie unter "Update" verstehen? git checkout a839e8faktualisiert HEAD so, dass es auf Commit verweist a839e8f.
LarsH
67

resetSetzt in der einfachsten Form den Index zurück, ohne den Arbeitsbaum zu berühren, während checkoutder Arbeitsbaum geändert wird, ohne den Index zu berühren.

Setzt den Index auf Übereinstimmung zurück HEAD, wobei der Arbeitsbaum allein gelassen wird:

git reset

Konzeptionell wird dadurch der Index in den Arbeitsbaum ausgecheckt. Damit es tatsächlich etwas tut, müssten Sie es -fzwingen, lokale Änderungen zu überschreiben. Dies ist eine Sicherheitsfunktion, um sicherzustellen, dass das Formular "kein Argument" nicht destruktiv ist:

git checkout

Sobald Sie mit dem Hinzufügen von Parametern beginnen, gibt es zwar einige Überlappungen.

checkoutwird normalerweise mit einem Zweig, Tag oder Commit verwendet. In diesem Fall wird HEADder Index auf das angegebene Commit zurückgesetzt und das Auschecken des Index in den Arbeitsbaum durchgeführt.

Wenn Sie angeben --hard, können resetSie auch darum bitten reset, den Arbeitsbaum zu überschreiben und den Index zurückzusetzen.

Wenn Sie derzeit eine Filiale ausgecheckt haben, gibt es einen entscheidenden Unterschied zwischen resetund checkoutwann Sie eine alternative Filiale oder ein Commit angeben. resetändert den aktuellen Zweig so, dass er auf das ausgewählte Commit zeigt, während checkoutder aktuelle Zweig in Ruhe bleibt, aber stattdessen den angegebenen Zweig auscheckt oder festschreibt.

Andere Formen von resetund commitbeinhalten die Bereitstellung von Pfaden.

Wenn Sie Pfade liefern resetSie nicht liefern kann --hardund resetwird nur der Index - Version der gelieferten Pfade zu der Version in der Commit geliefert ändern (oder , HEADwenn Sie nicht eine Festschreibung angeben).

Wenn Sie Pfade angeben checkout, resetwird die Indexversion der angegebenen Pfade so aktualisiert , dass sie mit dem angegebenen Commit (oder HEAD) übereinstimmt, aber die Indexversion der angegebenen Pfade wird immer in den Arbeitsbaum eingecheckt.

CB Bailey
quelle
2
Es ist falsch zu sagen, dass "checkout" den Index nicht ändert: Er ändert ihn, wenn er verwendet wird, um von einem Zweig zu einem anderen zu wechseln.
wiki1000
In ihrer einfachsten Form setzt das Zurücksetzen den Index zurück, ohne den Arbeitsbaum zu berühren, während das Auschecken den Arbeitsbaum ändert, ohne den Index zu berühren. : Wie verwirrend ist das: |
Aditya Gupta
41

Ein einfacher Anwendungsfall beim
Zurücksetzen von Änderungen: 1. Verwenden Sie Zurücksetzen, wenn Sie das Staging einer geänderten Datei rückgängig machen möchten.
2. Verwenden Sie checkout, wenn Sie Änderungen an nicht bereitgestellten Dateien verwerfen möchten.

John Doe
quelle
1
Perfekte Antwort. Vielen Dank.
user358591
11

Der Hauptunterschied auf den Punkt gebracht besteht darin, dass reset die aktuelle Zweigreferenz verschoben wird , während checkoutdies nicht der Fall ist (es wird HEAD verschoben).

Wie das Pro Git-Buch unter Reset Demystified erklärt ,

Das erste, was Sie resettun müssen, ist zu verschieben, worauf HEAD zeigt . Dies ist nicht dasselbe wie das Ändern des KOPFES selbst (was auch der checkoutFall ist). reset Verschiebt den Zweig , auf den HEAD zeigt. Dies bedeutet, wenn HEAD auf den masterZweig eingestellt ist (dh Sie befinden sich derzeit im masterZweig), git reset 9e5e6a4beginnt die Ausführung mit einem masterPunkt auf 9e5e6a4. [Betonung hinzugefügt]

Siehe auch VonCs Antwort für einen sehr hilfreichen Text- und Diagrammauszug aus demselben Artikel, den ich hier nicht duplizieren werde.

Natürlich gibt es viel mehr Details über das, was Auswirkungen checkoutund resetauf dem Index und den Arbeitsbaum haben kann, je nachdem , welche Parameter verwendet werden. Es kann viele Ähnlichkeiten und Unterschiede zwischen den beiden Befehlen geben. Aber aus meiner Sicht ist der wichtigste Unterschied, ob sie die Spitze des aktuellen Zweigs bewegen.

LarsH
quelle
2
Gutes Feedback, zusätzlich zu meiner älteren Antwort. +1
VonC
2

Die beiden Befehle (Zurücksetzen und Auschecken) sind völlig unterschiedlich.

checkout X IST NICHT reset --hard X

Wenn X ein Zweigname ist, checkout Xwird der aktuelle Zweig geändert, während dies reset --hard Xnicht der Fall ist.

wiki1000
quelle
2
Wenn X jedoch eine Datei oder ein Ordner ist, sind sie identisch.
Ted Bigham
1

kurze Mnemonik:

git reset HEAD           :             index = HEAD
git checkout             : file_tree = index
git reset --hard HEAD    : file_tree = index = HEAD
Филя Усков
quelle