Wie kann ich ein Git-Repository auf ein vorheriges Commit zurücksetzen?

7630

Wie kann ich von meinem aktuellen Status zu einem Snapshot zurückkehren, der bei einem bestimmten Commit erstellt wurde?

Wenn ich das tue git log, bekomme ich die folgende Ausgabe:

$ git log
commit a867b4af366350be2e7c21b8de9cc6504678a61b`
Author: Me <[email protected]>
Date:   Thu Nov 4 18:59:41 2010 -0400

blah blah blah...

commit 25eee4caef46ae64aa08e8ab3f988bc917ee1ce4
Author: Me <[email protected]>
Date:   Thu Nov 4 05:13:39 2010 -0400

more blah blah blah...

commit 0766c053c0ea2035e90f504928f8df3c9363b8bd
Author: Me <[email protected]>
Date:   Thu Nov 4 00:55:06 2010 -0400

And yet more blah blah...

commit 0d1d7fc32e5a947fbd92ee598033d85bfc445a50
Author: Me <[email protected]>
Date:   Wed Nov 3 23:56:08 2010 -0400

Yep, more blah blah.

Wie kann ich ab dem 3. November zum Commit zurückkehren, dh zum Commit 0d1d7fc?

Verrückter Serbe
quelle
116
Hier ist ein sehr klarer und gründlicher Beitrag über das Rückgängigmachen von Dingen in Git, direkt von Github.
Nobita
3
Verwandte: Rollback zu einem alten Git-Commit in einem öffentlichen Repo . Beachten Sie, dass diese Frage eine Einschränkung hinzufügt, dass das Repo öffentlich ist.
58
Ich liebe Git, aber die Tatsache, dass es 35 Antworten auf etwas gibt, das unglaublich einfach sein sollte, wirft ein großes Problem mit Git auf. Oder sind es die Dokumente?
Der Muffin-Mann
2
Wie ist die Sprache "Falle" bei der Verwendung des Wortes , um als umgangssprachliche Bedeutung zum Zurücksetzen zurückzukehren, nicht einmal hier angesprochen? 6594 Upvotes bisher und keine Bearbeitung auf diese Weise, um den Unterschied zu betonen? Es wäre nicht verwirrender, hier auf "Speichern einer Datei" mit dem Ausdruck "
Festschreiben

Antworten:

9728

Dies hängt stark davon ab, was Sie unter "Zurücksetzen" verstehen.

Wechseln Sie vorübergehend zu einem anderen Commit

Wenn Sie vorübergehend zurückkehren möchten, herumalbern und dann wieder dorthin zurückkehren möchten, wo Sie sich befinden, müssen Sie nur das gewünschte Commit überprüfen:

# This will detach your HEAD, that is, leave you with no branch checked out:
git checkout 0d1d7fc32

Oder wenn Sie Commits machen möchten, während Sie dort sind, machen Sie einen neuen Zweig, während Sie gerade dabei sind:

git checkout -b old-state 0d1d7fc32

Um dorthin zurückzukehren, wo Sie waren, sehen Sie sich einfach die Filiale an, in der Sie sich wieder befanden. (Wenn Sie wie immer beim Wechseln von Zweigen Änderungen vorgenommen haben, müssen Sie diese entsprechend behandeln. Sie können sie zurücksetzen, um sie wegzuwerfen. Sie können sie verstauen, auschecken und Pop aufbewahren, um sie mitzunehmen sie zu einer Filiale dort, wenn Sie eine Filiale dort wollen.)

Unveröffentlichte Commits hart löschen

Wenn Sie andererseits wirklich alles loswerden möchten, was Sie seitdem getan haben, gibt es zwei Möglichkeiten. Erstens, wenn Sie keine dieser Commits veröffentlicht haben, setzen Sie sie einfach zurück:

# This will destroy any local modifications.
# Don't do it if you have uncommitted work you want to keep.
git reset --hard 0d1d7fc32

# Alternatively, if there's work to keep:
git stash
git reset --hard 0d1d7fc32
git stash pop
# This saves the modifications, then reapplies that patch after resetting.
# You could get merge conflicts, if you've modified things which were
# changed since the commit you reset to.

Wenn Sie es vermasseln, haben Sie Ihre lokalen Änderungen bereits verworfen, aber Sie können zumindest wieder dorthin zurückkehren, wo Sie zuvor waren, indem Sie sie erneut zurücksetzen.

Veröffentlichen Sie veröffentlichte Commits mit neuen Commits

Wenn Sie die Arbeit jedoch veröffentlicht haben, möchten Sie den Zweig wahrscheinlich nicht zurücksetzen, da dadurch der Verlauf effektiv neu geschrieben wird. In diesem Fall könnten Sie die Commits tatsächlich zurücksetzen. Mit Git hat das Zurücksetzen eine ganz bestimmte Bedeutung: Erstellen Sie ein Commit mit dem umgekehrten Patch, um es aufzuheben. Auf diese Weise schreiben Sie keine Historie neu.

# This will create three separate revert commits:
git revert a867b4af 25eee4ca 0766c053

# It also takes ranges. This will revert the last two commits:
git revert HEAD~2..HEAD

#Similarly, you can revert a range of commits using commit hashes:
git revert a867b4af..0766c053 

# Reverting a merge commit
git revert -m 1 <merge_commit_sha>

# To get just one, you could use `rebase -i` to squash them afterwards
# Or, you could do it manually (be sure to do this at top level of the repo)
# get your index and work tree into the desired state, without changing HEAD:
git checkout 0d1d7fc32 .

# Then commit. Be sure and write a good message describing what you just did
git commit

Die git-revertManpage behandelt tatsächlich viel davon in ihrer Beschreibung. Ein weiterer nützlicher Link ist dieser Abschnitt von git-scm.com, in dem git-revert behandelt wird .

Wenn Sie entscheiden, dass Sie doch nicht zurücksetzen möchten, können Sie das Zurücksetzen (wie hier beschrieben) zurücksetzen oder vor dem Zurücksetzen auf zurücksetzen (siehe vorherigen Abschnitt).

Diese Antwort kann auch in diesem Fall hilfreich sein:
Wie verschiebe ich HEAD zurück an einen vorherigen Speicherort? (Abgenommener Kopf)

Cascabel
quelle
118
@ Rod Kommentar auf git revert HEAD~3als die beste wat um wieder zurück 3Commits ist am wichtigen Konvention.
New Alexandria
19
Könnten Sie die ganze Zahl schreiben? wie:git reset --hard 0d1d7fc32e5a947fbd92ee598033d85bfc445a50
Spoeken
16
@MathiasMadsenStav Ja, Sie können natürlich Commits für den vollständigen SHA1 angeben. Ich habe abgekürzte Hashes verwendet, um die Antwort besser lesbar zu machen, und Sie verwenden sie auch, wenn Sie tippen. Wenn Sie kopieren und einfügen, verwenden Sie auf jeden Fall den vollständigen Hash. Siehe Angeben von Revisionen im Menschen git rev-Parsing für eine vollständige Beschreibung, wie Sie Commits benennen.
Cascabel
59
Sie können verwenden git revert --no-commit hash1 hash2 ...und danach einfach jede einzelne Wiederherstellung in einem Commit git commit -m "Message"
festschreiben
6
Was bedeutet "veröffentlichen" in diesem Zusammenhang?
Howiecamp
1849

Viele komplizierte und gefährliche Antworten hier, aber es ist eigentlich einfach:

git revert --no-commit 0766c053..HEAD
git commit

Dadurch wird alles vom HEAD zurück zum Commit-Hash zurückgesetzt, was bedeutet, dass dieser Commit-Status im Arbeitsbaum neu erstellt wird, als ob jedes Commit seitdem zurückgeführt worden wäre. Sie können dann den aktuellen Baum festschreiben, und es wird ein brandneues Festschreiben erstellt, das im Wesentlichen dem Festschreiben entspricht, auf das Sie "zurückgesetzt" haben.

(Mit dem --no-commitFlag kann git alle Commits auf einmal zurücksetzen. Andernfalls werden Sie für jedes Commit im Bereich zur Eingabe einer Nachricht aufgefordert, die Ihren Verlauf mit unnötigen neuen Commits übersät.)

Dies ist eine sichere und einfache Möglichkeit, einen Rollback auf einen früheren Status durchzuführen . Da keine Historie zerstört wird, kann sie für bereits veröffentlichte Commits verwendet werden.

Yarin
quelle
23
Wenn Sie wirklich einzelne Commits haben möchten (anstatt alles mit einem großen Commit zurückzusetzen), können Sie --no-editstattdessen übergeben --no-commit, damit Sie nicht für jede Umkehrung eine Commit-Nachricht bearbeiten müssen.
87
Wenn einer der Commits zwischen 0766c053..HEAD eine Zusammenführung ist, wird ein Fehler angezeigt (dies wird mit no -m angegeben). Dies kann denjenigen helfen, die auf Folgendes
timhc22
7
Um die Unterschiede zu sehen, bevor Sie festschreiben, verwenden Sie git diff --cached.
John Erck
21
$ git revert --no-commit 53742ae..HEADkehrt zurückfatal: empty commit set passed
Alex G
10
@AlexG Das liegt daran, dass Sie den Hash vor dem eingeben müssen, zu dem Sie zurückkehren möchten. In meinem Fall waren Hashes wie 81bcc9e HEAD{0}; e475924 HEAD{1}, ...git reflog81bcc9egit revert e475924..HEAD
folgt
1611

Rogue Coder?

Sie arbeiten alleine und möchten nur, dass es funktioniert? Befolgen Sie diese Anweisungen unten, sie haben jahrelang zuverlässig für mich und viele andere gearbeitet.

Mit anderen arbeiten? Git ist kompliziert. Lesen Sie die Kommentare unter dieser Antwort, bevor Sie etwas Unüberlegtes tun.

Zurücksetzen der Arbeitskopie auf das letzte Commit

So kehren Sie zu einem vorherigen Commit zurück und ignorieren alle Änderungen:

git reset --hard HEAD

Dabei ist HEAD das letzte Commit in Ihrer aktuellen Niederlassung

Zurücksetzen der Arbeitskopie auf ein älteres Commit

So kehren Sie zu einem Commit zurück, das älter als das letzte Commit ist:

# Resets index to former commit; replace '56e05fced' with your commit code
git reset 56e05fced 

# Moves pointer back to previous HEAD
git reset --soft HEAD@{1}

git commit -m "Revert to 56e05fced"

# Updates working copy to reflect the new commit
git reset --hard

Credits gehen an eine ähnliche Stack Overflow-Frage: Zurück zu einem Commit durch einen SHA-Hash in Git? .

boulder_ruby
quelle
33
Ich habe das getan, aber dann konnte ich mich nicht festschreiben und in das Remote-Repository übertragen. Ich möchte, dass ein bestimmtes älteres Commit HEAD wird ...
Lennon
7
Dies bedeutet, dass Sie bereits die Commits eingegeben haben, die Sie zurücksetzen möchten. Es kann viele Probleme für Leute verursachen, die Ihren Code ausgecheckt und daran gearbeitet haben. Da sie Ihr Commit nicht reibungslos auf ihr anwenden können. In diesem Fall ist es besser, einen Git-Revert durchzuführen. Wenn Sie der einzige sind, der das Repo verwendet. Mach einen Git Push -f (aber
überlege es dir
6
Ich möchte nur darauf hinweisen, dass Sie alternativ für die Soft-Reset-Lösung, anstatt zuerst einen gemischten Reset und zuletzt einen Hard-Reset durchzuführen, den Hard-Reset zuerst wie folgt durchführen können : git reset --hard 56e05fc; git reset --soft HEAD@{1}; git commit.
5
@nuton linus pauling sich selbst, der schöpfer von git, kritisierte es als zu kompliziert. Er ist bekannt, dass er "schockiert" war. Git wurde aufgrund seiner Komplexität so beliebt
boulder_ruby
5
@boulder_ruby Ich denke du meintest Linus Torvalds war der Schöpfer von git. Aber ich denke, Linus Pauling würde wahrscheinlich zustimmen, dass Git kompliziert ist.
Suncat2000
215

Die beste Option für mich und wahrscheinlich für andere ist die Option zum Zurücksetzen von Git:

git reset --hard <commidId> && git clean -f

Dies war die beste Option für mich! Es ist einfach, schnell und effektiv!


** Hinweis: ** Wie in den Kommentaren erwähnt, tun Sie dies nicht, wenn Sie Ihre Filiale mit anderen Personen teilen, die Kopien der alten Commits haben

Auch aus den Kommentaren, wenn Sie eine weniger "ballzy" Methode wollten, könnten Sie verwenden

git clean -i
Pogrindis
quelle
37
Obligatorische Warnung: Tun Sie dies nicht, wenn Sie Ihren Zweig mit anderen Personen teilen, die Kopien der alten Commits haben, da sie bei Verwendung eines solchen Hard-Reset gezwungen sind, ihre Arbeit mit dem neu zurückgesetzten Zweig neu zu synchronisieren. In dieser Antwort finden Sie eine Lösung, in der ausführlich erläutert wird, wie Sie Commits sicher zurücksetzen können, ohne die Arbeit mit einem Hard-Reset zu verlieren .
7
Ich bin der Warnung von @ Cupcake gefolgt ... sei mir der Konsequenzen sehr bewusst. Beachten Sie jedoch, dass , wenn Ihr Bedarf wirklich ist diese Commits aus der Geschichte verschwinden zu lassen für immer, diese Reset + saubere Methode wird es tun, und Sie werden für brauchen Kraft schieben Sie Ihre modifizierte Zweige zu irgendwelchen und allen Fernbedienungen zurück.
Ashnazg
5
git clean -f GEFAHR GEFAHR
Tisch
2
Dadurch wird der Kopf meiner lokalen Kopie auf das gewünschte Commit gesetzt. Aber dann kann ich keine Änderungen vornehmen, da sie sich hinter der Fernbedienung befinden. Und wenn ich von der Fernbedienung ziehe, landet sie wieder dort, wo sie zuletzt im Remote-Zweig festgeschrieben wurde. Wie lösche ich (von überall) mehrere Commits auf meiner lokalen Kopie, die gepusht wurden, vollständig aus?
Ade
2
@Ade .. Sie könnten die git push -fFlagge verwenden .. Aber seien Sie vorsichtig, es wird die Fernbedienung überschreiben .. Stellen Sie sicher, dass Sie wissen, was Sie tun möchten ...
Pogrindis
176

Bevor wir antworten, fügen wir einige Hintergrundinformationen hinzu und erklären, was dies HEADist.

First of all what is HEAD?

HEADist einfach ein Verweis auf das aktuelle Commit (aktuell) in der aktuellen Verzweigung. Es kann immer nur eine einzige HEADgeben (ausgenommengit worktree ).

Der Inhalt von HEADwird im Inneren gespeichert .git/HEADund enthält die 40 Bytes SHA-1 des aktuellen Commits.


detached HEAD

Wenn Sie sich nicht im letzten Commit befinden, bedeutet dies, dass HEADauf ein vorheriges Commit im Verlauf verwiesen wird detached HEAD.

Geben Sie hier die Bildbeschreibung ein

In der Befehlszeile sieht es folgendermaßen aus: SHA-1 anstelle des Zweignamens, da der HEADnicht auf die Spitze des aktuellen Zweigs zeigt:

Geben Sie hier die Bildbeschreibung ein


Einige Optionen zur Wiederherstellung nach einem abgetrennten KOPF:


git checkout

git checkout <commit_id>
git checkout -b <new branch> <commit_id>
git checkout HEAD~X // x is the number of commits t go back

Dadurch wird ein neuer Zweig ausgecheckt, der auf das gewünschte Commit verweist. Dieser Befehl checkt zu einem bestimmten Commit aus.

An diesem Punkt können Sie einen Zweig erstellen und ab diesem Punkt mit der Arbeit beginnen:

# Checkout a given commit.
# Doing so will result in a `detached HEAD` which mean that the `HEAD`
# is not pointing to the latest so you will need to checkout branch
# in order to be able to update the code.
git checkout <commit-id>

# Create a new branch forked to the given commit
git checkout -b <branch name>

git reflog

Sie können das auch immer verwenden reflog. git reflogzeigt jede Änderung an, die das aktualisiert hat, HEADund das Auschecken des gewünschten Reflog-Eintrags setzt HEADdiesen Commit zurück.

Jedes Mal, wenn der KOPF geändert wird, wird ein neuer Eintrag in der reflog

git reflog
git checkout HEAD@{...}

Dadurch kehren Sie zu Ihrem gewünschten Commit zurück

Geben Sie hier die Bildbeschreibung ein


git reset HEAD --hard <commit_id>

Bewegen Sie Ihren Kopf zurück zum gewünschten Commit.

# This will destroy any local modifications.
# Don't do it if you have uncommitted work you want to keep.
git reset --hard 0d1d7fc32

# Alternatively, if there's work to keep:
git stash
git reset --hard 0d1d7fc32
git stash pop
# This saves the modifications, then reapplies that patch after resetting.
# You could get merge conflicts, if you've modified things which were
# changed since the commit you reset to.
  • Hinweis: ( Seit Git 2.7 ) können Sie auch das verwenden git rebase --no-autostash.

Dieses Schema zeigt, welcher Befehl was tut. Wie Sie dort sehen können, reset && checkoutändern Sie die HEAD.

Geben Sie hier die Bildbeschreibung ein

CodeWizard
quelle
6
Ausgezeichneter Hinweis darauf git reflog, genau das brauchte ich
smac89
4
Autsch! Das alles scheint furchtbar kompliziert zu sein ... gibt es nicht einen einfachen Befehl, der Sie nur einen Schritt zurück in den Prozess bringt? Möchten Sie von Version 1.1 in Ihrem Projekt zurück zu Version 1.0 wechseln? Ich würde so etwas wie erwarten: git
stepback_one_commit
Es gibt: git reset HEAD^--hard`
CodeWizard
3
@Kokodoko Ja, es ist schrecklich kompliziert ... und ein perfektes Beispiel dafür, wie wenig Rücksicht Experten auf Leute haben, die gerade erst anfangen. Bitte beziehen Sie sich hier auf meine Antwort und auch auf das Buch, das ich darin empfehle. Git ist NICHT etwas, das man einfach intuitiv lernen kann. Und ich kann absolut sicher sein, dass CodeWizard dies nicht getan hat.
Mike Nagetier
145

Wenn Sie die Festschreibung aufheben, die letzte Festschreibungsnachricht löschen und die geänderten Dateien wieder in die Staging-Funktion versetzen möchten, verwenden Sie den folgenden Befehl:

git reset --soft HEAD~1
  • --soft gibt an, dass die nicht festgeschriebenen Dateien als entgegengesetzte Arbeitsdateien beibehalten werden sollen --hard die sie verwerfen würden.
  • HEAD~1ist das letzte Commit. Wenn Sie 3 Commits zurücksetzen möchten, können Sie diese verwenden HEAD~3. Wenn Sie auf eine bestimmte Revisionsnummer zurücksetzen möchten, können Sie dies auch mithilfe des SHA-Hashs tun.

Dies ist ein äußerst nützlicher Befehl in Situationen, in denen Sie das Falsche begangen haben und das letzte Festschreiben rückgängig machen möchten.

Quelle: http://nakkaya.com/2009/09/24/git-delete-last-commit/

Stephen Ostermiller
quelle
3
Dies ist weich und sanft: risikofrei, wenn Sie Ihre Arbeit nicht vorangetrieben haben
nilsM
124

Sie können dies mit den folgenden zwei Befehlen tun:

git reset --hard [previous Commit SHA id here]
git push origin [branch Name] -f

Es wird Ihr vorheriges Git-Commit entfernen.

Wenn Sie Ihre Änderungen beibehalten möchten, können Sie auch Folgendes verwenden:

git reset --soft [previous Commit SHA id here]

Dann werden Ihre Änderungen gespeichert.

kiran boghra
quelle
2
Ich habe ein halbes Dutzend Antworten in diesem Beitrag versucht, bis ich zu diesem kam. Bei all den anderen gab mir meine Git-Konfiguration immer wieder einen Fehler, als ich versuchte zu pushen. Diese Antwort hat funktioniert. Vielen Dank!
Gene Bo
Ein Detail für mich war, dass ich die Unterschiede verloren habe. Ich wollte behalten, um zu sehen, was ich in dem Commit getan habe, das nicht funktioniert hat. Also würde ich das nächste Mal nur diese Daten speichern, bevor ich diesen Rücksetzbefehl erteile
Gene Bo
1
Dies war die einzige Möglichkeit für mich, eine fehlerhafte Zusammenführung rückgängig zu machen. In diesem Fall funktionierte das Zurücksetzen nicht. Vielen Dank!
Dave Cole
Beste Antwort. Vielen Dank
Imran Pollob
Beste Antwort, danke.
user1394
114

Ich habe viele Möglichkeiten ausprobiert, um lokale Änderungen in Git rückgängig zu machen, und es scheint, dass dies am besten funktioniert, wenn Sie nur auf den neuesten Festschreibungsstatus zurückgreifen möchten.

git add . && git checkout master -f

Kurze Beschreibung:

  • Es werden KEINE Commits erstellt git revert.
  • Es wird Ihren KOPF NICHT wie gewohnt abnehmen git checkout <commithashcode>.
  • Es überschreibt alle Ihre lokalen Änderungen und löscht alle hinzugefügten Dateien seit dem letzten Commit in der Verzweigung.
  • Es funktioniert nur mit Zweigstellennamen, sodass Sie auf diese Weise nur zum neuesten Commit in der Zweigstelle zurückkehren können.

Ich habe einen viel bequemeren und einfacheren Weg gefunden, um die obigen Ergebnisse zu erzielen:

git add . && git reset --hard HEAD

Dabei zeigt HEAD auf das letzte Commit in Ihrer aktuellen Niederlassung.

Es ist der gleiche Code-Code wie von boulder_ruby vorgeschlagen, aber ich habe git add .zuvor hinzugefügt git reset --hard HEAD, um alle neuen Dateien zu löschen, die seit dem letzten Commit erstellt wurden, da dies das ist, was die meisten Leute erwarten, wenn ich zum letzten Commit zurückkehre.

Roman Minenok
quelle
83

OK, es ist ganz einfach, zu einem früheren Commit in Git zurückzukehren ...

Zurückkehren, ohne die Änderungen beizubehalten :

git reset --hard <commit>

Kehren Sie zurück, indem Sie die Änderungen beibehalten :

git reset --soft <commit>

Erläuterung: usinggit reset können Sie auf einen bestimmten Status zurücksetzen. Es ist üblich, es mit einem Commit-Hash zu verwenden, wie Sie oben sehen.

Aber wie Sie sehen, besteht der Unterschied darin, dass die beiden Flags verwendet werden --softund --hardstandardmäßig git resetdas --softFlag verwendet wird. Es wird jedoch empfohlen, immer das Flag zu verwenden. Ich erkläre jedes Flag:


--Sanft

Das erläuterte Standardflag, das nicht angegeben werden muss, ändert den Arbeitsbaum nicht, fügt jedoch alle geänderten Dateien hinzu, die zum Festschreiben bereit sind, sodass Sie zum Festschreibungsstatus zurückkehren, bei dem Änderungen an Dateien nicht mehr bereitgestellt werden.


--schwer

Sei vorsichtig mit dieser Flagge. Es setzt den Arbeitsbaum und alle Änderungen an den verfolgten Dateien zurück und alles wird weg sein!


Ich habe auch das Bild unten erstellt, das in einem realen Leben mit Git passieren kann:

Git auf ein Commit zurückgesetzt

Alireza
quelle
Der Standardwert git resetist git reset --mixednicht git reset --soft. Bitte überprüfen Sie, was der Unterschied zwischen git reset --mixed, --soft und --hard ist. und was macht "git reset" im Klartext?
Fabio sagt Reinstate Monica
70

Angenommen, Sie sprechen über Master und auf dem jeweiligen Zweig (das heißt, dies könnte jeder Arbeitszweig sein, mit dem Sie sich befassen):

# Reset local master branch to November 3rd commit ID
git reset --hard 0d1d7fc32e5a947fbd92ee598033d85bfc445a50

# Reset remote master branch to November 3rd commit ID
git push -f origin 0d1d7fc32e5a947fbd92ee598033d85bfc445a50:master

Ich habe die Antwort in einem Blog-Beitrag gefunden (existiert jetzt nicht mehr)

Beachten Sie, dass dies das Zurücksetzen und Erzwingen der Änderung an der Fernbedienung ist. Wenn also andere Mitglieder Ihres Teams bereits Git gezogen haben, verursachen Sie Probleme für sie. Sie zerstören die Änderungshistorie, was ein wichtiger Grund ist, warum Menschen Git überhaupt verwenden.

Verwenden Sie lieber "Zurücksetzen" (siehe andere Antworten) als "Zurücksetzen". Wenn Sie ein Ein-Mann-Team sind, spielt es wahrscheinlich keine Rolle.

Markreyes
quelle
6
Wie unterscheidet sich diese Antwort von den unzähligen anderen?
Matsmath
Das ist bedauerlich. Ich habe dem Blogger eine E-Mail geschickt - hoffentlich hat er es noch!
Markreyes
2
Die Push-Syntax fehlt in den meisten anderen Vorschlägen zur Behebung dieses Problems. Hat super funktioniert.
jpa57
61

Angenommen, Sie haben die folgenden Commits in einer Textdatei mit dem Namen ~/commits-to-revert.txt(ich habe git log --pretty=onelinesie verwendet)

fe60adeba6436ed8f4cc5f5c0b20df7ac9d93219
0c27ecfdab3cbb08a448659aa61764ad80533a1b
f85007f35a23a7f29fa14b3b47c8b2ef3803d542
e9ec660ba9c06317888f901e3a5ad833d4963283
6a80768d44ccc2107ce410c4e28c7147b382cd8f
9cf6c21f5adfac3732c76c1194bbe6a330fb83e3
fff2336bf8690fbfb2b4890a96549dc58bf548a5
1f7082f3f52880cb49bc37c40531fc478823b4f5
e9b317d36a9d1db88bd34831a32de327244df36a
f6ea0e7208cf22fba17952fb162a01afb26de806
137a681351037a2204f088a8d8f0db6e1f9179ca

Erstellen Sie ein Bash- Shell-Skript, um jedes von ihnen zurückzusetzen:

#!/bin/bash
cd /path/to/working/copy
for i in `cat ~/commits-to-revert.txt`
do
    git revert $i --no-commit
done

Dadurch wird alles auf den vorherigen Status zurückgesetzt, einschließlich der Erstellung und Löschung von Dateien und Verzeichnissen. Übertragen Sie es in Ihren Zweig, und Sie behalten den Verlauf bei, aber Sie haben ihn auf dieselbe Dateistruktur zurückgesetzt. Warum Git kein hat, git revert --to <hash>ist mir ein Rätsel.

Lance Caraccioli
quelle
41
Sie könnten eine tun git revert HEAD~3, um die letzten 3 Commits zu entfernen
Rod
25
@ Rod - Nein, das stimmt nicht. Dieser Befehl setzt das Commit zurück, das der dritte Großelternteil von HEAD ist (nicht die letzten drei Commits).
Kflorence
1
@kflorence Ok danke für die Info. Würde git revert -n master~3..master~1funktionieren? (Wie aus kernel.org/pub/software/scm/git/docs/git-revert.html ersichtlich )
Rod
3
@ Rod - Das klingt richtig, ist sicher eine hässliche Syntax, nicht wahr? Ich habe immer festgestellt, dass ich das Commit, zu dem ich "zurückkehren" möchte, überprüfen und dann intuitiver festschreiben möchte.
Kflorence
7
Es gibt jetzt einen viel einfacheren Weg, dies zu tun als mit einem Skript wie diesem. Verwenden Sie es einfach git revert --no-commit <start>..<end>, da es git reverteinen Commit-Bereich in neuen (oder allen?) Versionen von Git akzeptiert. Beachten Sie, dass der Beginn des Bereichs nicht in der Wiederherstellung enthalten ist.
58

Zusätzliche Alternativen zu Jefromis Lösungen

Jefromis Lösungen sind definitiv die besten, und Sie sollten sie auf jeden Fall verwenden. Der Vollständigkeit halber wollte ich jedoch auch diese anderen alternativen Lösungen zeigen, die auch zum Zurücksetzen eines Commits verwendet werden können (in dem Sinne, dass Sie ein neues Commit erstellen, das Änderungen im vorherigen Commit rückgängig macht , genau wie dies der git revertFall ist).

Um klar zu sein, diese Alternativen sind nicht der beste Weg, um Commits zurückzusetzen , wie es Jefromis Lösungen sind , aber ich möchte nur darauf hinweisen, dass Sie diese anderen Methoden auch verwenden können, um dasselbe zu erreichen wie git revert.

Alternative 1: Hard- und Soft-Resets

Dies ist eine sehr leicht modifizierte Version von Charles Baileys Lösung, um zu einem Commit durch einen SHA-Hash in Git zurückzukehren. ::

# Reset the index to the desired commit
git reset --hard <commit>

# Move the branch pointer back to the previous HEAD
git reset --soft HEAD@{1}

# Commit the changes
git commit -m "Revert to <commit>"

Dies funktioniert im Wesentlichen unter Verwendung der Tatsache, dass Soft-Resets den Status des vorherigen Commits im Index- / Staging-Bereich belassen, den Sie dann festschreiben können.

Alternative 2: Löschen Sie den aktuellen Baum und ersetzen Sie ihn durch den neuen

Diese Lösung stammt aus der Lösung von svick zum Auschecken eines alten Commits und zum Erstellen eines neuen Commits :

git rm -r .
git checkout <commit> .
git commit

Ähnlich wie bei Alternative 1 wird der Status <commit>in der aktuellen Arbeitskopie reproduziert . Dies ist zuerst erforderlich, git rmda git checkoutDateien, die seitdem hinzugefügt wurden, nicht entfernt werden <commit>.

user456814
quelle
Zu Alternative 1 eine kurze Frage: Auf diese Weise verlieren wir nicht zwischen den Commits, oder?
Bogac
2
@Bogac - Die Punkte geben einen Dateipfad an, in diesem Fall das aktuelle Verzeichnis. Es wird also davon ausgegangen, dass Sie ihn vom Stammverzeichnis Ihrer Arbeitskopie aus ausführen.
Tom
Die Warnung wird in der Antwort mehrmals wiederholt, aber könnte jemand hinzufügen, warum dies nicht der beste Weg ist - im Vergleich zu etwas wie git revert HEAD~2..HEADder verknüpften Lösung von @ Cascabel (@ Jefromi). Ich sehe das Problem nicht.
Joshua Goldberg
55

Hier ist eine viel einfachere Möglichkeit, zu einem vorherigen Commit zurückzukehren (und es in einem nicht festgeschriebenen Zustand zu haben, um damit zu tun, was immer Sie möchten):

git reset HEAD~1

Also, keine Notwendigkeit für Commit-IDs und so weiter :)

Paul Walczewski
quelle
hat nicht funktioniert, ein Git-Pull danach ergibt: Fehler: Ihre lokalen Änderungen an den folgenden Dateien würden durch Zusammenführung überschrieben:
Malhal
1
@malhal Das liegt daran, dass Sie nicht festgeschriebene Änderungen vorgenommen haben. Verstecken / zurücksetzen und dann funktioniert es ohne diesen Fehler.
Paul Walczewski
39

Es gibt einen Befehl (nicht Teil des Git-Kerns, aber im git-extras- Paket enthalten) speziell zum Zurücksetzen und Bereitstellen alter Commits:

git back

Laut Manpage kann es auch als solches verwendet werden:

# Remove the latest three commits
git back 3
Schattenmann
quelle
38

Der beste Weg ist:

git reset --hard <commidId> && git push --force

Dadurch wird der Zweig auf das bestimmte Commit zurückgesetzt und anschließend der Remote-Server mit denselben Commits hochgeladen, die Sie in local haben (dadurch werden die Befehle nach diesem bestimmten Commit vollständig eliminiert).

Seien Sie vorsichtig, wenn das --forceFlag alle nachfolgenden Commits nach dem ausgewählten Commit entfernt, ohne die Option, sie wiederherzustellen.

david.t_92
quelle
3
arbeitete wie Charme!
Gaurav Gupta
Ich habe abgelehnt, weil ich nicht sehe, wie Ihre Antwort neue Informationen enthält, die nicht bereits in beispielsweise stackoverflow.com/a/37145089/1723886 , stackoverflow.com/a/27438379/1723886 oder stackoverflow.com/a/48756719/1723886 enthalten sind . Tatsächlich erwähnen die meisten Commits bereits das Zurücksetzen von Git --hard, und viele weitere erwähnen die Verwendung von --force oder -f zum Drücken.
Alex Telon
Es erledigt die Arbeit mit nur einem Befehl, klar und einfach. Sie können meine Antwort ablehnen, wenn Sie sie nicht mögen.
david.t_92
1
Eine weitere Option, die Sie für die Zukunft in Betracht ziehen sollten, besteht darin, eine Bearbeitung einer früheren Antwort vorzuschlagen oder einen Kommentar hinzuzufügen, der besagt, dass dies beispielsweise auch mit && in einer Zeile erfolgen kann. Auf diese Weise kann jeder die verbesserte Antwort an einem Ort sehen.
Alex Telon
36

Wenn Sie nach all den Änderungen alle diese Befehle drücken, müssen Sie möglicherweise Folgendes verwenden:

git push -f ...

Und nicht nur git push.

sivi
quelle
15
Obligatorische Warnung: Tun Sie dies nicht, wenn Sie Ihren Zweig mit anderen Personen teilen, die Kopien der alten Commits haben, da sie durch einen solchen Force-Push gezwungen sind, ihre Arbeit neu zu synchronisieren. In dieser Antwort finden Sie eine Lösung, in der ausführlich erläutert wird, wie Sie Commits sicher zurücksetzen können, ohne die Arbeit mit einem Force-Push zu verlieren .
3
Manchmal ist es das, was du willst. Beispiel: Mehrere Commits wurden festgeschrieben und in den falschen Zweig (Zweig A) verschoben. Nach dem Kirschpflücken in Zweig B möchte ich, dass diese Commits aus Zweig A entfernt werden. Ich möchte nicht zurücksetzen, da der Rückzug später angewendet wird, wenn Zweig A und B zusammengeführt werden. Durch Zurücksetzen --hard <commitId> in Zweig A, gefolgt von einem Force-Push, werden diese Commits aus dem Zweig entfernt, während sie in Zweig B beibehalten werden. Ich kann damit durchkommen, weil ich weiß, dass sich in Zweig A niemand anderes entwickelt.
Doug R.
Vielen Dank! Ich konnte nicht herausfinden, wie ich den Remote-Zweig an meinen lokalen Zweig anpassen konnte. Ich musste nur einen Force-Push ausführen.
Mido
32

Sie können alle diese ersten Schritte selbst ausführen und zum Git-Repository zurückkehren.

  1. Rufen Sie mit dem git pull --allBefehl die neueste Version Ihres Repositorys aus Bitbucket ab .

  2. Führen Sie den Git-Protokollbefehl mit -n 4von Ihrem Terminal aus. Die Zahl nach dem -nbestimmt die Anzahl der Festschreibungen im Protokoll ab dem letzten Festschreiben in Ihrem lokalen Verlauf.

    $ git log -n 4
    
  3. Setzen Sie den Kopf des Repository-Verlaufs zurück, indem git reset --hard HEAD~NSie die Anzahl der Commits angeben, für die Sie den Kopf zurücknehmen möchten. Im folgenden Beispiel wird der Kopf um ein Commit auf das letzte Commit im Repository-Verlauf zurückgesetzt:

  4. Übertragen Sie die Änderung in das Git-Repository git push --force, um die Änderung zu erzwingen.

Wenn Sie das Git-Repository auf ein vorheriges Commit setzen möchten:

git pull --all
git reset --hard HEAD~1
git push --force
Nanhe Kumar
quelle
30

Zum letzten Commit zurückkehren und alle lokalen Änderungen ignorieren:

git reset --hard HEAD
Mohammed Irfan Tirupattur
quelle
28

Wählen Sie das gewünschte Commit aus und überprüfen Sie es durch

git show HEAD
git show HEAD~1
git show HEAD~2 

bis Sie das erforderliche Commit erhalten. Tun Sie dies, um den KOPF darauf hinzuweisen

git reset --hard HEAD~1

oder git reset --hard HEAD~2oder was auch immer.

tonythomas01
quelle
7
Obligatorische Warnung: Tun Sie dies nicht, wenn Sie Ihren Zweig mit anderen Personen teilen, die Kopien der alten Commits haben, da sie bei Verwendung eines solchen Hard-Reset gezwungen sind, ihre Arbeit mit dem neu zurückgesetzten Zweig neu zu synchronisieren. In dieser Antwort finden Sie eine Lösung, in der ausführlich erläutert wird, wie Sie Commits sicher zurücksetzen können, ohne die Arbeit mit einem Hard-Reset zu verlieren .
2
Um klar zu sein, git show HEADist es auch gleichbedeutend mit nur zu verwenden git log HEAD -1.
25

Wenn die Situation dringend ist und Sie nur schnell und schmutzig das tun möchten, was der Fragesteller gefragt hat , vorausgesetzt, Ihr Projekt befindet sich in einem Verzeichnis mit dem Namen "Mein Projekt":


SCHNELL UND SCHMUTZIG : Abhängig von den Umständen kann schnell und schmutzig tatsächlich sehr GUT sein. Was meine Lösung hier tut, ist NICHT , die Dateien, die Sie in Ihrem Arbeitsverzeichnis haben, irreversibel durch Dateien zu ersetzen, die aus den Tiefen des Git-Repositorys gezogen / extrahiert wurden, das unter Ihrem .git / -Verzeichnis lauert, und zwar mit teuflisch cleveren und teuflisch mächtigen Git-Befehlen, von denen es solche gibt viele. SIE MÜSSEN KEIN TIEFES MEER-TAUCHEN TUN, UM eine möglicherweise katastrophale Situation wiederherzustellen, und der Versuch, dies ohne ausreichendes Fachwissen zu tun, kann sich als tödlich erweisen .


  1. Kopieren Sie das gesamte Verzeichnis und nennen Sie es etwas anderes, wie "Mein Projekt - Kopie". Angenommen, Ihre Git-Repository-Dateien ("Repo") befinden sich im Verzeichnis "Mein Projekt" (der Standardspeicherort für sie, unter einem Verzeichnis namens ".git"), dann haben Sie jetzt sowohl Ihre Arbeitsdateien als auch Ihre Repo-Dateien kopiert.

  2. Tun Sie dies im Verzeichnis "Mein Projekt":

    .../my project $ git reset --hard [first-4-letters&numbers-of-commit's-SHA]
    

Dadurch wird der Status des Repos unter "Mein Projekt" auf den Stand zurückgesetzt, als Sie diesen Commit durchgeführt haben (ein "Commit" bedeutet eine Momentaufnahme Ihrer Arbeitsdateien). Alle Commits seitdem gehen für immer unter "Mein Projekt" verloren, ABER ... sie sind weiterhin im Repo unter "Mein Projekt - Kopie" vorhanden, da Sie alle kopiert haben diese Dateien - einschließlich der Dateien unter ... /. Git /.

Sie haben dann zwei Versionen auf Ihrem System ... Sie können Dateien von Interesse oder was auch immer aus dem vorherigen Commit untersuchen oder kopieren oder ändern. Sie können die Dateien unter "Mein Projekt - Kopie" vollständig verwerfen, wenn Sie sich für die neue Arbeit entschieden haben, da das wiederhergestellte Commit nirgendwo hingegangen ist ...

Wenn Sie den Status des Projekts fortsetzen möchten, ohne die Arbeit seit diesem abgerufenen Commit tatsächlich zu verwerfen, müssen Sie Ihr Verzeichnis erneut umbenennen: Löschen Sie das Projekt mit dem abgerufenen Commit (oder geben Sie ihm einen temporären Namen) und benennen Sie Ihr " mein Projekt - kopiere "Verzeichnis zurück in" mein Projekt ". Versuchen Sie dann vielleicht, einige der anderen Antworten hier zu verstehen, und führen Sie wahrscheinlich bald ein weiteres Commit durch.

Git ist eine brillante Kreation, aber absolut niemand kann sie einfach "on the fly" aufgreifen: auch Leute, die versuchen, sie viel zu oft zu erklären setzen Vorkenntnisse anderer VCS [Versionskontrollsysteme] voraus und vertiefen sich viel zu tief zu früh und begehen andere Verbrechen, wie die Verwendung austauschbarer Begriffe zum "Auschecken" - auf eine Weise, die manchmal fast so berechnet erscheint, dass sie einen Anfänger verwirrt.

Um sich viel Stress zu ersparen, lernen Sie aus meinen Narben. Man muss so ziemlich ein Buch über Git lesen - ich würde "Versionskontrolle mit Git" empfehlen . Mach es eher früher als später. Wenn Sie dies tun, denken Sie daran, dass ein Großteil der Komplexität von Git durch Verzweigen und anschließendes Zusammenführen entsteht: Sie können diese Teile in jedem Buch überspringen. Nach Ihrer Frage gibt es keinen Grund, warum die Leute Sie mit der Wissenschaft blenden sollten .

Besonders wenn dies zum Beispiel eine verzweifelte Situation ist und Sie ein Neuling bei Git sind!

PS: Ein anderer Gedanke: Es ist (jetzt) ​​eigentlich ganz einfach, das Git-Repo in einem anderen Verzeichnis als dem mit den Arbeitsdateien zu speichern. Dies würde bedeuten, dass Sie nicht das gesamte Git-Repository mit der oben genannten Quick & Dirty-Lösung kopieren müssen. Die Antwort von Fryer finden Sie --separate-git-dir hier . Seien Sie jedoch gewarnt : Wenn Sie ein "separates Verzeichnis" -Repository haben, das Sie nicht kopieren, und Sie einen Hard-Reset durchführen, gehen alle Versionen nach dem Reset-Commit für immer verloren, es sei denn, Sie haben, wie Sie unbedingt sollten, Sichern Sie Ihr Repository regelmäßig, vorzugsweise in der Cloud (z. B. Google Drive ).

Zu diesem Thema "Sichern in der Cloud" besteht der nächste Schritt darin, ein Konto (natürlich kostenlos) bei GitHub oder (meiner Ansicht nach besser) GitLab zu eröffnen . Sie können dann regelmäßig einen git pushBefehl ausführen, um Ihr Cloud-Repo "richtig" auf den neuesten Stand zu bringen. Aber auch hier kann es zu früh sein, darüber zu sprechen.

Mike Nagetier
quelle
23

Dies ist eine weitere Möglichkeit, direkt auf ein kürzlich festgeschriebenes Commit zurückzusetzen

git stash
git stash clear

Alle Änderungen, die Sie seit dem letzten Commit vorgenommen haben, werden direkt gelöscht.

PS: Es hat ein kleines Problem; Außerdem werden alle kürzlich gespeicherten Stash-Änderungen gelöscht. Was ich in den meisten Fällen denke, sollte keine Rolle spielen.

Punktnetzwerke
quelle
HINWEIS: Neue Dateien, die nicht im Index hinzugefügt wurden, werden nicht gespeichert. Sie müssen sie auch hinzufügen oder manuell löschen.
Andrejro
Warum oh, warum Versteck räumen? Dies ist nicht nur eine Nichtlösung, sondern auch schädlich. Das Lesen des allerersten Satzes der Frage macht die Stash-Lösung sofort ungültig (was NUR zum Zurücksetzen auf das LAST-Commit nützlich sein kann).
RomainValeri
22

Um das Verzeichnis eines Codierers vollständig von versehentlichen Änderungen zu befreien, haben wir Folgendes verwendet:

git add -A .
git reset --hard HEAD

Nur git reset --hard HEADwird erhalten von Änderungen befreien, aber es wird nicht der „neuen“ Dateien loszuwerden. In ihrem Fall hatten sie versehentlich einen wichtigen Ordner an einen zufälligen Ort gezogen, und all diese Dateien wurden von Git als neu behandelt, sodass a reset --hardsie nicht reparierte. Durch vorheriges Ausführen git add -A .wurden alle explizit mit git verfolgt, um durch das Zurücksetzen gelöscht zu werden.

Chris Moschini
quelle
21

Gehen Sie folgendermaßen vor, um die Änderungen vom vorherigen Commit für HEAD beizubehalten und zum vorherigen Commit zu wechseln:

git reset <SHA>

Wenn keine Änderungen gegenüber dem vorherigen Commit für HEAD erforderlich sind und einfach alle Änderungen verwerfen, gehen Sie wie folgt vor:

git reset --hard <SHA>
Vishnu Atrai
quelle
20

Ich glaube, einige Leute kommen zu dieser Frage und möchten wissen, wie sie festgeschriebene Änderungen, die sie an ihrem Master vorgenommen haben, rückgängig machen können - dh alles wegwerfen und zum Ursprung / Master zurückkehren. In diesem Fall tun Sie Folgendes:

git reset --hard origin/master

/superuser/273172/how-to-reset-master-to-origin-master

Nevster
quelle
18

Zurücksetzen ist der Befehl zum Zurücksetzen der Commits.

git revert <commit1> <commit2> 

Stichprobe:

git revert 2h3h23233

Es ist in der Lage, die Reichweite vom KOPF wie unten zu nehmen. Hier sagt 1 "letztes Commit zurücksetzen".

git revert HEAD~1..HEAD

und dann tun git push

Sireesh Yarlagadda
quelle
14

Versuchen Sie, das gewünschte Commit zurückzusetzen -

git reset <COMMIT_ID>

(um die Verwendung von COMMIT_ID zu überprüfen git log)

Dadurch werden alle geänderten Dateien in den nicht hinzugefügten Zustand zurückgesetzt.

Jetzt können Sie checkoutalle nicht hinzugefügten Dateien von

git checkout .

Überprüfen Sie git log, ob Ihre Änderungen überprüft wurden.

AKTUALISIEREN

Wenn Sie ein einziges Commit in Ihrem Repo haben, versuchen Sie es

git update-ref -d HEAD

optimistanoop
quelle
13

Da Ihre Commits remote übertragen werden, müssen Sie sie entfernen. Lassen Sie mich annehmen, dass sich Ihr Zweig entwickelt und über den Ursprung hinausgeschoben wird .

Sie müssen zuerst die Entwicklung vom Ursprung entfernen :

git push origin :develop (note the colon)

Dann müssen Sie sich auf den gewünschten Status entwickeln. Lassen Sie mich annehmen, dass der Commit-Hash EFGHIJK lautet:

git reset --hard EFGHIJK

Zuletzt drücken Sie erneut entwickeln :

git push origin develop
George Ninan
quelle
13

Vorsicht! Dieser Befehl kann zum Verlust des Commit-Verlaufs führen, wenn der Benutzer versehentlich das falsche Commit eingegeben hat. Haben Sie immer ein zusätzliches Backup Ihres Git woanders, nur für den Fall, dass Sie Fehler machen, als Sie ein bisschen sicherer sind. :) :)

Ich hatte ein ähnliches Problem und wollte zu einem früheren Commit zurückkehren. In meinem Fall war ich nicht daran interessiert, das neuere Commit beizubehalten, daher habe ich es verwendet Hard.

So habe ich es gemacht:

git reset --hard CommitId && git clean -f

Dies wird auf das lokale Repository zurückgesetzt und hier nach der Verwendung git push -fwird das Remote-Repository aktualisiert.

git push -f
Maytham-ɯɐɥʇʎɐɯ
quelle
13

In GitKraken können Sie dies tun:

  1. Klicken Sie mit der rechten Maustaste auf das Commit, das Sie zurücksetzen möchten, und wählen Sie: Auf dieses Commit zurücksetzen / Schwer :

    Geben Sie hier die Bildbeschreibung ein

  2. Klicken Sie erneut mit der rechten Maustaste auf das Commit und wählen Sie: Aktueller Filialname / Push :

    Geben Sie hier die Bildbeschreibung ein

  3. Klicken Sie auf Force Push :

    Geben Sie hier die Bildbeschreibung ein

Obs. : Sie müssen vorsichtig sein, da der gesamte Commit-Verlauf nach dem Hard-Reset verloren geht und diese Aktion irreversibel ist. Sie müssen sicher sein, was Sie tun.

Engelo Polotto
quelle
11

Wenn Sie einen Fehler beim letzten Festschreiben korrigieren möchten, ist die Verwendung des Befehls git commit --amend eine gute Alternative . Wenn auf das letzte Commit nicht durch eine Referenz verwiesen wird, reicht dies aus, da ein Commit mit demselben übergeordneten Element wie das letzte Commit erstellt wird. Wenn es keinen Verweis auf das letzte Commit gibt, wird es einfach verworfen und dieses Commit ist das letzte Commit. Dies ist eine gute Möglichkeit, Commits zu korrigieren, ohne Commits zurückzusetzen. Es hat jedoch seine eigenen Einschränkungen.

Upul Doluweera
quelle