Wie erzwinge ich einen Git-Push richtig?

1274

Ich habe ein nicht nacktes "Haupt" -Repo eingerichtet und auf meinen Computer geklont. Ich habe einige lokale Änderungen vorgenommen, mein lokales Repository aktualisiert und die Änderungen zurück auf mein Remote-Repo übertragen. Bis zu diesem Punkt war alles in Ordnung.

Jetzt musste ich etwas im Remote-Repo ändern. Dann habe ich etwas in meinem lokalen Repo geändert. Mir wurde klar, dass die Änderung am Remote-Repo nicht erforderlich war. Also habe ich versucht, git pushvon meinem lokalen Repo zu meinem Remote-Repo zu wechseln, aber ich habe eine Fehlermeldung erhalten wie:

Um zu verhindern, dass Sie den Verlauf verlieren, wurden Aktualisierungen ohne schnellen Vorlauf abgelehnt. Führen Sie die Remote-Änderungen zusammen, bevor Sie sie erneut übertragen. Weitere git push --helpInformationen finden Sie im Abschnitt "Hinweis zum Schnellvorlauf" .

Ich dachte das wahrscheinlich ein

git push --force

würde meine lokale Kopie zwingen, Änderungen an der Remote-Kopie zu übertragen und sie gleich zu machen. Das Update wird zwar erzwungen , aber wenn ich zum Remote-Repo zurückkehre und ein Commit durchführe, stelle ich fest, dass die Dateien veraltete Änderungen enthalten (die das Haupt-Remote-Repo zuvor hatte).

Wie ich in den Kommentaren zu einer der Antworten erwähnt habe :

[Ich] habe versucht zu erzwingen, aber wenn ich zum Master-Server zurückkehre, um die Änderungen zu speichern, bekomme ich veraltetes Staging. Wenn ich also festschreibe, sind die Repositorys nicht gleich. Und wenn ich versuche, Git Push erneut zu verwenden, erhalte ich den gleichen Fehler.

Wie kann ich dieses Problem beheben?

Spyros
quelle
4
Sie werden bald (git1.8.5, Q4 2013) in der Lage sein, dies git push -forcesorgfältiger zu tun .
VonC
6
Wie ich in meiner eigenen Antwort ausführlich darlege , git push --forceist dies in der Tat eine weitere gültige Methode, um Push zu erzwingen, und es werden genauso viele Zweige wie git push origin master --forcemit der Standardeinstellung push.default config settingsvon Git gepusht. Welche Zweige speziell verschoben werden, unterscheidet sich jedoch zwischen den Git-Versionen vor 2.0 und nach 2.0.
2
git push --forcefunktioniert heutzutage gut, FWIW ...
Rogerdpack
git push --force-with-leasefunktioniert noch besser :), es wird sich weigern, einen Zweig zu aktualisieren, es sei denn, es ist der Zustand, den Sie erwarten. (siehe developer.atlassian.com/blog/2015/04/force-with-lease )
spoorcc

Antworten:

2309

Mach einfach:

git push origin <your_branch_name> --force

oder wenn Sie ein bestimmtes Repo haben:

git push https://git.... --force

Dadurch werden Ihre vorherigen Commits gelöscht und Ihre aktuellen Commits verschoben.

Es mag nicht richtig sein, aber wenn jemand auf diese Seite stößt, dachte er, er möchte vielleicht eine einfache Lösung ...

Kurze Flagge

Beachten Sie auch, dass dies -fkurz --forceist

git push origin <your_branch_name> -f

wird auch funktionieren.

Katie
quelle
58
Sie können git push origin +masterstattdessen verwenden, wodurch Sie mehrere Referenzspezifikationen pushen können, ohne sie alle zu erzwingen.
Nickgrim
5
Seien Sie sich bewusst, dass Sie, wenn Sie dies versehentlich tun git push --force, möglicherweise Ihren
Hauptzweig durcheinander bringen
9
@Jeewes ab Git Version 2.0 besteht das Standardverhalten von git push --forcedarin, den aktuell ausgecheckten Zweig zwangsweise auf seinen Remote-Counter-Teil zu verschieben. Wenn Sie also den Hauptzweig ausgecheckt haben, ist er identisch mit git push origin master --force. Es ist anders, wenn Sie die matchingEinstellung für verwenden push.default, die die Standardeinstellung für Git-Versionen vor 2.0 ist. matchingschiebt alle lokalen Zweige zu entfernten Zweigen, die den gleichen Namen haben, so dass
@Jeewes Aber mit Git 2.0 ist die Standardeinstellung sicherer oder zumindest nicht gefährlicher als sie git push origin master --forceist.
2
push -f ist gut, wird jedoch für master nicht empfohlen, da in den meisten Unternehmensrepositorys -f für master deaktiviert ist. das merge -s oursarbeitete für mich
mihai
247

Und wenn push --forcees nicht funktioniert, können Sie es tun push --delete. Blick auf 2 nd Linie auf dieser Instanz:

git reset --hard HEAD~3  # reset current branch to 3 commits ago
git push origin master --delete  # do a very very bad bad thing
git push origin master  # regular push

Aber Vorsicht...

Gehen Sie niemals auf eine öffentliche Git-Geschichte zurück!

Mit anderen Worten:

  • Drücken Sie niemals forceauf ein öffentliches Repository.
  • Tu dies nicht oder irgendetwas, das jemandes kaputt machen kann pull.
  • Niemals resetoder rewriteGeschichte in einem Repo, die jemand vielleicht schon gezogen hat.

Natürlich gibt es auch bei dieser Regel außergewöhnlich seltene Ausnahmen, aber in den meisten Fällen ist dies nicht erforderlich und führt zu Problemen für alle anderen.

Führen Sie stattdessen ein Zurücksetzen durch.

Und seien Sie immer vorsichtig mit dem, was Sie zu einem öffentlichen Repo bringen . Zurücksetzen:

git revert -n HEAD~3..HEAD  # prepare a new commit reverting last 3 commits
git commit -m "sorry - revert last 3 commits because I was not careful"
git push origin master  # regular push

In der Tat, beide Herkunft HEADS (aus dem revert und aus dem bösen Reset ) die gleichen Dateien enthalten.


Bearbeiten, um aktualisierte Informationen und weitere Argumente hinzuzufügen push --force

Ziehen Sie in Betracht, die Kraft mit Leasing anstelle von Druck zu drücken, bevorzugen Sie jedoch das Zurücksetzen

Ein weiteres Problem push --forcekann sein, wenn jemand etwas drückt, bevor Sie es tun, aber nachdem Sie es bereits abgerufen haben. Wenn Sie Ihre neu basierte Version jetzt erzwingen, werden Sie die Arbeit anderer ersetzen .

git push --force-with-leaseeingeführt in git 1.8.5 ( dank @VonC Kommentar zu der Frage) versucht, dieses spezielle Problem zu beheben . Grundsätzlich wird es einen Fehler bringen und nicht pushen, wenn die Fernbedienung seit Ihrem letzten Abruf geändert wurde.

Dies ist gut, wenn Sie wirklich sicher sind, dass ein push --forcebenötigt wird, aber dennoch weitere Probleme vermeiden möchten. Ich würde so weit gehen zu sagen, dass es das Standardverhalten sein sollte push --force. Aber es ist noch weit davon entfernt, eine Ausrede zu sein, um a zu erzwingen push. Personen, die vor Ihrer Rebase abgerufen wurden, haben immer noch viele Probleme, die leicht vermieden werden könnten, wenn Sie stattdessen zurückgekehrt wären .

Und da es sich um git --pushInstanzen handelt ...

Warum sollte jemand Push erzwingen wollen?

@linquize brachte ein gutes Push-Force-Beispiel für die Kommentare: sensible Daten . Sie haben fälschlicherweise Daten verloren, die nicht übertragen werden sollten. Wenn Sie schnell genug sind, können Sie das Problem beheben* , indem Sie einen Druck auf die Oberseite erzwingen.

*Die Daten befinden sich weiterhin auf der Fernbedienung, es sei denn, Sie führen auch eine Speicherbereinigung durch oder bereinigen sie irgendwie . Es gibt auch das offensichtliche Potenzial, dass es von anderen verbreitet wird, die es bereits abgerufen haben, aber Sie haben die Idee.

Cregox
quelle
1
Das Problem, @rogerdpack, ist nicht, ob es machbar ist. Es ist. Aber es kann zu einer großen Katastrophe führen. Je mehr jemand es tut (Force Push) und je seltener Sie aus dem öffentlichen Repo aktualisieren (Pull), desto größer ist die Katastrophe. Es kann die Welt, wie Sie sie kennen, zerlegen !!! 111 Zumindest die Welt, die aus diesem bestimmten Repository besteht.
Cregox
3
Wenn Sie sensible Daten haben, erzwingen Sie Push-it
Linquize
3
@Cawas: Ich denke, er meint, wenn Sie versuchen, vertrauliche Daten aus dem Repository zu entfernen, möchten Sie den Verlauf neu schreiben. Wenn Sie zurücksetzen, sind die vertraulichen Daten im vorherigen Commit noch vorhanden. Wenn jedoch bereits jemand anderes aus dem Repository abgerufen hat, können Sie durch das Umschreiben des Verlaufs nicht verhindern, dass er auf die vertraulichen Daten zugreift. Zu diesem Zeitpunkt ist es bereits zu spät.
Stuart Golodetz
3
git push origin master --delete # do a very very bad bad thing git push origin master # regular pushDies löste mein Problem tatsächlich perfekt (auf einem Repo nur mit mir und meinem Freund). Vielleicht ist es falsch für öffentliche Repos, aber für private Repos ist dies ein Lebensretter.
Kann Poyrazoğlu
1
Dies geschieht automatisch, wenn einige Repo-Manager, auch bekannt als Auto-Squash usw., nach Abschluss eines Feature-Zweigs Druck ausüben, um Commits zu reduzieren. Dies ist üblich und wird erwartet.
FlavorScape
18

Zunächst einmal würde ich keine Änderungen direkt im "Haupt" -Repo vornehmen. Wenn Sie wirklich ein "Haupt" -Repo haben möchten, sollten Sie nur darauf drängen, es niemals direkt ändern.

Haben Sie es in Bezug auf den Fehler, den Sie erhalten, git pullvon Ihrem lokalen Repo und dann git pushzum Haupt-Repo versucht ? Was Sie gerade tun (wenn ich es gut verstanden habe), ist den Push zu erzwingen und dann Ihre Änderungen im "Haupt" -Repo zu verlieren. Sie sollten die Änderungen zuerst lokal zusammenführen.

ubik
quelle
Ja, ich habe einen Pull versucht, aber ich verliere den Verlust von Daten aufgrund dieses Pulls. Ich möchte meine Haupt-Repos so erstellen, wie meine lokalen sind, ohne vorher von der Haupt-Aktualisierung zu aktualisieren.
Spyros
1
In diesem Fall verwenden git push -f, aber wenn Sie Ihr Haupt-Repo erneut ändern, müssen Sie zu Ihrem lokalen Repo zurückkehren und git pull, damit es mit den neuesten Änderungen synchronisiert wird. Dann können Sie Ihre Arbeit erledigen und erneut drücken. Wenn Sie diesem "Push-Pull" -Workflow folgen, erhalten Sie nicht die Art von Fehler, über die Sie sich beschwert haben.
Ubik
Ja, ich verstehe, dass dies meine Schuld war: / Ich werde das versuchen und in kurzer Zeit zurückkommen. Danke
Spyros
1
Ich habe versucht zu erzwingen, aber wenn ich zum Master-Server zurückkehre, um die Änderungen zu speichern, bekomme ich veraltetes Staging. Wenn ich also festschreibe, sind die Repositorys nicht gleich. Und wenn ich versuche, Git Push erneut zu verwenden, erhalte ich den gleichen Fehler.
Spyros
17

Wenn ich mich in meinem lokalen Zweig A befinde und erzwingen möchte, dass der lokale Zweig B in den Ursprungszweig verschoben wird, kann CI die folgende Syntax verwenden:

git push --force origin B:C
IcedDante
quelle
2
Ich fand heraus, dass ich es auch in meiner Zweigstelle B noch tun muss git push --force origin B:C. In meinem Fall scheint dies git push --force origin Cnur vom lokalen Master zum Remote-C-Zweig zu führen, unabhängig davon, in welchem ​​Zweig ich mich gerade befinde. git version 2.3.8 (Apple Git-58)
Weishi Zeng
12

Verwenden Sie diesen folgenden Befehl:

git push -f origin master
mustafa Elsayed
quelle
1
Geben Sie vielleicht eine weitere Erklärung, warum diese Antwort den anderen vorzuziehen ist und was sie anders macht.
Adam
Oh, Entschuldigung für die Unannehmlichkeiten, ich hatte das gleiche Problem und dieser Befehl löste es. Ich dachte, ich sollte es teilen.
Mustafa Elsayed
12
Es ist genauso wie bei den anderen, Sie haben gerade die Position der -fFlagge geändert ...
svelandiag
11

Ich würde wirklich empfehlen:

Mit anderen Worten, halten Sie ein nacktes Repo sowohl vom Hauptserver als auch vom lokalen Computer aus zugänglich, um ein einziges Upstream-Repo von / zu dem Sie ziehen / ziehen können.

VonC
quelle
5

Dies war unsere Lösung zum Ersetzen des Masters in einem gitHub-Repository eines Unternehmens unter Beibehaltung des Verlaufs.

push -fDas Mastering in Unternehmens-Repositorys ist häufig deaktiviert, um den Filialverlauf zu verwalten. Diese Lösung hat bei uns funktioniert.

git fetch desiredOrigin
git checkout -b master desiredOrigin/master // get origin master

git checkout currentBranch  // move to target branch
git merge -s ours master  // merge using ours over master
// vim will open for the commit message
git checkout master  // move to master
git merge currentBranch  // merge resolved changes into master

Schieben Sie Ihre Niederlassung zu desiredOriginund erstellen Sie eine PR

mihai
quelle
3

Ich hatte die gleiche Frage, fand sie aber schließlich heraus. Am wahrscheinlichsten müssen Sie die folgenden zwei Git-Befehle ausführen (Hash durch die Git-Commit-Revisionsnummer ersetzen):

git checkout <hash>
git push -f HEAD:master
Brian M.
quelle