Git Reset vs Revert vs Rebase
Veröffentlicht: 2021-05-20In diesem Artikel erfahren Sie, wie Sie mit Commits in Git herumspielen können.
Als Entwickler wären Sie mehrmals mit solchen Situationen konfrontiert, in denen Sie zu einem Ihrer vorherigen Commits zurückkehren wollten, sich aber nicht sicher sind, wie das geht. Und selbst wenn Sie die Git-Befehle wie reset, revert, rebase kennen, sind sich die Unterschiede zwischen ihnen nicht bewusst. Fangen wir also an und verstehen, was git reset, revert und rebase sind.
Git-Reset
Git reset ist ein komplexer Befehl, mit dem die Änderungen rückgängig gemacht werden.
Sie können sich git reset als eine Rollback-Funktion vorstellen. Mit git reset können Sie zwischen verschiedenen Commits springen. Es gibt drei Modi zum Ausführen eines git reset-Befehls: –soft, –mixed und –hard. Standardmäßig verwendet der Befehl git reset den gemischten Modus. In einem git-reset-Workflow kommen drei interne Verwaltungsmechanismen von git ins Spiel: HEAD , Staging-Bereich (Index) und das Arbeitsverzeichnis .

Das Arbeitsverzeichnis ist der Ort, an dem Sie gerade arbeiten, es ist der Ort, an dem Ihre Dateien vorhanden sind. Mit einem git status-Befehl können Sie sehen, welche Dateien/Ordner im Arbeitsverzeichnis vorhanden sind.
Der Staging-Bereich (Index) ist der Ort, an dem git alle Änderungen in den Dateien verfolgt und speichert. Die gespeicherten Änderungen werden im .git-Verzeichnis widergespiegelt. Sie verwenden git add "filename", um die Datei zum Staging-Bereich hinzuzufügen. Und wie zuvor sehen Sie beim Ausführen von git status, welche Dateien im Staging-Bereich vorhanden sind.
Der aktuelle Zweig in Git wird als HEAD bezeichnet. Es zeigt auf den letzten Commit, der im aktuellen Checkout-Zweig stattgefunden hat. Es wird als Zeiger für jede Referenz behandelt. Sobald Sie in eine andere Filiale auschecken, wechselt der HEAD ebenfalls in die neue Filiale.
Lassen Sie mich erklären, wie git reset im harten, weichen und gemischten Modus funktioniert. Der Hard-Modus wird verwendet, um zum angegebenen Commit zu gelangen, das Arbeitsverzeichnis wird mit Dateien dieses Commits gefüllt und der Staging-Bereich wird zurückgesetzt. Beim Soft-Reset wird nur der Zeiger auf den angegebenen Commit geändert. Die Dateien aller Commits verbleiben vor dem Zurücksetzen im Arbeitsverzeichnis und im Staging-Bereich. Im gemischten Modus (Standard) werden sowohl der Zeiger als auch der Staging-Bereich zurückgesetzt.
Git Zurücksetzen schwer
Der Zweck von git hard reset besteht darin, den HEAD in den angegebenen Commit zu verschieben. Es entfernt alle Commits, die nach dem angegebenen Commit aufgetreten sind. Dieser Befehl ändert den Commit-Verlauf und zeigt auf den angegebenen Commit.
In diesem Beispiel werde ich drei neue Dateien hinzufügen, sie festschreiben und dann einen Hard-Reset durchführen.
Wie Sie dem folgenden Befehl entnehmen können, gibt es im Moment nichts zu begehen.
$ git status On branch master Your branch is ahead of 'origin/master' by 2 commits. (use "git push" to publish your local commits) nothing to commit, working tree cleanJetzt werde ich 3 Dateien erstellen und einige Inhalte hinzufügen.
$ vi file1.txt $ vi file2.txt $ vi file3.txtFügen Sie diese Dateien dem vorhandenen Repository hinzu.
$ git add file*Wenn Sie den Statusbefehl erneut ausführen, werden die neuen Dateien angezeigt, die ich gerade erstellt habe.
$ git status On branch master Your branch is ahead of 'origin/master' by 2 commits. (use "git push" to publish your local commits) Changes to be committed: (use "git restore --staged <file>..." to unstage) new file: file1.txt new file: file2.txt new file: file3.txtLassen Sie mich Ihnen vor dem Commit zeigen, dass ich derzeit ein Protokoll von 3 Commits in Git habe.
$ git log --oneline 0db602e (HEAD -> master) one more commit 59c86c9 new commit e2f44fc (origin/master, origin/HEAD) testJetzt werde ich mich dem Repository verpflichten.
$ git commit -m 'added 3 files' [master d69950b] added 3 files 3 files changed, 3 insertions(+) create mode 100644 file1.txt create mode 100644 file2.txt create mode 100644 file3.txtWenn ich ls-Dateien mache, sehen Sie, dass die neuen Dateien hinzugefügt wurden.
$ git ls-files demo dummyfile newfile file1.txt file2.txt file3.txtWenn ich den log-Befehl in git ausführe, habe ich 4 Commits und der HEAD zeigt auf den neuesten Commit.
$ git log --oneline d69950b (HEAD -> master) added 3 files 0db602e one more commit 59c86c9 new commit e2f44fc (origin/master, origin/HEAD) testWenn ich die Datei file1.txt manuell lösche und einen Git-Status durchführe, wird die Meldung angezeigt, dass die Änderungen nicht für den Commit bereitgestellt werden.
$ git status On branch master Your branch is ahead of 'origin/master' by 3 commits. (use "git push" to publish your local commits) Changes not staged for commit: (use "git add/rm <file>..." to update what will be committed) (use "git restore <file>..." to discard changes in working directory) deleted: file1.txt no changes added to commit (use "git add" and/or "git commit -a")Jetzt führe ich den Hard-Reset-Befehl aus.
$ git reset --hard HEAD is now at d69950b added 3 filesWenn ich den Status erneut überprüfe, werde ich feststellen, dass nichts festgeschrieben werden muss und die gelöschte Datei wieder im Repository ist. Das Rollback ist passiert, weil ich nach dem Löschen der Datei keinen Commit gemacht habe, so dass sie nach einem Hard-Reset in den vorherigen Zustand zurückgekehrt ist.
$ git status On branch master Your branch is ahead of 'origin/master' by 3 commits. (use "git push" to publish your local commits) nothing to commit, working tree cleanWenn ich das Log von git überprüfe, sieht es so aus.
$ git log commit d69950b7ea406a97499e07f9b28082db9db0b387 (HEAD -> master) Author: mrgeek <[email protected]> Date: Mon May 17 19:53:31 2020 +0530 added 3 files commit 0db602e085a4d59cfa9393abac41ff5fd7afcb14 Author: mrgeek <[email protected]> Date: Mon May 17 01:04:13 2020 +0530 one more commit commit 59c86c96a82589bad5ecba7668ad38aa684ab323 Author: mrgeek <[email protected]> Date: Mon May 17 00:54:53 2020 +0530 new commit commit e2f44fca2f8afad8e4d73df6b72111f2f2fd71ad (origin/master, origin/HEAD) Author: mrgeek <[email protected]> Date: Mon May 17 00:16:33 2020 +0530 testDer Zweck des Hard-Resets besteht darin, auf den angegebenen Commit zu verweisen und das Arbeitsverzeichnis und den Staging-Bereich zu aktualisieren. Lassen Sie mich Ihnen noch ein Beispiel zeigen. Derzeit sieht die Visualisierung meiner Commits wie folgt aus:

Hier führe ich den Befehl mit HEAD^ aus, was bedeutet, dass ich auf den vorherigen Commit zurücksetzen möchte (ein Commit zurück).
$ git reset --hard HEAD^ HEAD is now at 0db602e one more commitSie können sehen, dass sich der Kopfzeiger von d69950b in 0db602e geändert hat.
$ git log --oneline 0db602e (HEAD -> master) one more commit 59c86c9 new commit e2f44fc (origin/master, origin/HEAD) test 
Wenn Sie das Protokoll überprüfen, ist der Commit von d69950b weg und der Head zeigt jetzt auf 0db602e SHA.
$ git log commit 0db602e085a4d59cfa9393abac41ff5fd7afcb14 (HEAD -> master) Author: mrgeek <[email protected]> Date: Mon May 17 01:04:13 2020 +0530 one more commit commit 59c86c96a82589bad5ecba7668ad38aa684ab323 Author: mrgeek <[email protected]> Date: Mon May 17 00:54:53 2020 +0530 new commit commit e2f44fca2f8afad8e4d73df6b72111f2f2fd71ad (origin/master, origin/HEAD) Author: mrgeek <[email protected]> Date: Mon May 17 00:16:33 2020 +0530 TestWenn Sie die ls-Dateien ausführen, können Sie sehen, dass file1.txt, file2.txt und files3.txt nicht mehr im Repository sind, da dieser Commit und seine Datei nach dem Hard-Reset entfernt wurden.
$ git ls-files demo dummyfile newfileGit Soft-Reset
Ebenso zeige ich Ihnen jetzt ein Beispiel für einen Soft-Reset. Bedenken Sie, ich habe die 3 Dateien wie oben erwähnt erneut hinzugefügt und übertragen. Das Git-Log wird wie unten gezeigt angezeigt. Sie können sehen, dass 'Soft Reset' mein neuestes Commit ist, und HEAD weist auch darauf hin.
$ git log --oneline aa40085 (HEAD -> master) soft reset 0db602e one more commit 59c86c9 new commit e2f44fc (origin/master, origin/HEAD) testDetails zum Commit im Protokoll können mit dem folgenden Befehl eingesehen werden.
$ git log commit aa400858aab3927e79116941c715749780a59fc9 (HEAD -> master) Author: mrgeek <[email protected]> Date: Mon May 17 21:01:36 2020 +0530 soft reset commit 0db602e085a4d59cfa9393abac41ff5fd7afcb14 Author: mrgeek <[email protected]> Date: Mon May 17 01:04:13 2020 +0530 one more commit commit 59c86c96a82589bad5ecba7668ad38aa684ab323 Author: mrgeek <[email protected]> Date: Mon May 17 00:54:53 2020 +0530 new commit commit e2f44fca2f8afad8e4d73df6b72111f2f2fd71ad (origin/master, origin/HEAD) Author: mrgeek <[email protected]> Date: Mon May 17 00:16:33 2020 +0530 testJetzt möchte ich mit dem Soft-Reset zu einem der älteren Commits mit SHA 0db602e085a4d59cfa9393abac41ff5fd7afcb14 wechseln

Dazu führe ich den folgenden Befehl aus. Sie müssen mehr als 6 Anfangszeichen von SHA übergeben, das vollständige SHA ist nicht erforderlich.
$ git reset --soft 0db602e085a4Wenn ich jetzt das Git-Protokoll ausführe, kann ich sehen, dass der HEAD auf den von mir angegebenen Commit zurückgesetzt wurde.
$ git log commit 0db602e085a4d59cfa9393abac41ff5fd7afcb14 (HEAD -> master) Author: mrgeek <[email protected]> Date: Mon May 17 01:04:13 2020 +0530 one more commit commit 59c86c96a82589bad5ecba7668ad38aa684ab323 Author: mrgeek <[email protected]> Date: Mon May 17 00:54:53 2020 +0530 new commit commit e2f44fca2f8afad8e4d73df6b72111f2f2fd71ad (origin/master, origin/HEAD) Author: mrgeek <[email protected]> Date: Mon May 17 00:16:33 2020 +0530 testAber der Unterschied hier ist, dass die Dateien des Commits (aa400858aab3927e79116941c715749780a59fc9), wo ich 3 Dateien hinzugefügt hatte, immer noch in meinem Arbeitsverzeichnis sind. Sie wurden nicht gelöscht. Aus diesem Grund sollten Sie eher einen Soft-Reset als einen Hard-Reset verwenden. Im Soft-Modus besteht kein Risiko, die Dateien zu verlieren.
$ git ls-files demo dummyfile file1.txt file2.txt file3.txt newfileGit-Revert
In Git wird der Revert-Befehl verwendet, um eine Revert-Operation durchzuführen, dh um einige Änderungen rückgängig zu machen. Es ähnelt dem Reset-Befehl, aber der einzige Unterschied besteht darin, dass Sie einen neuen Commit ausführen, um zu einem bestimmten Commit zurückzukehren. Kurz gesagt, es ist fair zu sagen, dass der Befehl git revert ein Commit ist.
Der Git-Befehl revert löscht keine Daten, während der Wiederherstellungsvorgang ausgeführt wird.
Nehmen wir an, ich füge 3 Dateien hinzu und führe eine Git-Commit-Operation für das Revert-Beispiel durch.
$ git commit -m 'add 3 files again' [master 812335d] add 3 files again 3 files changed, 3 insertions(+) create mode 100644 file1.txt create mode 100644 file2.txt create mode 100644 file3.txtDas Protokoll zeigt das neue Commit an.
$ git log --oneline 812335d (HEAD -> master) add 3 files again 0db602e one more commit 59c86c9 new commit e2f44fc (origin/master, origin/HEAD) testNun möchte ich zu einem meiner früheren Commits zurückkehren, sagen wir – „59c86c9 new commit“. Ich würde den folgenden Befehl ausführen.
$ git revert 59c86c9Dadurch wird eine Datei geöffnet, Sie finden die Details des Commits, zu dem Sie zurückkehren möchten, und Sie können Ihrem neuen Commit hier einen Namen geben und die Datei dann speichern und schließen.
Revert "new commit" This reverts commit 59c86c96a82589bad5ecba7668ad38aa684ab323. # Please enter the commit message for your changes. Lines starting # with '#' will be ignored, and an empty message aborts the commit. # # On branch master # Your branch is ahead of 'origin/master' by 4 commits. # (use "git push" to publish your local commits) # # Changes to be committed: # modified: dummyfileNachdem Sie die Datei gespeichert und geschlossen haben, erhalten Sie diese Ausgabe.
$ git revert 59c86c9 [master af72b7a] Revert "new commit" 1 file changed, 1 insertion(+), 1 deletion(-)Um nun die notwendigen Änderungen vorzunehmen, hat revert im Gegensatz zu reset einen weiteren neuen Commit durchgeführt. Wenn Sie das Protokoll erneut überprüfen, finden Sie aufgrund der Zurücksetzungsoperation einen neuen Commit.
$ git log --oneline af72b7a (HEAD -> master) Revert "new commit" 812335d add 3 files again 0db602e one more commit 59c86c9 new commit e2f44fc (origin/master, origin/HEAD) test 
Das Git-Log enthält den gesamten Verlauf der Commits. Wenn Sie die Commits aus der Historie entfernen möchten, dann ist revert keine gute Wahl, aber wenn Sie die Commit-Änderungen in der Historie beibehalten möchten, dann ist revert der geeignete Befehl anstelle von reset.
Git-Rebase
In Git ist Rebase die Methode, Commits eines Branchs über einen anderen Branch zu verschieben oder zu kombinieren. Als Entwickler würde ich meine Features in einem realen Szenario nicht auf dem Master-Branch erstellen. Ich würde an meinem eigenen Branch (einem 'Feature-Branch') arbeiten, und wenn ich ein paar Commits in meinem Feature-Branch mit dem hinzugefügten Feature habe, würde ich ihn gerne in den Master-Branch verschieben.
Rebase kann manchmal etwas verwirrend sein, weil es einem Merge sehr ähnlich ist. Das Ziel des Zusammenführens und Rebasierens von beiden besteht darin, die Commits aus meinem Feature-Branch zu nehmen und in einen Master-Branch oder einen anderen Branch zu übertragen. Bedenken Sie, ich habe ein Diagramm, das wie folgt aussieht:

Angenommen, Sie arbeiten in einem Team mit anderen Entwicklern. In diesem Fall können Sie sich vorstellen, dass dies sehr komplex werden kann, wenn eine Reihe anderer Entwickler an verschiedenen Funktionszweigen arbeiten und mehrere Änderungen zusammengeführt haben. Es wird verwirrend, die Spur zu verfolgen.
Hier hilft also Rebase. Anstatt einen Git-Merge durchzuführen, mache ich diesmal eine Rebase, bei der ich meine beiden Feature-Branch-Commits nehmen und in den Master-Branch verschieben möchte. Ein Rebase nimmt alle meine Commits aus dem Feature-Branch und verschiebt sie über die Master-Branch-Commits. Hinter den Kulissen dupliziert git also die Feature-Branch-Commits auf den Master-Branch.

Mit diesem Ansatz erhalten Sie ein sauberes, geradliniges Diagramm mit allen Commits in einer Reihe.

Es macht es einfach zu verfolgen, welche Commits wohin gegangen sind. Sie können sich vorstellen, dass in einem Team mit vielen Entwicklern alle Commits noch hintereinander liegen. Es ist also wirklich einfach zu folgen, selbst wenn viele Leute gleichzeitig an demselben Projekt arbeiten.
Lassen Sie mich Ihnen das praktisch zeigen.
So sieht mein Master Branch aktuell aus. Es hat 4 Commits.
$ git log --oneline 812335d (HEAD -> master) add 3 files again 0db602e one more commit 59c86c9 new commit e2f44fc (origin/master, origin/HEAD) testIch werde den folgenden Befehl ausführen, um einen neuen Branch namens Feature zu erstellen und zu diesem zu wechseln, und dieser Branch wird aus dem 2. Commit erstellt, dh 59c86c9
(master) $ git checkout -b feature 59c86c9 Switched to a new branch 'feature'Wenn Sie das Protokoll im Feature-Zweig überprüfen, enthält es nur 2 Commits vom Master (Mainline).
(feature) $ git log --oneline 59c86c9 (HEAD -> feature) new commit e2f44fc (origin/master, origin/HEAD) testIch werde Feature 1 erstellen und an den Feature-Branch übergeben.
(feature) $ vi feature1.txt (feature) $ git add . The file will have its original line endings in your working directory (feature) $ git commit -m 'feature 1' [feature c639e1b] feature 1 1 file changed, 1 insertion(+) create mode 100644 feature1.txtIch werde ein weiteres Feature, dh Feature 2, im Feature-Zweig erstellen und es festschreiben.
(feature) $ vi feature2.txt (feature) $ git add . The file will have its original line endings in your working directory (feature) $ git commit -m 'feature 2' [feature 0f4db49] feature 2 1 file changed, 1 insertion(+) create mode 100644 feature2.txtWenn Sie nun das Protokoll des Feature-Zweigs überprüfen, enthält es zwei neue Commits, die ich oben ausgeführt habe.
(feature) $ git log --oneline 0f4db49 (HEAD -> feature) feature 2 c639e1b feature 1 59c86c9 new commit e2f44fc (origin/master, origin/HEAD) testJetzt möchte ich diese beiden neuen Funktionen zum Master-Zweig hinzufügen. Dafür verwende ich den rebase-Befehl. Vom Feature-Branch aus rebasiere ich gegen den Master-Branch. Was dies bewirkt, ist, dass mein Feature-Zweig gegen die neuesten Änderungen verankert wird.
(feature) $ git rebase master Successfully rebased and updated refs/heads/feature.Jetzt gehe ich weiter und checke den Master-Zweig aus.
(feature) $ git checkout master Switched to branch 'master' Your branch is ahead of 'origin/master' by 3 commits. (use "git push" to publish your local commits)Und schließlich rebasieren Sie den Master-Zweig gegen meinen Feature-Zweig. Dies nimmt diese beiden neuen Commits in meinem Feature-Branch und spielt sie über meinem Master-Branch ab.
(master) $ git rebase feature Successfully rebased and updated refs/heads/master.Wenn ich jetzt das Protokoll im Master-Zweig überprüfe, kann ich sehen, dass die beiden Commits meines Features-Zweigs erfolgreich zu meinem Master-Zweig hinzugefügt wurden.
(master) $ git log --oneline 766c996 (HEAD -> master, feature) feature 2 c036a11 feature 1 812335d add 3 files again 0db602e one more commit 59c86c9 new commit e2f44fc (origin/master, origin/HEAD) testDas war alles über Reset-, Revert- und Rebase-Befehle in Git.
Fazit
Das war alles über Reset-, Revert- und Rebase-Befehle in Git. Ich hoffe, diese Schritt-für-Schritt-Anleitung war hilfreich. Jetzt wissen Sie, wie Sie mit den im Artikel erwähnten Befehlen nach Bedarf mit Ihren Commits herumspielen können.
