git push –force und wie man damit umgeht

Haben Sie sich schon einmal in einer Situation befunden, in der ein falscher Git-Befehl die Projektrepositorien Ihres Projekts verwüstet hat? Menschen machen Fehler, und manchmal können diese Fehler Stunden der Zeit Ihres Teams kosten. In diesem Tutorial zeigen wir Ihnen, wie Sie sich schnell von einem unglücklichen git push --force erholen können.

Wir sollten nicht zu selbstbewusst sein. Früher oder später wird das passieren. Wenn Sie mit mehreren Remotes im selben Git-Repository arbeiten, werden Sie irgendwann git push --force in master (oder einen anderen wichtigen Zweig, an dem man nie herumpfuschen sollte) geraten.

Das kann zum Beispiel bei der Bereitstellung mit Deis oder Heroku passieren, die separate Git-Remotes zum Erstellen und Bereitstellen einer Anwendung verwenden. Nach einem langen Arbeitstag ist es unglaublich einfach, git push --force statt des üblichen git push --force deis master auszuführen.

Oops! Im Handumdrehen haben Ihre Teamkollegen ihre gesamte letzte Arbeit verloren. Es ist an der Zeit, sich ihrer Wut zu stellen.

Doch wie ein hervorragender Ratgeber sagt: DON’T PANIC! Das Gute ist, dass du git verwendest, und das bedeutet, dass alles repariert werden kann.

Im besten Fall hat jemand anderes, der am selben Code arbeitet, eine aktuelle Version des master gezogen, kurz bevor du es kaputt gemacht hast. Dann brauchen Sie nur in den Chat Ihres Teams zu gehen und diese Person zu bitten, ihre letzten Änderungen zu pushen.

Wenn Sie Glück haben, hat ihr lokales Repository den gesamten Verlauf der Übertragungen, Ihr Fehler wird mit frischem Code überschrieben, und nichts geht verloren. Aber was, wenn Sie nicht so viel Glück haben? Dann lesen Sie weiter!

Fall 1: Sie waren die letzte Person, die vor dem Fehler nach Master gepusht hat

Gute Nachrichten! Sie haben alles, was Sie brauchen, um Ihren Fehler rückgängig zu machen, direkt vor Ihren Augen. Schließen oder löschen Sie nur nicht Ihr Terminal. Gehen Sie zuerst in den Chat Ihres Teams und beichten Sie Ihre Sünden. Bitten Sie die Leute, für die nächste Minute oder so nicht am Projektarchiv herumzupfuschen, während Sie die Dinge in Ordnung bringen.

Suchen Sie in der Ausgabe des git push --force-Befehls in Ihrer Shell nach einer Zeile, die dieser ähnelt:

 + deadbeef...f00f00ba master -> master (forced update)

Die erste Gruppe von Symbolen (die wie das SHA-Präfix eines Commits aussieht) ist der Schlüssel zur Rettung. deadbeef ist Ihr letzter guter Commit an den master-Zweig, kurz bevor Sie Schaden anrichteten.

So müssen Sie nur… diesen Commit zurück zum master-Zweig schieben (Feuer mit Feuer bekämpfen!), und zwar über einen schlechten.

$ git push --force origin deadbeef:master

Glückwunsch! Du hast den Tag gerettet. Jetzt ist es an der Zeit, aus deinen Fehlern zu lernen.

Fall 2: Der Master wurde von jemand anderem geändert, bevor du es vermasselt hast

So, kurz bevor du git push --force gemacht hast, hat jemand einen Haufen Pull Requests geschlossen, und die master sieht jetzt nicht mehr wie deine lokale Kopie aus. Du kannst git push --force sha1:master nicht mehr machen, da du keine aktuellen Commits lokal hast (und du kannst sie nicht mit git fetch bekommen, da sie zu keinem Zweig mehr gehören). Bleiben Sie trotzdem ruhig und bitten Sie Ihre Teamkollegen, sich eine Weile vom Remote zu entfernen.

Wir werden davon profitieren, dass GitHub unerreichbare Commits nicht sofort entfernt. Natürlich kann man sie auch nicht abrufen, aber es gibt einen Workaround.

Bitte beachten Sie, dass dies nur funktioniert, wenn Sie das Repository „beobachten“, so dass alles, was darin passiert, in einem Feed auf der Startseite von GitHub angezeigt wird. Öffnen Sie diesen Feed und suchen Sie nach etwas wie diesem:

an hour agoUsername pushed to master at org/repo - deadbeef Implement foo - deadf00d Fix bar

Nun können Sie:

  • eine URL https://github.com/org/repo/tree/deadbeef verfassen, wobei deadbeef ein Hash des letzten guten Commits an den beschädigten Branch ist;
  • den Branches/Tags Switcher in der Web-UI von GitHub öffnen;

GitHub Branch/Tag Switcher

GitHub Branch/Tag Switcher

  • Erstelle einen Namen für einen neuen temporären Branch (z.g., master-before-force-push);
  • Klicken Sie auf „Zweig erstellen“.

Jetzt können Sie alle fehlenden Commits holen:

$ git fetchFrom github.com:org/repo * master-before-force-push -> origin/master-before-force-push

Ihr Problem ist jetzt auf das im vorherigen Beispiel beschriebene reduziert:

$ git push --force origin origin/master-before-force-push:master

Wenn du deine Arbeit immer noch in der master haben willst, dann rebase einfach darüber:

$ git rebase origin/master

Wie du solche Katastrophen in Zukunft vermeiden kannst

  1. GitHub und GitLab haben eine Funktion, die sich „geschützte Zweige“ nennt.“ Markieren Sie master, develop, stable oder jeden anderen wichtigen Zweig als geschützt und niemand kann einen Push in diese Zweige erzwingen. Es ist immer möglich, einen Zweig vorübergehend „ungeschützt“ zu machen, wenn Sie wirklich die Historie überschreiben müssen.

    Lesen Sie die GitHub-Dokumente für Details.

  2. Anstelle der Option --force, verwenden Sie --force-with-lease. Sie hält den Push-Vorgang an, wenn jemand in denselben Zweig gepusht hat, während Sie daran gearbeitet haben (und keine Änderungen gezogen haben).

    Siehe diesen Artikel von Atlassian.

  3. Erstelle Aliase für Befehle, die git push --force verwenden, um destruktive Aktionen aus Versehen zu verhindern:

    # ~/.gitconfig deploy = "!git push --force deis \"$(git rev-parse --abbrev-ref HEAD):master\""

    Lese das ProGit Kapitel über Aliase.

  4. Erstelle niemals deine Experimente im Hauptzweig eines Repositorys! git checkout -b experiments ist dein bester Freund.

Pro-Tipp: git push hat viele Optionen. --force und --all funktionieren besonders gut zusammen. Sie können diese Kombination verwenden, wenn Sie nach mehreren Monaten der Inaktivität zu dem Projekt zurückkehren. Probieren Sie es aus, wenn Sie sich besonders abenteuerlustig fühlen!

Leave a Reply