6424 Stimmen

Verschieben der letzten Übertragung(en) in einen neuen Zweig mit Git

Ich würde gerne die letzten Commits, die ich an Master übertragen habe, in einen neuen Zweig verschieben und Master auf den Stand vor diesen Commits zurückbringen. Leider ist mein Git-Fu noch nicht stark genug, kann mir jemand helfen?

D.h. Wie kann ich von diesem

master A - B - C - D - E

dazu?

newbranch     C - D - E
             /
master A - B

161 Stimmen

Anmerkung: Ich habe die gegenteilige Frage gestellt aquí

6 Stimmen

eddmann.com/posts/ dieser funktioniert

22 Stimmen

Wurden die Kommentare hier gelöscht? Ich frage, weil ich bei meinem zweimonatlichen Besuch dieser Frage immer an diesem Kommentar vorbeilaufe.

267voto

Slam Punkte 2817

Viel einfachere Lösung mit git stash

Hier ist eine viel einfachere Lösung für Übertragungen in den falschen Zweig. Starten im Zweig master die drei fehlerhafte Übertragungen aufweist:

git reset HEAD~3
git stash
git checkout newbranch
git stash pop

Wann ist dies zu verwenden?

  • Wenn Ihr Hauptzweck darin besteht, ein Rollback durchzuführen master
  • Sie möchten Datei-Änderungen behalten
  • Sie interessieren sich nicht für die Nachrichten über die falschen Übertragungen
  • Sie haben noch nicht geschoben
  • Sie wollen, dass Sie sich das leicht merken können
  • Sie wollen keine Komplikationen wie temporäre/neue Zweige, das Finden und Kopieren von Commit-Hashes und andere Kopfschmerzen

Was dies bedeutet, nach Zeilennummer

  1. Macht die letzten drei Übertragungen (und ihre Nachrichten) an master und lässt dennoch alle Arbeitsdateien intakt
  2. Speichert alle Änderungen in der Arbeitsdatei und macht die master der Arbeitsbaum entspricht genau dem Zustand HEAD~3
  3. Wechselt zu einem bestehenden Abzweig newbranch
  4. Wendet die versteckten Änderungen auf Ihr Arbeitsverzeichnis an und leert den Vorrat

Sie können nun Folgendes verwenden git add et git commit wie Sie es normalerweise tun würden. Alle neuen Übertragungen werden hinzugefügt zu newbranch .

Was dies nicht tut

  • Ihr Baum wird nicht durch zufällige, vorübergehende Äste verunstaltet.
  • Die fehlerhaften Commit-Meldungen bleiben nicht erhalten, Sie müssen also eine neue Commit-Nachricht zu diesem neuen Commit hinzufügen
  • Aktualisieren! Benutzen Sie die Pfeil-nach-oben-Taste, um durch Ihren Befehlspuffer zu blättern und die vorherige Übergabe mit ihrer Übergabemeldung erneut anzuwenden (danke @ARK)

Ziele

Der Auftraggeber gab an, dass das Ziel darin besteht, den Master auf den Stand vor den Übertragungen zurückzusetzen, ohne dass Änderungen verloren gehen, und diese Lösung erfüllt diese Aufgabe.

Ich mache das mindestens einmal pro Woche, wenn ich versehentlich neue Übertragungen an master anstelle von develop . Normalerweise habe ich nur einen Commit zum Rollback, in diesem Fall verwende ich git reset HEAD^ in Zeile 1 ist eine einfachere Möglichkeit, nur eine Übertragung zurückzunehmen.

Tun Sie dies nicht, wenn Sie die Änderungen des Masters upstream gepusht haben

Vielleicht hat jemand anderes diese Änderungen vorgenommen. Wenn Sie nur Ihren lokalen Master umschreiben, hat es keine Auswirkungen, wenn es upstream gepusht wird, aber das Pushen einer umgeschriebenen Historie an Mitwirkende kann Kopfschmerzen verursachen.

7 Stimmen

Danke, ich bin so froh, dass ich vorbei / durch so viel zu lesen, um hier zu bekommen, weil es eine ziemlich häufige Anwendungsfall für mich als gut ist. Sind wir so untypisch?

11 Stimmen

Ich denke, wir sind ganz typisch und "oops I commited to master by mistake" ist der häufigste Anwendungsfall für die Notwendigkeit, eine Handvoll oder weniger Commits zu revertieren. Zum Glück ist diese Lösung so einfach, dass ich sie mir jetzt gemerkt habe.

14 Stimmen

Dies sollte die akzeptierte Antwort sein. Sie ist einfach, leicht zu verstehen und leicht zu merken

37voto

Saikat Punkte 10782

Das ist der einfachste Weg, dies zu tun:

1. Umbenennen master Zweig zu Ihrem newbranch (vorausgesetzt, Sie sind auf master Zweig):

git branch -m newbranch

2. erstellen. master Zweig von der gewünschten Übergabe:

git checkout -b master <seven_char_commit_id>

z.B. git checkout -b master a34bc22

HINWEIS: Der Upstream für newbranch wäre origin/master .

2 Stimmen

Ich mag diese Lösung, weil man den Titel/die Beschreibung der Git-Übertragung nicht umschreiben muss.

17 Stimmen

Bringt das nicht die entfernten Upstream-Zweige durcheinander? Ist nicht newbranch die jetzt auf origin/master ?

3 Stimmen

Das funktioniert, hat aber auch dazu geführt, dass ich eine master die nicht mehr verfolgt origin/master . git branch -u origin/master master die Situation wiederhergestellt.

34voto

Sukima Punkte 9785

Dadurch werden sie zwar nicht im technischen Sinne "bewegt", aber es hat die gleiche Wirkung:

A--B--C  (branch-foo)
 \    ^-- I wanted them here!
  \
   D--E--F--G  (branch-bar)
      ^--^--^-- Opps wrong branch!

While on branch-bar:
$ git reset --hard D # remember the SHAs for E, F, G (or E and G for a range)

A--B--C  (branch-foo)
 \
  \
   D-(E--F--G) detached
   ^-- (branch-bar)

Switch to branch-foo
$ git cherry-pick E..G

A--B--C--E'--F'--G' (branch-foo)
 \   E--F--G detached (This can be ignored)
  \ /
   D--H--I (branch-bar)

Now you won't need to worry about the detached branch because it is basically
like they are in the trash can waiting for the day it gets garbage collected.
Eventually some time in the far future it will look like:

A--B--C--E'--F'--G'--L--M--N--... (branch-foo)
 \
  \
   D--H--I--J--K--.... (branch-bar)

1 Stimmen

Ja, Sie können alternativ auch Folgendes verwenden rebase auf dem abgetrennten Zweig in dem obigen Szenario.

30voto

teh_senaus Punkte 1327

Um dies zu tun, ohne die Geschichte umzuschreiben (d.h. wenn Sie die Commits bereits gepusht haben):

git checkout master
git revert <commitID(s)>
git checkout -b new-branch
git cherry-pick <commitID(s)>

Beide Äste können dann ohne Gewalt geschoben werden!

1 Stimmen

Aber dann müssen Sie sich mit dem Szenario der Rückgängigmachung befassen, was je nach den Umständen sehr viel schwieriger sein kann. Wenn Sie einen Commit auf dem Zweig rückgängig machen, sieht Git diese Commits immer noch als stattgefunden, so dass Sie, um das rückgängig zu machen, den Revert rückgängig machen müssen. Das ist für viele Leute ein Ärgernis, vor allem wenn sie eine Zusammenführung rückgängig machen und versuchen, den Zweig wieder zusammenzuführen, nur um festzustellen, dass Git glaubt, dass es den Zweig bereits zusammengeführt hat (was ja auch stimmt).

1 Stimmen

Deshalb wähle ich die Commits am Ende in einen neuen Zweig aus. Auf diese Weise sieht Git sie als neue Commits, was dein Problem löst.

0 Stimmen

Dies ist gefährlicher, als es auf den ersten Blick scheint, da Sie den Status der Historie des Repositorys ändern, ohne die Auswirkungen dieses Status wirklich zu verstehen.

14voto

Darkglow Punkte 673

Ich hatte genau diese Situation:

Branch one: A B C D E F     J   L M  
                       \ (Merge)
Branch two:             G I   K     N

Ich bin aufgetreten:

git branch newbranch 
git reset --hard HEAD~8 
git checkout newbranch

Ich hatte erwartet, dass Commit I der HEAD sein würde, aber jetzt ist es Commit L...

Um sicher zu sein, dass man an der richtigen Stelle in der Historie landet, ist es einfacher, mit dem Hash des Commits zu arbeiten

git branch newbranch 
git reset --hard #########
git checkout newbranch

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X