Git nicht schneller Vorlauf abgelehnt

88

Ich habe das Gefühl, dass diese Frage schon oft gestellt wurde, aber die Lösung lautet normalerweise "Ich habe das Verzeichnis gelöscht und meine Arbeit mit einer neuen Kasse wiederholt." Ich habe ein Commit und Push durchgeführt, aber festgestellt, dass ich in der Commit-Nachricht auf die falsche Ticketnummer verwiesen habe. Also suchte ich bei SO nach einer schnellen Lösung und tippte am Ende Folgendes in das Terminal ein:

$ git reset --soft HEAD^
$ git commit -m "... correct message ..."

Das einzige Problem ist, dass ich die folgende Fehlermeldung erhalte:

To prevent you from losing history, non-fast-forward updates were rejected
Merge the remote changes before pushing again.  See the 'Note about
fast-forwards' section of 'git push --help' for details.

Ich verwende das Git-Flow-Modell und arbeite am Entwicklungszweig. Wie kann ich Dinge wieder zusammenführen, um Git wieder glücklich zu machen?

rynmrtn
quelle

Antworten:

52

Kraft git push:

git push origin +develop
Alan Haggai Alavi
quelle
24
Das ist eine Lösung, aber lesen Sie den Kommentar von Brian Campbell, damit Sie verstehen, was Sie tun, bevor Sie dies verwenden.
Thelem
5
Git Push Origin + Master
Aniket Thakur
Siehe auch den Hinweis receive.denyNonFastForwardsin Brian Campbells Antwort : +oder --forcemöglicherweise nicht ausreichend aussagekräftig, je nachdem, wie sie - wer auch immer sie sind - ihr Git-Repository konfiguriert haben .
Torek
174

Wenn Sie ein Commit an den Server schieben, und dann neu zu schreiben , die lokal zu begehen (mit git reset, git rebase, git filter-branchoder jede andere Geschichte Manipulation), und dann schob die neu geschriebenen verpflichten zurück bis zu dem Server, wird schrauben Sie auf alle anderen , die gezogen hatte. Hier ist ein Beispiel; Angenommen, Sie haben A festgeschrieben und auf den Server übertragen.

- * - * - Ein <- Meister

- * - * - A <- Ursprung / Master

Jetzt beschließen Sie, A auf die von Ihnen erwähnte Weise neu zu schreiben, zurückzusetzen und erneut festzuschreiben. Beachten Sie, dass dies ein baumelndes Commit A hinterlässt, das schließlich als Müll gesammelt wird, da es nicht erreichbar ist.

-*-*-EIN
    \.
     Ein Meister

- * - * - A <- Ursprung / Master

Wenn jemand anderes, sagen wir Fred, masterwährenddessen vom Server herunterfährt , hat er einen Verweis auf A, von dem aus er möglicherweise mit der Arbeit beginnt:

- * - * - Ein '<- Meister

- * - * - A <- Ursprung / Master

- * - * - AB <- Fred / Master

Wenn Sie nun in der Lage wären, Ihr A 'zum Ursprung / Master zu verschieben, was einen nicht schnellen Vorlauf erzeugen würde, hätte es kein A in seiner Geschichte. Wenn Fred also erneut versuchen würde zu ziehen, müsste er plötzlich zusammengeführt werden und würde das A-Commit wieder einführen:

- * - * - Ein '<- Meister

- * - * - A <- Ursprung / Master

- * - * - AB- \ 
    \ * <- Fred / Master
     EIN'--/

Wenn Fred dies bemerkt, könnte er eine Rebase durchführen, die verhindern würde, dass Commit A wieder erscheint. Aber er würde das bemerken und daran denken müssen; und wenn Sie mehr als eine Person haben, die A nach unten gezogen hat, müssten sie alle neu gründen, um zu vermeiden, dass das zusätzliche A-Commit in den Baum aufgenommen wird.

Daher ist es im Allgemeinen keine gute Idee, die Geschichte eines Repos zu ändern, aus dem andere Leute ziehen. Wenn Sie jedoch zufällig wissen, dass niemand anderes aus diesem Repo zieht (zum Beispiel ist es Ihr eigenes privates Repo, oder Sie haben nur einen anderen Entwickler, der an dem Projekt arbeitet, mit dem Sie sich leicht koordinieren können), können Sie dies mit Gewalt tun Update durch Ausführen von:

git push -f

oder

git push origin +master

Diese ignorieren beide die Überprüfung auf einen nicht schnellen Vorlauf und aktualisieren die Daten auf dem Server auf Ihre neue A'-Revision, wobei die A-Revision abgebrochen wird, damit sie schließlich als Müll gesammelt wird.

Es ist möglich, dass Force Pushs mit der receive.denyNonFastForwardsKonfigurationsoption vollständig deaktiviert werden . Diese Option ist standardmäßig für freigegebene Repositorys aktiviert. In diesem Fall ist es die beste Option, den Zweig zu löschen und ihn mit neu zu erstellen, wenn Sie einen Push wirklich erzwingen möchten git push origin :master; git push origin master:master. Die denyNonFastForwardsOption ist jedoch aus einem oben beschriebenen Grund aktiviert. In einem gemeinsam genutzten Repository bedeutet dies, dass jetzt jeder, der es verwendet, sicherstellen muss, dass er auf den neuen Verlauf zurückgreift.

In einem gemeinsam genutzten Repository ist es im Allgemeinen besser, nur neue Commits nach oben zu verschieben, um das Problem zu beheben. Sie können git revertCommits generieren, mit denen die Änderungen früherer Commits rückgängig gemacht werden.

Brian Campbell
quelle
Tolle Ausbildung, und Sie haben am Ende das Kommando erhalten, aber mein Zweig hieß Entwickeln (basierend auf Git-Flow), und der andere Typ hat +developsein Kommando eingegeben - also geht der Scheck an ihn. Sie haben sowieso eine astronomische Anzahl von Punkten: P
rynmrtn
7
Oder verwenden Sie die weniger kryptischegit push --force
Bennett McElwee
3
@Panique Sie versuchen, mehreren Personen die gleichzeitige Arbeit an einer großen, komplexen Codebasis zu ermöglichen, ohne sich gegenseitig zu blockieren (sodass jeweils nur eine Person daran arbeiten kann) und ohne dass Änderungen sich gegenseitig überschreiben. Sie benötigen jede Person, um Änderungen unabhängig vornehmen und diese Änderungen zusammenführen zu können. Das Zusammenführen (manuell oder automatisch) kann zu unerwarteten Problemen führen. Sie möchten also so viele Informationen wie möglich aufbewahren, um herauszufinden, was passiert ist, wenn ein Fehler aufgetreten ist. Dies ist an sich komplex; Es ist nicht schmutzig, nur ein schweres Problem.
Brian Campbell
Ich habe sowohl die Option -f als auch die Option + ausprobiert, um den Remote-Repo-Verlauf neu zu schreiben. Bei beiden Optionen stieß ich auf ein Problem mit nicht schnellem Vorlauf. [5:05 PM] $ git push -f origin local_A: remote_A Objekte zählen: 35, erledigt. Delta-Komprimierung mit bis zu 2 Threads. Objekte komprimieren: 100% (18/18), fertig. Objekte schreiben: 100% (21/21), 7,41 KiB, fertig. Insgesamt 21 (Delta 9), wiederverwendete 0 (Delta 0) Remote: Um zu verhindern, dass Sie den Verlauf verlieren, wurden Aktualisierungen ohne schnellen Vorlauf abgelehnt. Führen Sie die Remote-Änderungen (z. B. "Git Pull") zusammen, bevor Sie erneut drücken. Weitere Informationen finden Sie im Abschnitt "Hinweis zum Schnellvorlauf" von "git push --help".
Srikanth
4
@Srikanth Mit der receive.denyNonFastForwardsKonfigurationsoption können erzwungene Pushs vollständig deaktiviert werden . Diese Option ist standardmäßig für freigegebene Repositorys aktiviert. In diesem Fall ist es die beste Option, den Zweig zu löschen und ihn mit neu zu erstellen, wenn Sie einen Push wirklich erzwingen möchten git push origin :remote_A; git push origin local_A:remote_A. Aber lesen Sie, was ich oben darüber geschrieben habe, warum es eine schlechte Idee ist, diese Art von Workflow in einem gemeinsam genutzten Repository durchzuführen. Sie sollten versuchen, dies nur zu tun, wenn Sie etwas haben, das ernsthafte Probleme beim Festschreiben verursacht, das Sie entfernen oder neu schreiben möchten.
Brian Campbell
14

Möglicherweise müssen Sie eine git pullAktion ausführen, die möglicherweise automatisch für Sie zusammengeführt wird. Dann können Sie erneut festschreiben. Wenn Sie Konflikte haben, werden Sie aufgefordert, diese zu lösen.

Denken Sie daran, dass Sie angeben müssen, aus welchem ​​Zweig Sie ziehen möchten, wenn Sie Ihre gitconfig nicht aktualisiert haben, um anzugeben ...

Beispielsweise:

git pull origin develop:develop
Tony
quelle
Immer noch verrückt nach nicht schnellem Vorlauf. Irgendwelche Gedanken darüber, wie man es zum Zusammenführen zwingt? ! [rejected] develop -> develop (non-fast-forward)
Rynmrtn
Ich denke, der Schalter ist -f, aber ich könnte mich irren. kernel.org/pub/software/scm/git/docs/git-pull.html
Tony
Dies funktioniert teilweise. Ich sehe die Updates auf Github jedoch nicht (es zeigt das vorherige Commit als das neueste sogar mit einem git push origin develop)
rynmrtn
7

Ich habe EGit verwendet und war auch mit diesem Problem konfrontiert. Ich habe gerade versucht, rebasedie aktuelle Filiale und es hat funktioniert.

Nguyen Minh Binh
quelle