Git ziehen nach erzwungenem Update

332

Ich habe nur ein paar Commits mit gequetscht git rebaseund ein gemacht git push --force(was böse ist, ich weiß).

Jetzt haben die anderen Softwareentwickler eine andere Historie und wenn sie eine machen git pull, wird Git zusammengeführt. Gibt es eine Möglichkeit, dies zu beheben, außer eine rm my-repo; git clone [email protected]:my-repo.git?

Ich brauche so etwas wie das Gegenteil von git push --force, habe aber git pull --forcenicht die beabsichtigten Ergebnisse geliefert.

iblue
quelle
16
Sie können ihren Zweig löschen und auch neu erstellen, ohne das gesamte Repo löschen zu müssen:git checkout master && git branch -D test && git checkout -b test origin/test
Florian Klein

Antworten:

508

Um die neuen Commits zu erhalten

git fetch

Zurücksetzen

Sie können das Commit für einen lokalen Zweig mithilfe von zurücksetzen git reset.

So ändern Sie das Commit eines lokalen Zweigs:

git reset origin/master --hard

Seien Sie jedoch vorsichtig, wie es in der Dokumentation heißt:

Setzt den Index und den Arbeitsbaum zurück. Alle Änderungen an nachverfolgten Dateien im Arbeitsbaum seit <commit> werden verworfen.

Wenn Sie die Änderungen, die Sie lokal vorgenommen haben, tatsächlich beibehalten möchten, führen Sie --softstattdessen einen Reset durch. Dadurch wird der Festschreibungsverlauf für den Zweig aktualisiert, es werden jedoch keine Dateien im Arbeitsverzeichnis geändert (und Sie können sie dann festschreiben).

Rebase

Sie können Ihre lokalen Commits zusätzlich zu jedem anderen Commit / Zweig wiedergeben, indem Sie git rebase:

git rebase -i origin/master

Dadurch wird die Rebase im interaktiven Modus aufgerufen, in dem Sie auswählen können, wie jedes einzelne Commit angewendet werden soll, das nicht in dem Verlauf enthalten ist, auf dem Sie die Rebasis durchführen.

Wenn die Commits, die Sie entfernt haben (mit git push -f), bereits in den lokalen Verlauf aufgenommen wurden, werden sie als Commits aufgeführt, die erneut angewendet werden. Sie müssten im Rahmen der Neueinstellung gelöscht werden oder werden einfach wieder in den Verlauf aufgenommen für den Zweig - und erscheinen beim nächsten Push wieder in der Remote-Historie.

In der Hilfe finden Sie git command --helpweitere Details und Beispiele zu den oben genannten (oder anderen) Befehlen.

AD7six
quelle
2
@iblue Wählen Sie zwischen dem Verlust aller Änderungen, dem Entfernen des Festschreibungsverlaufs, dem Beibehalten der Dateiänderungen oder dem Versuch, jedes Festschreiben auf den neuen Kopf anzuwenden. Die einfachste Option ist wahrscheinlich ein Soft-Reset.
AD7six
1
@iblue Wenn Ihr Kollege "git reabse origin / master" verwendet und in der Zwischenzeit bereits ein Commit durchgeführt hat, schreibt git Ihr Commit hinter das Commit.
Tim
6
git reset origin/otherbranch --hard
Könnte
Also, um zu klären, ist dies entweder : Option 1: reset --hard, oder Option 2: reset --soft+ rebase, nicht wahr?
PlasmaBinturong
2
@PlasmaBinturong No. git reset --soft origin/masterändert den Festschreibungsverlauf so, dass die Unterschiede zwischen Fernbedienung und Stufe mit der Fernbedienung übereinstimmen, die dann festgeschrieben werden . In diesem Szenario wäre keine Neubasis erforderlich (und Sie würden aufgrund der nicht festgeschriebenen Änderungen daran gehindert), da es keinen Unterschied im Festschreibungsverlauf gibt. Die beiden Optionen sind Zurücksetzen oder Wiederherstellen - keine Kombination aus beiden. Bitte stellen Sie eine Frage, wenn Ihr Szenario anders ist als das, das ich hier beantwortet habe.
AD7six
16

Dadurch werden keine Zweige repariert, die bereits den Code enthalten, den Sie nicht möchten (siehe unten, wie das geht), aber wenn sie einen Zweig gezogen haben und jetzt möchten, dass er sauber ist (und nicht "voraus") Ursprung / irgendein Zweig) dann einfach:

git checkout some-branch   # where some-branch can be replaced by any other branch
git branch base-branch -D  # where base-branch is the one with the squashed commits
git checkout -b base-branch origin/base-branch  # recreating branch with correct commits

Hinweis: Sie können diese alle kombinieren, indem Sie && zwischen sie setzen

Anmerkung 2: Florian hat dies in einem Kommentar erwähnt, aber wer liest Kommentare, wenn er nach Antworten sucht?

Hinweis 3: Wenn Sie Zweige kontaminiert haben, können Sie neue Zweige erstellen, die auf dem neuen "dummen Zweig" basieren, und nur die Commits von Cherry Pick auswählen.

Ex:

git checkout feature-old  # some branch with the extra commits
git log                   # gives commits (write down the id of the ones you want)
git checkout base-branch  # after you have already cleaned your local copy of it as above
git checkout -b feature-new # make a new branch for your feature
git cherry-pick asdfasd   # where asdfasd is one of the commit ids you want
# repeat previous step for each commit id
git branch feature-old -D # delete the old branch

Jetzt ist Feature-New Ihre Filiale ohne die zusätzlichen (möglicherweise schlechten) Commits!

Tom Prats
quelle
Das wollte ich wirklich. Jemand hat den Hauptzweig neu gegründet (Gott weiß, aus welchem ​​Grund), aber ich hatte keine lokalen Änderungen daran, die ich begehen wollte, oder so. Also musste ich nur meinen lokalen Hauptzweig löschen (was sich wirklich komisch anfühlte) und erneut auschecken. Vielen Dank!
Danilo Carvalho
für den letzten Schritt können Sie auch git checkout -b base-branch origin/base-branchmitgit checkout --track origin/base-branch
bluesmonk
1

Mit Rebase ziehen

Ein regulärer Pull ist Fetch + Merge, aber was Sie wollen, ist Fetch + Rebase. Dies ist eine Option mit dem pullBefehl:

git pull --rebase
ihr Mann
quelle
Ich verwende dies die ganze Zeit, um den neuesten Code vom Master in meinen Feature-Zweig zu bekommen, ohne all diese Merge-Commits im Verlauf zu haben.
Hermann