Wie kann ich mich von einem fehlerhaften Git Push -f Origin Master erholen?

92

Ich habe gerade die falsche Quelle für mein Projekt mit der --forceOption festgeschrieben .

Ist es möglich, zurückzusetzen? Ich verstehe, dass alle vorherigen Zweige mit der -fOption überschrieben wurden , sodass ich möglicherweise meine vorherigen Überarbeitungen vermasselt habe.

David van Dugteren
quelle
Mögliches Duplikat von Gibt es überhaupt eine
cmbuckley

Antworten:

53

Git wirft im Allgemeinen nichts weg, aber es kann immer noch schwierig sein, sich davon zu erholen.

Wenn Sie die richtige Quelle haben, können Sie sie mit der --forceOption einfach in die Fernbedienung schieben . Git hat keine Zweige gelöscht, es sei denn, Sie haben es gesagt. Wenn Sie tatsächlich Commits verloren haben, lesen Sie diese nützliche Anleitung zum Wiederherstellen von Commits . Wenn Sie die SHA-1 der gewünschten Commits kennen, sind Sie wahrscheinlich in Ordnung.

Am besten sichern Sie alles und sehen Sie, was sich noch in Ihrem lokalen Repository befindet. Machen Sie dasselbe nach Möglichkeit auf der Fernbedienung. Verwenden git fsckSie diese Option, um festzustellen, ob Sie Dinge wiederherstellen können, und führen Sie sie vor allem NICHT ausgit gc .

Verwenden Sie die --forceOption vor allem niemals, es sei denn, Sie meinen es wirklich ernst.

Cameron Skinner
quelle
64
Sie können sich sehr wahrscheinlich nur die Reflogs ansehen, um festzustellen, wo sich die Remote-Zweige ursprünglich befanden. Zum Beispiel git reflog show remotes/origin/master. Sie sollten in der Lage sein, Ihren Push dort zu sehen; Das Commit in der vorherigen Zeile befindet sich dort, wo es war, bevor Sie es durcheinander gebracht haben. Sie können diese Revision dann einfach (mit --force) zum Ursprung schieben und wieder da sein, wo Sie waren!
Cascabel
@ David: Oh. Sie haben in Ihrer Frage nicht erwähnt, dass Sie das Repo nicht hatten. (Dies ist natürlich etwas, das Sie niemals tun möchten.) Wenn Sie über einen Dateisystemzugriff verfügen, auf den Sie verschoben haben, können Sie dies alles trotzdem tun.
Cascabel
1
@ David: Huch. Es ist immer gut, Ihr aktuelles Verzeichnis als Teil Ihrer Eingabeaufforderung zu haben, um solche Dinge zu vermeiden.
Cascabel
1
@Jefromi Ich denke, was du gesagt hast, ist die eigentliche Antwort: Selbst mit einer alten Version (die schon lange nicht mehr git fetchbearbeitet wurde) kannst du das Reflog von GitHubs Seite anzeigen und dich erholen!
nh2
1
Wo ist diese Antwort von @Jefromi? Ich sehe den auf dieser Seite erwähnten Benutzer außerhalb dieses Kommentarthreads nicht.
Don McCurdy
47

Wenn Sie den Commit-Hash kennen, ist es einfach, erstellen Sie einfach Ihren Zweig neu.

5794458...b459f069 master -> master (forced update)

Löschen Sie den Remote-Zweig:

git push origin :master

Erstellen Sie dann Ihren Zweig mit den folgenden Befehlen neu:

git checkout 5794458
git branch master
git push origin master
user1094125
quelle
28

Die Lösung wird bereits erwähnt hier

# work on local master
git checkout master

# reset to the previous state of origin/master, as recorded by reflog
git reset --hard origin/master@{1}

# at this point verify that this is indeed the desired commit.
# (if necessary, use git reflog to find the right one, and
# git reset --hard to that one)

# finally, push the master branch (and only the master branch) to the server
git push -f origin master
Abdelhafid
quelle
Danke, das hat bei mir funktioniert. Ich hatte keinen Zugriff zum Löschen des Masters, daher schlug der genehmigte Kommentar fehl.
Andi
Ja, und git reflog show remotes/origin/masterwenn Git Reflog notwendig ist (wie von @Cascabel oben erwähnt)
Josiah Yoder
2
Dies ist die richtige Antwort, danke für die Verknüpfung mit der richtigen.
Noitidart
6

Wenn Sie sich nicht in dem lokalen Repo befinden, von dem der erzwungene Push stammt, gibt es auf Ursprungs- / Master-Ebene keine Möglichkeit, sich zu erholen. Wenn Sie jedoch das Glück haben, GitHub oder GitHub for Enterprise zu verwenden , können Sie einen Blick auf die REST- API werfen und das verlorene Commit als Patch abrufen. Beispiel:

  1. Listen Sie Ereignisse auf und finden Sie das Commit sha1-Langformat

https://api.github.com/repos/apache/logging-log4j2/events

  1. Laden Sie das verlorene Commit herunter und rufen Sie den zugehörigen Patch im json-Pfad .files [] / patch ab

https://api.github.com/repos/apache/logging-log4j2/commits/889232e28f3863d2a17392c06c1dd8cac68485de

  1. Bewerben Sie sich lokal und drücken Sie erneut

git wende patch.patch an && git commit -m "wiederhergestelltes Commit" && git push origin master

Pierrick HYMBERT
quelle
3

Eine andere Möglichkeit, das verlorene Commit wiederherzustellen oder sogar herauszufinden, welche Commits verloren gegangen sind, wenn der vorherige Push nicht von Ihrem lokalen Repo stammt, besteht darin, sich Ihren CI-Computer anzusehen.

Wenn Sie einen Job haben, der den Hauptzweig nach jedem Commit (oder einer Reihe aufeinanderfolgender Commits) testet, den Sie haben sollten, können Sie sich ansehen, was zuletzt getestet wurde. Dies ist das Commit, das Sie wiederherstellen müssen.

Der CI-Computer behält möglicherweise sogar einen lokalen Klon des Repos, von dem aus Sie möglicherweise diese Wiederherstellung durchführen können.

Quelle: wahrscheinlich Continuous Delivery: Zuverlässige Softwareversionen durch Automatisierung von Builds, Tests und Bereitstellungen (Addison-Wesley Signature Series (Fowler))

user7610
quelle
3

Ja, Sie können Commits nachher wiederherstellen git push -f your_branch

Text aus Doc :

Bereinigen Sie Einträge, die älter als die angegebene Zeit sind. Wenn diese Option nicht angegeben wird, wird die Ablaufzeit aus der Konfigurationseinstellung gc.reflogExpire übernommen, die standardmäßig 90 Tage beträgt. --expire = alle Pflaumeneinträge unabhängig von ihrem Alter; --expire = Deaktiviert niemals das Bereinigen erreichbarer Einträge (siehe jedoch --expire-unreachable).

So können Sie tun:

1- git reflog

Geben Sie hier die Bildbeschreibung ein

2- Sie wählen Head_Number, mit dem Sie wiederherstellen möchten git reset –hard HEAD@{HEAD-NUMBER}

Geben Sie hier die Bildbeschreibung ein

3- Sie können alle Commits auf diesem Kopf von sehen git cherry -v branch_name

4- Am Ende sollten Sie einen Druck erzwingen git push -f branch_name

ODER

1- Holen Sie sich die Anzahl der SHA von Ihrem GIT-Client (Schnittstelle)

git reset --hard commit_SHA

2- Druck drücken

git push -f your_branch

Hoffe das hilft

Jacob
quelle
2

Ich habe das Gleiche getan, als ich einen letzten Push für nur eine Datei rückgängig gemacht habe. Am Ende kehrte ich zum ursprünglichen Zustand des Repositorys zurück. Ich habe Git-Befehle von Linus verwendet, da ich die lokale Kopie unter Linux hatte. Zum Glück war diese Kopie noch intakt.

Alles, was ich getan habe, war (nachdem ich einige weitere Kopien des lokalen Repos angefertigt hatte):

git add .
git status

(Es hieß, dass Origin / Master 68 Commits voraus war, okay ... das waren alle Commits, die ich gelöscht habe.)

git remote set-url origin <GIT_SSH_URL>
git push

Und alles wurde so wiederhergestellt, wie es war, bevor ich gewaltsam Druck ausübte. Das Wichtigste, an das Sie sich erinnern sollten, ist, niemals einen Git-Checkout durchzuführen. nachdem Sie gewaltsam gedrückt hatten. Die beste Vorgehensweise ist jedoch, die Push-Option zu deaktivieren. Ich benutze es nie wieder. Habe meine Lektion gelernt !!

Pran
quelle
0

Hier können Sie Entscheidungen lesen https://evilmartians.com/chronicles/git-push---force-and-how-to-deal-with-it

Der zweite hat mir geholfen. Ich habe diese Befehle falsch gemacht

1) (some-branch) git pull -> correct command was git pull origin some-branch

2) (some-branch) git push -f origin some-branch

Nach diesen Befehlen habe ich drei Commits verloren. Um sie wiederherzustellen, habe ich zum Terminal geschaut, wo ich fälschlicherweise "Git Pull" gemacht habe und dort eine Ausgabe wie gesehen habe

60223bf ... 0b258eb ein Zweig -> Ursprung / ein Zweig

Der zweite Hash 0b258eb war genau das, was ich brauchte. Also nahm ich diesen Hash und erzeugte den Befehl

git push --force origin 0b258eb:some-branch
Andrey
quelle
0

Für Leute in wirklich schlechten Situationen wie ich (zum Beispiel, wenn bad objectbeim Laufen Fehler auftreten git reset --hard):

Ich habe ein Skript namens TreeSaver geschrieben , das als letzten Ausweg alle Ihre Dateien von der GitHub-API abruft . So verwenden Sie es:

  1. Klonen Sie das treesaverSkript und cddarauf.
  2. Suchen Sie die SHAZeichenfolge des Baums, den Sie wiederherstellen möchten, indem Sie auf zugreifen https://api.github.com/repos/<your_username_or_org>/<repo>/events.
  3. payloadSuchen commitSie in der Eigenschaft, die Ihrem Push-Ereignis entspricht, das Objekt, zu dem Sie zurückkehren möchten, und klicken Sie darauf url.
  4. Unter commit.treeKopieren Sie die tree‚s url.
  5. Ausführen python3 main.py <tree_url> <path_to_save_to>.

In meinem Fall würde ich beispielsweise Folgendes ausführen:

python3 main.py https://api.github.com/repos/anthonykrivonos/my-repo/git/trees/1234567 .

PRs sind natürlich willkommen.

Anthony Krivonos
quelle