Ich möchte die letzten Commits, für die ich mich verpflichtet habe, in einen neuen Zweig verschieben und den Master zurückbringen, bevor diese Commits gemacht wurden. Leider ist mein Git-Fu noch nicht stark genug, Hilfe?
Dh wie kann ich davon ausgehen?
master A - B - C - D - E
dazu?
newbranch C - D - E
/
master A - B
git
git-branch
branching-and-merging
Mark A. Nicolosi
quelle
quelle
Antworten:
Umzug in eine bestehende Filiale
Wenn Sie Ihre Commits in einen vorhandenen Zweig verschieben möchten, sieht dies folgendermaßen aus:
Die
--keep
Option behält alle nicht festgeschriebenen Änderungen bei, die Sie möglicherweise in nicht verwandten Dateien vorgenommen haben, oder bricht ab, wenn diese Änderungen überschrieben werden müssten - ähnlich wie dies dergit checkout
Fall ist. Wenn es abgebrochen wird,git stash
Ihre Änderungen und versuchen Sie es erneut oder verwenden Sie--hard
, um die Änderungen zu verlieren (auch von Dateien, die sich zwischen den Commits nicht geändert haben!)Umzug in einen neuen Zweig
Diese Methode erstellt einen neuen Zweig mit dem ersten Befehl (
git branch newbranch
), wechselt jedoch nicht zu diesem. Dann rollen wir den aktuellen Zweig (Master) zurück und wechseln zum neuen Zweig, um weiter zu arbeiten.Aber stellen Sie sicher, wie viele Commits zurückgehen. Alternativ können Sie stattdessen
HEAD~3
einfach den Hash des Commits (oder die Referenz wieorigin/master
) angeben, auf die Sie zurückgreifen möchten, z.WARNUNG: Wenn Sie mit Git Version 2.0 und höher später
git rebase
den neuen Zweig auf den ursprünglichen (master
) Zweig setzen, benötigen Sie möglicherweise--no-fork-point
während der Rebase eine explizite Option, um zu vermeiden, dass die Commits verloren gehen, die Sie aus dem Master-Zweig verschoben haben. Dasbranch.autosetuprebase always
Setzen macht dies wahrscheinlicher. Siehe John Mellors Antwort für Details.quelle
Für diejenigen, die sich fragen, warum es funktioniert (wie ich es zuerst war):
Sie möchten zu C zurückkehren und D und E in den neuen Zweig verschieben. So sieht es zunächst aus:
Nachher
git branch newBranch
:Nachher
git reset --hard HEAD~2
:Da ein Zweig nur ein Zeiger ist, zeigte der Master auf das letzte Commit. Wenn Sie newBranch erstellt haben , haben Sie einfach einen neuen Zeiger auf das letzte Commit erstellt. Dann haben
git reset
Sie mit dem Master- Zeiger zwei Commits zurückbewegt. Da Sie newBranch jedoch nicht verschoben haben , verweist es immer noch auf das Commit, das es ursprünglich ausgeführt hat.quelle
git push origin master --force
damit die Änderung im Haupt-Repository angezeigt wurde.git rebase
werden die 3 Commits stillschweigend verworfennewbranch
. Siehe meine Antwort für Details und sicherere Alternativen.origin/master
dies im obigen Diagramm nicht angezeigt wird. Wenn Sieorigin/master
die obigen Änderungen vorgenommen und dann vorgenommen hätten, würden die Dinge sicher lustig werden. Aber das ist ein "Doktor, es tut weh, wenn ich das mache" -Problem. Und es ist nicht möglich für das, was die ursprüngliche Frage gestellt hat. Ich schlage vor, Sie schreiben Ihre eigene Frage, um Ihr Szenario zu untersuchen, anstatt diese zu entführen.git branch -t newbranch
". Geh zurück und lies die Antworten noch einmal. Niemand schlug vor, das zu tun.newbranch
auf ihrer bestehenden lokalenmaster
Niederlassung basieren möchten . Nach der akzeptierten Antwort durchgeführt wird , wenn der Benutzer auf herumlaufen wirdgit rebase
innewbranch
git wird sie daran erinnert , dass sie den vorgeschalteten Zweig zu setzen vergessen haben, so dass sie laufen werdengit branch --set-upstream-to=master
danngit rebase
und das gleiche Problem haben. Sie können genauso gutgit branch -t newbranch
in erster Linie verwenden.Allgemein...
Die von sykora exponierte Methode ist in diesem Fall die beste Option. Aber manchmal ist es nicht die einfachste und es ist keine allgemeine Methode. Verwenden Sie für eine allgemeine Methode Git Cherry-Pick :
Um das zu erreichen, was OP will, ist es ein zweistufiger Prozess:
Schritt 1 - Notieren Sie, welche Commits vom Master Sie auf einem möchten
newbranch
Ausführen
Beachten Sie die Hashes von (sagen wir 3) Commits, für die Sie möchten
newbranch
. Hier werde ich verwenden:C Commit:
9aa1233
D Commit:
453ac3d
E Commit:
612ecb3
Schritt 2 - Legen Sie sie auf die
newbranch
ODER (auf Git 1.7.2+ Bereiche verwenden)
Git Cherry-Pick wendet diese drei Commits auf Newbranch an.
quelle
Noch eine andere Möglichkeit, dies mit nur 2 Befehlen zu tun. Hält auch Ihren aktuellen Arbeitsbaum intakt.
Alte Version - bevor ich davon erfuhr
git branch -f
In der Lage zu
push
sein.
ist ein schöner Trick zu wissen.quelle
git branch -f
hier?.
ist aktueller Direktor. git kann auf REMOTES- oder GIT-URLs pushen.path to local directory
wird Git URLs Syntax unterstützt. Siehe den Abschnitt GIT-URLs ingit help clone
.Die meisten vorherigen Antworten sind gefährlich falsch!
Mach das nicht:
Wenn Sie das nächste Mal
git rebase
(odergit pull --rebase
) diese 3 Commits ausführen, werden diese stillschweigend verworfennewbranch
! (siehe Erklärung unten)Tun Sie stattdessen Folgendes:
--keep
ist wie--hard
, aber sicherer, da es fehlschlägt, anstatt nicht festgeschriebene Änderungen wegzuwerfen).newbranch
.newbranch
. Da sie nicht durch einen Zweig mehr referenziert wird, tut es , daß durch Gits mit reflog :HEAD@{2}
ist der Commit , dassHEAD
vor 2 Operationen Bezug zu nehmen, das heißt , bevor wir 1 ausgechecktnewbranch
und 2 verwendetgit reset
die 3 Commits zu verwerfen.Warnung: Das Reflog ist standardmäßig aktiviert. Wenn Sie es jedoch manuell deaktiviert haben (z. B. mithilfe eines "nackten" Git-Repositorys), können Sie die 3 Commits nach dem Ausführen nicht zurückerhalten
git reset --keep HEAD~3
.Eine Alternative, die sich nicht auf das Reflog stützt, ist:
(Wenn Sie es vorziehen, können Sie
@{-1}
anstelle des zuvor ausgecheckten Zweigs schreibenoldbranch
).Technische Erklärung
Warum sollten
git rebase
die 3 Commits nach dem ersten Beispiel verworfen werden? Es ist , weilgit rebase
ohne Argumente , die ermöglicht--fork-point
Option standardmäßig, die die lokale reflog verwendet , um zu versuchen , gegen den Upstream - Zweig den Zwang geschoben robust.Angenommen, Sie haben Origin / Master abgezweigt, als er Commits M1, M2, M3 enthielt, und dann selbst drei Commits durchgeführt:
aber dann schreibt jemand die Geschichte neu, indem er origin / master zwangsweise drückt, um M2 zu entfernen:
Wenn Sie Ihr lokales Reflog verwenden,
git rebase
können Sie feststellen, dass Sie sich von einer früheren Inkarnation des Ursprungs- / Hauptzweigs getrennt haben und daher die Commits M2 und M3 nicht wirklich Teil Ihres Themenzweigs sind. Daher wird davon ausgegangen, dass Sie M2, da es aus dem Upstream-Zweig entfernt wurde, auch nicht mehr in Ihrem Themenzweig haben möchten, sobald der Themenzweig neu basiert:Dieses Verhalten ist sinnvoll und im Allgemeinen beim erneuten Basieren richtig.
Der Grund, warum die folgenden Befehle fehlschlagen:
liegt daran, dass sie das Reflog im falschen Zustand belassen. Git sieht aus,
newbranch
als hätte er den Upstream-Zweig bei einer Revision, die die 3 Commits enthält, abgebrochen. Anschließend wird derreset --hard
Upstream-Verlauf neu geschrieben, um die Commits zu entfernen. Wenn Siegit rebase
ihn das nächste Mal ausführen , werden sie wie alle anderen Commits verworfen, die aus dem Upstream entfernt wurden.In diesem speziellen Fall möchten wir jedoch, dass diese drei Commits als Teil des Themenzweigs betrachtet werden. Um dies zu erreichen, müssen wir den Upstream bei der früheren Revision abzweigen, die die 3 Commits nicht enthält. Das ist, was meine vorgeschlagenen Lösungen tun, daher lassen beide das Reflog im richtigen Zustand.
Weitere Informationen finden Sie in der Definition von
--fork-point
in den Dokumenten git rebase und git merge-base .quelle
master
. Also nein, sie sind nicht gefährlich falsch.-t
Sie sich beziehen,git branch
geschieht implizit, wenn Sie festgelegt habengit config --global branch.autosetuprebase always
. Selbst wenn Sie dies nicht tun, habe ich Ihnen bereits erklärt , dass das gleiche Problem auftritt, wenn Sie das Tracking nach dem Ausführen dieser Befehle einrichten, wie dies das OP aufgrund seiner Frage wahrscheinlich beabsichtigt.Viel einfachere Lösung mit Git Stash
Hier ist eine weitaus einfachere Lösung für Commits in den falschen Zweig. Beginnend mit einem Zweig
master
mit drei falschen Commits:Wann soll man das benutzen?
master
Was dies tut, nach Zeilennummer
master
, lässt jedoch alle Arbeitsdateien intaktmaster
Arbeitsbaum genau dem Status HEAD ~ 3 entsprichtnewbranch
Sie können jetzt
git add
undgit commit
wie gewohnt verwenden. Alle neuen Commits werden hinzugefügtnewbranch
.Was das nicht macht
Tore
Das OP erklärte, das Ziel sei es, "den Master zurückzubringen, bevor diese Commits gemacht wurden", ohne Änderungen zu verlieren, und diese Lösung tut dies.
Ich mache das mindestens einmal pro Woche, wenn ich versehentlich neue Commits mache,
master
anstattdevelop
. Normalerweise habe ich nur ein Commit für das Rollback. In diesem Fall ist die Verwendunggit reset HEAD^
von Zeile 1 eine einfachere Möglichkeit, nur ein Commit zurückzusetzen.Tun Sie dies nicht, wenn Sie die Änderungen des Masters vorgelagert haben
Möglicherweise hat jemand anderes diese Änderungen vorgenommen. Wenn Sie nur Ihren lokalen Master neu schreiben, hat dies keine Auswirkungen, wenn er vorgelagert wird. Das Weiterleiten eines neu geschriebenen Verlaufs an Mitarbeiter kann jedoch zu Kopfschmerzen führen.
quelle
git add
als auch diegit commit
Befehle, die ich verwendet habe, also musste ich nur den Pfeil treffen und ein paar Mal eintreten und boomen! Alles war zurück, aber jetzt auf dem richtigen Ast.Dies "bewegt" sie nicht im technischen Sinne, hat aber den gleichen Effekt:
quelle
rebase
für das gleiche verwenden?rebase
im obigen Szenario alternativ den getrennten Zweig verwenden.So tun Sie dies, ohne den Verlauf neu zu schreiben (dh wenn Sie die Commits bereits verschoben haben):
Beide Äste können dann kraftlos geschoben werden!
quelle
Hatte gerade diese Situation:
Ich führte auf:
Ich habe erwartet, dass Commit ich der KOPF sein würde, aber Commit L ist es jetzt ...
Um sicherzugehen, dass Sie an der richtigen Stelle in der Geschichte landen, ist es einfacher, mit dem Hash des Commits zu arbeiten
quelle
Wie kann ich davon ausgehen?
dazu?
Mit zwei Befehlen
geben
und
geben
quelle
Wenn Sie nur alle Ihre nicht gepussten Commits in einen neuen Zweig verschieben müssen , müssen Sie nur:
Erstellen Sie einen neuen Zweig aus dem aktuellen:
git branch new-branch-name
Schieben Sie Ihren neuen Zweig :
git push origin new-branch-name
Setzen Sie Ihren alten (aktuellen) Zweig auf den letzten Push / Stable-Status zurück:
git reset --hard origin/old-branch-name
Einige Leute haben auch andere,
upstreams
anstattorigin
sie angemessen zu verwendenupstream
quelle
1) Erstellen Sie einen neuen Zweig, der alle Ihre Änderungen in new_branch verschiebt.
2) Dann gehe zurück zum alten Zweig.
3) Git Rebase
4) Dann enthält der geöffnete Editor die letzten 3 Festschreibungsinformationen.
5) Änderung
pick
androp
in all den drei Commits. Speichern und schließen Sie dann den Editor.6) Jetzt werden die letzten 3 Commits aus dem aktuellen Zweig entfernt (
master
). Drücken Sie nun den Zweig mit dem+
Vorzeichen vor dem Namen des Zweigs kräftig .quelle
Sie können dies tun, ist nur 3 einfache Schritt, die ich verwendet habe.
1) Erstellen Sie einen neuen Zweig, in dem Sie das letzte Update festschreiben möchten.
git branch <branch name>
2) Suchen Sie die letzte Commit-ID für das Commit für einen neuen Zweig.
git log
3) Kopieren Sie diese Festschreibungs-ID. Beachten Sie, dass die Liste der zuletzt festgeschriebenen Festschreibungen oben steht. So können Sie Ihr Commit finden. Sie finden dies auch per Nachricht.
git cherry-pick d34bcef232f6c...
Sie können auch eine Reihe von Festschreibungs-IDs angeben.
git cherry-pick d34bcef...86d2aec
Jetzt ist deine Arbeit erledigt. Wenn Sie die richtige ID und den richtigen Zweig ausgewählt haben, werden Sie Erfolg haben. Seien Sie also vorsichtig, bevor Sie dies tun. Andernfalls kann ein anderes Problem auftreten.
Jetzt können Sie Ihren Code pushen
git push
quelle
Ein anderer Weg, dies zu tun:
[1] Benennen Sie den
master
Zweig in Ihren umnewbranch
(vorausgesetzt, Sie befinden sich immaster
Zweig):[2] Erstellen Sie einen
master
Zweig aus dem gewünschten Commit:quelle