In diesem Artikel erfahren Sie, wie Sie mit Commits in Git herumspielen können.
Als Entwickler hätten Sie in solchen Situationen mehrmals Situationen gehabt, in denen Sie zu einem Ihrer vorherigen Commits zurückkehren wollten, sich aber nicht sicher waren, wie Sie dies tun sollen. Und selbst wenn Sie das wissen Git Befehle wie Zurücksetzen, Zurücksetzen, Zurücksetzen, Sie sind sich der Unterschiede zwischen ihnen nicht bewusst. Also lasst uns anfangen 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 das Zurücksetzen von Git als Rollback-Funktion vorstellen. Mit git reset können Sie zwischen verschiedenen Commits wechseln. 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 Workflow zum Zurücksetzen von Git kommen drei interne Verwaltungsmechanismen von Git ins Spiel: KOPF, Bühnenbereich (Index) und die Arbeitsverzeichnis.
Das Arbeitsverzeichnis ist der Ort, an dem Sie gerade arbeiten. Es ist der Ort, an dem Ihre Dateien vorhanden sind. Mit einem Befehl git status können Sie sehen, welche Dateien / Ordner im Arbeitsverzeichnis vorhanden sind.
Im Staging-Bereich (Index) verfolgt und speichert Git alle Änderungen in den Dateien. Die gespeicherten Änderungen werden im .git-Verzeichnis angezeigt. Sie verwenden git add "Dateiname", um die Datei zum Staging-Bereich hinzuzufügen. Und wie zuvor sehen Sie beim Ausführen des Git-Status, welche Dateien im Staging-Bereich vorhanden sind.
Der aktuelle Zweig in Git wird als HEAD bezeichnet. Es zeigt auf das letzte Commit, das im aktuellen Checkout-Zweig stattgefunden hat. Es wird als Zeiger für jede Referenz behandelt. Sobald Sie zu einem anderen Zweig auschecken, wechselt der HEAD auch zum neuen Zweig.
Lassen Sie mich erklären, wie das Zurücksetzen von Git im harten, weichen und gemischten Modus funktioniert. Der Hard-Modus wird verwendet, um zum gezielten Commit zu wechseln, das Arbeitsverzeichnis wird mit Dateien dieses Commits gefüllt und der Staging-Bereich wird zurückgesetzt. Beim Soft-Reset wird nur der Zeiger auf das angegebene 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 Hard zurücksetzen
Der Zweck des Git-Hard-Reset besteht darin, den HEAD auf das angegebene Commit zu verschieben. Es werden alle Commits entfernt, die nach dem angegebenen Commit aufgetreten sind. Dieser Befehl ändert den Festschreibungsverlauf und zeigt auf das angegebene Festschreiben.
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 derzeit nichts zu festschreiben.
$ 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 clean
Jetzt werde ich 3 Dateien erstellen und einige Inhalte hinzufügen.
$ vi file1.txt
$ vi file2.txt
$ vi file3.txt
Fü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.txt
Lassen Sie mich Ihnen vor dem Festschreiben zeigen, dass ich derzeit ein Protokoll mit 3 Festschreibungen in Git habe.
$ git log --oneline
0db602e (HEAD -> master) one more commit
59c86c9 new commit
e2f44fc (origin/master, origin/HEAD) test
Jetzt werde ich mich auf das Repository festlegen.
$ 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.txt
Wenn ich ls-Dateien mache, werden Sie sehen, dass die neuen Dateien hinzugefügt wurden.
$ git ls-files
demo
dummyfile
newfile
file1.txt
file2.txt
file3.txt
Wenn ich den Protokollbefehl in git ausführe, habe ich 4 Festschreibungen, und der HEAD zeigt auf die letzte Festschreibung.
$ git log --oneline
d69950b (HEAD -> master) added 3 files
0db602e one more commit
59c86c9 new commit
e2f44fc (origin/master, origin/HEAD) test
Wenn ich die Datei "file1.txt" manuell lösche und einen Git-Status ausführe, wird die Meldung angezeigt, dass die Änderungen nicht für das Festschreiben 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 werde ich den Hard-Reset-Befehl ausführen.
$ git reset --hard
HEAD is now at d69950b added 3 files
Wenn ich den Status erneut überprüfe, stelle ich fest, dass nichts festgeschrieben werden muss und die von mir gelöschte Datei wieder in das Repository aufgenommen wurde. Der Rollback ist aufgetreten, weil ich nach dem Löschen der Datei kein Commit durchgeführt habe. Nach einem Hard-Reset wurde der vorherige Status wiederhergestellt.
$ 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 clean
Wenn ich das Protokoll von git überprüfe, sieht es so aus.
$ git log
commit d69950b7ea406a97499e07f9b28082db9db0b387 (HEAD -> master)
Author: mrgeek <mrgeek@gmail.com>
Date:
Mon May 17 19:53:31 2020 +0530
added 3 files
commit 0db602e085a4d59cfa9393abac41ff5fd7afcb14
Author: mrgeek <mrgeek@gmail.com>
Date:
Mon May 17 01:04:13 2020 +0530
one more commit
commit 59c86c96a82589bad5ecba7668ad38aa684ab323
Author: mrgeek <mrgeek@gmail.com>
Date:
Mon May 17 00:54:53 2020 +0530
new commit
commit e2f44fca2f8afad8e4d73df6b72111f2f2fd71ad (origin/master, origin/HEAD)
Author: mrgeek <mrgeek@gmail.com>
Date:
Mon May 17 00:16:33 2020 +0530
test
Der Zweck des Hard-Reset besteht darin, auf das angegebene 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 das vorherige Commit zurücksetzen möchte (ein Commit zurück).
$ git reset --hard HEAD^
HEAD is now at 0db602e one more commit
Sie können sehen, dass der Kopfzeiger jetzt von d0b auf 602db69950e geändert wurde.
$ 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 das Commit von d69950b weg und der Kopf zeigt jetzt auf 0db602e SHA.
$ git log
commit 0db602e085a4d59cfa9393abac41ff5fd7afcb14 (HEAD -> master)
Author: mrgeek <mrgeek@gmail.com>
Date:
Mon May 17 01:04:13 2020 +0530
one more commit
commit 59c86c96a82589bad5ecba7668ad38aa684ab323
Author: mrgeek <mrgeek@gmail.com>
Date:
Mon May 17 00:54:53 2020 +0530
new commit
commit e2f44fca2f8afad8e4d73df6b72111f2f2fd71ad (origin/master, origin/HEAD)
Author: mrgeek <mrgeek@gmail.com>
Date:
Mon May 17 00:16:33 2020 +0530
Test
Wenn Sie die ls-Dateien ausführen, sehen Sie, dass sich file1.txt, file2.txt und files3.txt nicht mehr im Repository befinden, da dieses Commit und seine Datei nach dem Hard-Reset entfernt wurden.
$ git ls-files
demo
dummyfile
newfile
Git 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 sie festgeschrieben. Das Git-Protokoll wird wie unten gezeigt angezeigt. Sie können sehen, dass "Soft Reset" mein letztes 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) test
Details zum Festschreiben im Protokoll können mit dem folgenden Befehl angezeigt werden.
$ git log
commit aa400858aab3927e79116941c715749780a59fc9 (HEAD -> master)
Author: mrgeek <mrgeek@gmail.com>
Date:
Mon May 17 21:01:36 2020 +0530
soft reset
commit 0db602e085a4d59cfa9393abac41ff5fd7afcb14
Author: mrgeek <mrgeek@gmail.com>
Date:
Mon May 17 01:04:13 2020 +0530
one more commit
commit 59c86c96a82589bad5ecba7668ad38aa684ab323
Author: mrgeek <mrgeek@gmail.com>
Date:
Mon May 17 00:54:53 2020 +0530
new commit
commit e2f44fca2f8afad8e4d73df6b72111f2f2fd71ad (origin/master, origin/HEAD)
Author: mrgeek <mrgeek@gmail.com>
Date:
Mon May 17 00:16:33 2020 +0530
test
Mit dem Soft-Reset möchte ich jetzt zu einem der älteren Commits mit SHA 0db602e085a4d59cfa9393abac41ff5fd7afcb14 wechseln
Dazu führe ich den folgenden Befehl aus. Sie müssen mehr als 6 Startzeichen von SHA übergeben, die vollständige SHA ist nicht erforderlich.
$ git reset --soft 0db602e085a4
Wenn ich jetzt das Git-Protokoll ausführe, kann ich sehen, dass der HEAD auf das von mir angegebene Commit zurückgesetzt wurde.
$ git log
commit 0db602e085a4d59cfa9393abac41ff5fd7afcb14 (HEAD -> master)
Author: mrgeek <mrgeek@gmail.com>
Date:
Mon May 17 01:04:13 2020 +0530
one more commit
commit 59c86c96a82589bad5ecba7668ad38aa684ab323
Author: mrgeek <mrgeek@gmail.com>
Date:
Mon May 17 00:54:53 2020 +0530
new commit
commit e2f44fca2f8afad8e4d73df6b72111f2f2fd71ad (origin/master, origin/HEAD)
Author: mrgeek <mrgeek@gmail.com>
Date:
Mon May 17 00:16:33 2020 +0530
test
Der Unterschied besteht jedoch darin, dass sich die Dateien des Commits (aa400858aab3927e79116941c715749780a59fc9), zu denen ich 3 Dateien hinzugefügt habe, noch in meinem Arbeitsverzeichnis befinden. Sie wurden nicht gelöscht. Aus diesem Grund sollten Sie einen Soft-Reset anstelle eines Hard-Reset verwenden. Es besteht kein Risiko, dass die Dateien im Soft-Modus verloren gehen.
$ git ls-files
demo
dummyfile
file1.txt
file2.txt
file3.txt
newfile
Git Revert
In Git wird der Befehl zum Zurücksetzen verwendet, um eine Wiederherstellungsoperation auszuführen, dh um einige Änderungen zurückzusetzen. Es ähnelt dem Befehl zum Zurücksetzen, aber der einzige Unterschied besteht darin, dass Sie ein neues 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 Befehl Git revert löscht keine Daten, während der Wiederherstellungsvorgang ausgeführt wird.
Angenommen, ich füge 3 Dateien hinzu und führe eine Git-Commit-Operation für das Revert-Beispiel aus.
$ 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.txt
Das 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) test
Jetzt 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 59c86c9
Dadurch 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: dummyfile
Nachdem 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 erforderlichen Änderungen vorzunehmen, hat revert im Gegensatz zum Zurücksetzen ein weiteres neues Commit durchgeführt. Wenn Sie das Protokoll erneut überprüfen, finden Sie aufgrund des Wiederherstellungsvorgangs ein neues 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-Protokoll enthält den gesamten Verlauf der Commits. Wenn Sie die Commits aus dem Verlauf entfernen möchten, ist das Zurücksetzen keine gute Wahl. Wenn Sie jedoch die Festschreibungsänderungen im Verlauf beibehalten möchten, ist das Zurücksetzen der geeignete Befehl anstelle des Zurücksetzens.
Git Rebase
In Git ist Rebase die Methode zum Verschieben oder Kombinieren von Commits eines Zweigs über einen anderen Zweig. Als Entwickler würde ich meine Funktionen in einem realen Szenario nicht in der Hauptniederlassung erstellen. Ich würde an meinem eigenen Zweig arbeiten (einem 'Feature-Zweig'), und wenn ich einige Commits in meinem Feature-Zweig mit dem hinzugefügten Feature habe, möchte ich ihn dann in den Hauptzweig verschieben.
Rebase kann manchmal etwas verwirrend sein, da es einer Zusammenführung sehr ähnlich ist. Das Ziel des Zusammenführens und erneuten Basierens besteht darin, die Commits aus meinem Feature-Zweig zu übernehmen und sie einem Hauptzweig oder einem anderen Zweig zuzuweisen. Bedenken Sie, ich habe eine Grafik, die so 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 Feature-Zweigen arbeiten und mehrere Änderungen zusammengeführt haben. Es wird verwirrend zu verfolgen.
Hier wird Rebase also helfen. Dieses Mal werde ich anstelle einer Git-Zusammenführung eine Rebase durchführen, bei der ich meine beiden Feature-Branch-Commits in den Master-Branch verschieben möchte. Bei einer Rebase werden alle meine Commits aus dem Feature-Zweig übernommen und über die Commits des Master-Zweigs verschoben. Hinter den Kulissen dupliziert git also die Commits des Feature-Zweigs im Master-Zweig.
Mit diesem Ansatz erhalten Sie ein sauberes, geradliniges Diagramm mit allen Commits in einer Reihe.
Es macht es einfach zu verfolgen, welche Commits wohin gingen. Sie können sich vorstellen, wenn Sie in einem Team mit vielen Entwicklern sind, sind alle Commits immer noch in einer Reihe. Es ist also wirklich einfach zu folgen, selbst wenn viele Leute gleichzeitig an demselben Projekt arbeiten.
Lassen Sie mich Ihnen dies praktisch zeigen.
So sieht meine Hauptniederlassung derzeit 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) test
Ich werde den folgenden Befehl ausführen, um einen neuen Zweig namens feature zu erstellen und zu diesem zu wechseln, und dieser Zweig 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, werden nur 2 Commits vom Master (Hauptzeile) gesendet.
(feature)
$ git log --oneline
59c86c9 (HEAD -> feature) new commit
e2f44fc (origin/master, origin/HEAD) test
Ich werde Feature 1 erstellen und es dem Feature-Zweig ü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.txt
Ich werde ein weiteres Feature, dh Feature 2, im Feature-Zweig erstellen und 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.txt
Wenn Sie nun das Protokoll des Feature-Zweigs überprüfen, hat 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) test
Jetzt möchte ich diese beiden neuen Funktionen zum Hauptzweig hinzufügen. Dafür werde ich den Befehl rebase verwenden. Aus dem Feature-Zweig werde ich mich auf den Master-Zweig stützen. Dadurch wird mein Feature-Zweig gegen die neuesten Änderungen neu verankert.
(feature)
$ git rebase master
Successfully rebased and updated refs/heads/feature.
Jetzt werde ich die Hauptniederlassung auschecken.
(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 können Sie den Hauptzweig gegen meinen Feature-Zweig neu starten. Dadurch werden diese beiden neuen Commits in meinem Feature-Zweig übernommen und über meinem Master-Zweig wiedergegeben.
(master)
$ git rebase feature
Successfully rebased and updated refs/heads/master.
Wenn ich jetzt das Protokoll im Hauptzweig überprüfe, kann ich sehen, dass die beiden Commits meines Feature-Zweigs erfolgreich zu meinem Hauptzweig 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) test
Hier ging es darum, Befehle in Git zurückzusetzen, zurückzusetzen und neu zu starten.
Fazit
Hier ging es darum, Befehle zurückzusetzen, zurückzusetzen und neu zu starten Git. Ich hoffe, diese Schritt-für-Schritt-Anleitung war hilfreich. Jetzt wissen Sie, wie Sie mit Ihren Commits nach Bedarf mit den im Artikel genannten Befehlen herumspielen können.