Git - Push-Commits rückgängig machen

609

Ich habe ein Projekt in einem Remote-Repository, das mit einem lokalen Repository (Entwicklung) und dem Server-Repository (Produkt) synchronisiert ist. Ich habe einige festgeschriebene Änderungen vorgenommen, die bereits auf Remote übertragen und vom Server abgerufen wurden. Jetzt möchte ich diese Änderungen rückgängig machen. Ich könnte also nur git checkoutvor den Änderungen festschreiben und die neuen Änderungen festschreiben, aber ich vermute, dass es Probleme geben wird, sie erneut auf Remote zu übertragen. Irgendwelche Vorschläge, wie ich vorgehen soll?

Manolo
quelle

Antworten:

735

Sie können einzelne Commits zurücksetzen mit:

git revert <commit_hash>

Dadurch wird ein neues Commit erstellt, das die Änderungen des von Ihnen angegebenen Commits zurücksetzt. Beachten Sie, dass nur dieses bestimmte Commit zurückgesetzt wird und danach kein Commit mehr. Wenn Sie eine Reihe von Commits zurücksetzen möchten, können Sie dies folgendermaßen tun:

git revert <oldest_commit_hash>..<latest_commit_hash>

Es setzt die Commits zwischen und einschließlich der angegebenen Commits zurück.

Weitere Informationen zum Befehl finden Sie in der Manpage git-revertgit revert . In dieser Antwort finden Sie auch weitere Informationen zum Zurücksetzen von Commits.

Gitaarik
quelle
22
Mit anderen Worten, es kehrt zum <oldest_commit_hash> zurück;)
David
7
@ Mr_Jigsaw Verwendunggit log
Gitaarik
2
In der Git-Dokumentation heißt es, dass der Befehl zum Zurücksetzen die Festschreibungen zwischen der ersten und der letzten Festschreibung zurücksetzt (sowohl die erste als auch die letzte). Siehe Dokumentation
Onur Demir
4
@aod ist korrekt, diese Antwort muss aktualisiert werden. Die aktuelle Git-API für <oldest_commit_hash>das
Zurücksetzen wurde
4
mit git 2.17.2 revert <old> .. <new> enthält nicht old, sondern <new>
chingis
353

Eine Lösung, die keine Spuren des "Rückgängigmachens" enthält.

HINWEIS: Tun Sie dies nicht, wenn bereits jemand Ihr Wechselgeld gezogen hat (ich würde dies nur für mein persönliches Repo verwenden).

tun:

git reset <previous label or sha1>

Dadurch werden alle Updates lokal erneut ausgecheckt (so dass der Git-Status alle aktualisierten Dateien auflistet).

dann "erledigen Sie Ihre Arbeit" und übernehmen Ihre Änderungen erneut (Hinweis: Dieser Schritt ist optional)

git commit -am "blabla"

In diesem Moment unterscheidet sich Ihr lokaler Baum von der Fernbedienung

git push -f <remote-name> <branch-name>

wird Remote drücken und zwingen, diesen Push zu berücksichtigen und den vorherigen zu entfernen (die Angabe des Remote-Namens und des Filialnamens ist nicht obligatorisch, wird jedoch empfohlen, um zu vermeiden, dass alle Zweige mit dem Update-Flag aktualisiert werden).

!! Achtung, einige Tags zeigen möglicherweise immer noch auf entferntes Commit !! Wie lösche ich ein Remote-Tag?

jo_
quelle
4
-a alle verfolgten Dateien werden festgeschrieben -m Festschreibungsnachricht folgt
jo_
3
Genau das, wonach ich gesucht habe. Jemand hat ein fehlerhaftes Commit ausgeführt und es anschließend erneut zurückgesetzt. Die Zweige konnten aus diesem Grund nicht zusammengeführt werden, und ich wollte, dass das Repository wieder im richtigen Zustand ist (und das Commit aus dem Verlauf entfernt, da es ohnehin fehlerhaft war)
bis zum
1
Welches "vorherige Label oder sha1" soll ich verwenden? Sollte ich die letzte "richtige" oder die vorhergehende eingeben und alle Änderungen, die durch die letzte richtige vorgenommen wurden, erneut durchführen?
Elysch
3
der kurz vor dem fehlerhaften Commit
jo_
1
Genau das, was ich brauche. Ich habe versehentlich einen Zweig zum Master geschoben. Infolgedessen hatte ich während der gesamten Commits-Geschichte viele Müll-Commits. Ich habe gerade das git push -fletzte richtige Commit durchgeführt und den Remote-Verlauf bereinigt! Vielen Dank!
Anton Rybalko
193

Was ich in diesen Fällen mache, ist:

  • Bewegen Sie den Cursor auf dem Server zurück zum letzten bekannten guten Commit:

    git push -f origin <last_known_good_commit>:<branch_name>
    
  • Machen Sie vor Ort dasselbe:

    git reset --hard <last_known_good_commit>
    #         ^^^^^^
    #         optional
    



Sehen Sie sich ein vollständiges Beispiel für einen Zweig an my_new_branch, den ich zu diesem Zweck erstellt habe:

$ git branch
my_new_branch

Dies ist die jüngste Geschichte, nachdem einige Dinge hinzugefügt wurden zu myfile.py:

$ git log
commit 80143bcaaca77963a47c211a9cbe664d5448d546
Author: me
Date:   Wed Mar 23 12:48:03 2016 +0100

    Adding new stuff in myfile.py

commit b4zad078237fa48746a4feb6517fa409f6bf238e
Author: me
Date:   Tue Mar 18 12:46:59 2016 +0100

    Initial commit

Ich möchte das letzte Commit loswerden, das bereits gepusht wurde, also renne ich:

$ git push -f origin b4zad078237fa48746a4feb6517fa409f6bf238e:my_new_branch
Total 0 (delta 0), reused 0 (delta 0)
To [email protected]:me/myrepo.git
 + 80143bc...b4zad07 b4zad078237fa48746a4feb6517fa409f6bf238e -> my_new_branch (forced update)

Nett! Jetzt sehe ich die Datei, die in diesem Commit ( myfile.py) geändert wurde, in "Nicht für Commit bereitgestellt" angezeigt:

$ git status
On branch my_new_branch
Your branch is up-to-date with 'origin/my_new_branch'.

Changes not staged for commit:
  (use "git add <file>..." to update what will be committed)
  (use "git checkout -- <file>..." to discard changes in working directory)

    modified:   myfile.py

no changes added to commit (use "git add" and/or "git commit -a")

Da ich diese Änderungen nicht möchte, bewege ich den Cursor auch lokal zurück:

$ git reset --hard b4zad078237fa48746a4feb6517fa409f6bf238e
HEAD is now at b4zad07 Initial commit

Jetzt befindet sich HEAD im vorherigen Commit, sowohl lokal als auch remote:

$ git log
commit b4zad078237fa48746a4feb6517fa409f6bf238e
Author: me
Date:   Tue Mar 18 12:46:59 2016 +0100

    Initial commit
fedorqui 'SO hör auf zu schaden'
quelle
10
Das ist die richtige Antwort! Dies ist genau das, was in meinem Fall getan werden musste, danke, dass ich heute etwas Neues gelernt habe :)
Egli Becerra
2
Das ist die richtige Antwort! Es geht um Pushed (!) Commits!
Powtac
3
Wenn Sie wirklich revert Änderungen wollen (als ob Sie nie gedrückt haben), dies ist die richtige Antwort.
Jacob
1
Perfekte Antwort. Hat gut funktioniert wie erwartet!
RafiAlhamd
2
Jemand kauft diesem Mann ein Bier!
Jay Nebhwani
72

Sie können das Git-Commit sowohl lokal als auch remote umkehren (oder auch als DELETE bezeichnen ), wenn Sie die folgenden Schritte über die Git-Befehlszeile ausführen.

Führen Sie den folgenden Befehl aus, um die Festschreibungs-ID anzuzeigen, die Sie zurücksetzen möchten

git log --oneline --decorate --graph

Sie erhalten wie folgt einen Screenshot Geben Sie hier die Bildbeschreibung ein

Wenn Sie auch Remote (über das Webinterface) aktivieren, können Sie feststellen, dass dies wie unten gezeigt ist

Geben Sie hier die Bildbeschreibung ein

Wie pro Screenshot zur Zeit sind Sie auf id verpflichten e110322 jedoch zu dem Sie wieder zurück wollen 030bbf6 BEIDE lokal als auch remote .

Führen Sie die folgenden Schritte aus, um Commits lokal + remote zu löschen / rückgängig zu machen


Zuerst lokal zurücksetzen, um die ID 030bbf6 festzuschreiben

git reset --hard 030bbf6

gefolgt von

git clean -f -d

Diese beiden Befehle bereinigen das Zurücksetzen, um Stufe 030bbf6 festzuschreiben, wie unten im Schnappschuss gezeigt

Geben Sie hier die Bildbeschreibung ein

Wenn Sie jetzt den Git-Status ausführen, werden Sie feststellen, dass Sie ZWEI Commits HINTER dem Remote-Zweig sind, wie unten gezeigt Geben Sie hier die Bildbeschreibung ein

Führen Sie die folgenden Schritte aus, um Ihre Indizes zu aktualisieren (falls Aktualisierungen vorhanden sind). Es wird empfohlen, dass Sie alle Entwickler bitten, keine Pull-Anforderungen für den Haupt-Remote-Zweig zu akzeptieren.

git fetch --all

Sobald Sie damit fertig sind , dann sind Sie verpflichtet , schieben diese verpflichten , gewaltsam durch die Verwendung + -vor Zweig Symbol wie unten dargestellt. Ich habe hier verwendeten Master - Zweig, können Sie es mit jedem ersetzen

Geben Sie hier die Bildbeschreibung ein Code

git push -u origin +master

Wenn Sie nun die Weboberfläche von remote sehen, sollte das Festschreiben ebenfalls zurückgesetzt werden.

Geben Sie hier die Bildbeschreibung ein

vibs2006
quelle
61

Dadurch werden Ihre Push-Commits entfernt

git reset --hard 'xxxxx'

git clean -f -d

git push -f
Mo D Genesis
quelle
7
Diese Methode schreibt den Verlauf ordnungsgemäß neu, um das Commit zu löschen. Genial
Jesse Reza Khorasanee
2
Diese Antwort ist el magnifeco!
Truthadjustr
3
Liebe die Antwort, danke :)
Dzenis H.
1
Nur um klar zu sein (ich war mir nicht sicher): Das Commit ist das aktuelle Commit nach der Operation. Nicht der letzte, der gelöscht wird.
Maik639
21
git revert HEAD -m 1

In der obigen Codezeile. "Letztes Argument repräsentiert"

  • 1 - kehrt ein Commit zurück.

  • 2 - Setzt die letzten beiden Commits zurück.

  • n - setzt die letzten n Commits zurück.

Sie müssen nach diesem Befehl drücken, um die Wirkung auf die Fernbedienung zu erzielen. Sie haben andere Möglichkeiten, z. B. den Bereich der zurückzusetzenden Commits anzugeben. Dies ist eine der Optionen.


Später verwenden git commit -am "COMMIT_MESSAGE" dann git pushodergit push -f

Sireesh Yarlagadda
quelle
8
Dies ist nicht der Fall - der Parameter -m gibt die Anzahl der übergeordneten Elemente an, auf die zurückgesetzt werden soll (normalerweise 1, wenn Sie die eingehenden "ihre" Änderungen rückgängig machen möchten, im Gegensatz zu 2 für zusammengeführte Änderungen, "unsere" - für das Zusammenführen von 2 Commits). Es hat nichts mit der Anzahl der zurückgesetzten Commits zu tun - wenn Sie einen Commit-Bereich zurücksetzen möchten, verwenden Siegit revert ref1..ref2
Null Reference
1
Hatte nicht den gewünschten Effekt
Sam Tuke
2

2020 Einfacher Weg:

git reset <commit_hash>

(Der Hash des letzten Commits, den Sie behalten möchten).

Sie behalten die jetzt nicht festgeschriebenen Änderungen lokal bei.

Wenn Sie erneut pushen möchten, müssen Sie Folgendes tun:

git push -f
Xys
quelle
0

Hier ist mein Weg:

Angenommen, der Filialname lautet develop.

# Create a new temp branch based on one history commit
git checkout <last_known_good_commit_hash>
git checkout -b develop-temp

# Delete the original develop branch and 
# create a new branch with the same name based on the develop-temp branch
git branch -D develop
git checkout -b develop

# Force update this new branch
git push -f origin develop

# Remove the temp branch
git branch -D develop-temp
Backslash112
quelle
0

Sie können so etwas tun

git push origin +<short_commit_sha>^:<branch_name>
avrsanjay
quelle