Wie kopiere ich Commits von einem Zweig in einen anderen?

728

Ich habe zwei Zweige von meinem Meister:

  • v2.1 : (Version 2) Ich arbeite seit mehreren Monaten daran
  • wss : das ich gestern erstellt habe, um meinem Master eine bestimmte Funktion hinzuzufügen (in Produktion)

Gibt es eine Möglichkeit, die gestrigen Commits von wss nach v2.1 zu kopieren?

Bob Walsh
quelle
Um einfach Commits (oder eine Reihe von Commits) von einem Zweig in einen anderen zu kopieren,
caramba

Antworten:

565

Sie sollten wirklich einen Workflow haben, mit dem Sie dies alles durch Zusammenführen tun können:

- x - x - x (v2) - x - x - x (v2.1)
           \
            x - x - x (wss)

Alles was Sie tun müssen ist git checkout v2.1und git merge wss. Wenn Sie dies aus irgendeinem Grund wirklich nicht tun können und Sie git rebase nicht verwenden können , um Ihren wss-Zweig an die richtige Stelle zu verschieben, lautet der Befehl, ein einzelnes Commit von irgendwoher abzurufen und an anderer Stelle anzuwenden, git cherry-pick . Schauen Sie sich einfach den Zweig an, auf den Sie ihn anwenden möchten, und führen Sie ihn aus git cherry-pick <SHA of commit to cherry-pick>.

Einige der Möglichkeiten, wie Rebase Sie retten kann:

Wenn Ihre Geschichte so aussieht:

- x - x - x (v2) - x - x - x (v2.1)
           \
            x - x - x (v2-only) - x - x - x (wss)

Sie können git rebase --onto v2 v2-only wsswss verwenden , um wss direkt auf v2 zu verschieben:

- x - x - x (v2) - x - x - x (v2.1)
          |\
          |  x - x - x (v2-only)
           \
             x - x - x (wss)

Dann können Sie zusammenführen! Wenn Sie wirklich, wirklich, wirklich nicht an den Punkt gelangen, an dem Sie zusammenführen können, können Sie Rebase verwenden, um mehrere Kirschpicks gleichzeitig effektiv auszuführen:

# wss-starting-point is the SHA1/branch immediately before the first commit to rebase
git branch wss-to-rebase wss
git rebase --onto v2.1 wss-starting-point wss-to-rebase
git checkout v2.1
git merge wss-to-rebase

Hinweis: Der Grund dafür ist zusätzliche Arbeit, da doppelte Commits in Ihrem Repository erstellt werden. Dies ist nicht wirklich eine gute Sache - der springende Punkt beim einfachen Verzweigen und Zusammenführen ist, dass Sie alles tun können, indem Sie Commits an einem Ort platzieren und sie dort zusammenführen, wo sie benötigt werden. Doppelte Commits bedeuten die Absicht, diese beiden Zweige niemals zusammenzuführen (wenn Sie sich später dazu entschließen, treten Konflikte auf).

Cascabel
quelle
1
Konnte dieser Antwort nicht mehr zustimmen. +1. Siehe auch meine alte Antwort, um die Konsequenzen des Kirschpflückens zu veranschaulichen: stackoverflow.com/questions/881092/…
VonC
18
Hervorragende Antwort darauf, wie man das richtig macht ! Ich wünschte, ich könnte zweimal für die Erstellung von ASCII-Diagrammen stimmen.
Gotgenes
@VonC: Danke für die Unterstützung und die zusätzlichen Informationen, warum man nicht Kirschen pflücken sollte - ich weiß, dass ich dort ein wenig gespart habe. @gotgenes: Danke! Ich denke, die Mühe lohnt sich auf jeden Fall - schauen Sie sich einfach die git-rebase-Manpage an. Es gibt keinen besseren Weg, es zu erklären.
Cascabel
Warum Sie möglicherweise nicht zusammenführen können - Git-Zusammenführung funktioniert mit git-svn nicht gut. Um eine Reihe von Commits von einem SVN-Zweig in einen anderen zu kopieren, habe ich sie ausgewählt und dann ein interaktives Rebase / Reword durchgeführt, um die falschen git-svn-idReferenzen zu entfernen, bevor ich sie erneut erfülle dcommit. Obwohl ich wahrscheinlich den Kirschpflückschritt hätte weglassen und einfach eine Rebase alleine verwenden können.
Bob
1
Hier ist mein Anwendungsfall: Kritische Fehlerkorrekturen wurden für den Feature-Zweig festgelegt. Ich brauche es im Master, um jetzt in Produktion zu gehen. Das wird meinen Hintern retten.
Kapitän Hypertext
910

Verwenden

git cherry-pick <commit>

um sich <commit>auf Ihre aktuelle Niederlassung zu bewerben .

Ich selbst würde wahrscheinlich die Commits, die ich eingebe, überprüfen gitkund sie stattdessen mit Rechtsklicks auf den Commit-Eintrag dort auswählen.


Wenn Sie automatischer vorgehen möchten (mit all seinen Gefahren) und davon ausgehen möchten, dass alle Commits seit gestern auf wss stattgefunden haben, können Sie die Liste der Commits mit git log( --prettyvon Jefromi vorgeschlagen) erstellen.

git log --reverse --since=yesterday --pretty=%H

Also alles zusammen, vorausgesetzt du verwendest bash

for commit in $(git log --reverse --since=yesterday --pretty=%H);
do
    git cherry-pick $commit
done

Wenn hier etwas schief geht (es gibt viel Potenzial), sind Sie in Schwierigkeiten, da dies beim Live-Checkout funktioniert. Führen Sie also entweder manuelle Cherry-Picks durch oder verwenden Sie die von Jefromi vorgeschlagene Rebase.

Benjamin Bannier
quelle
Alle Platzhalter für die Option --pretty befinden sich in der git-log-Manpage. Sie können jedes gewünschte Format erhalten - besonders nützlich, um die gewünschten Felder für ein Skript in einer leicht analysierbaren Form abzurufen.
Cascabel
Ich möchte auch darauf hinweisen, dass die git rebasein meiner Antwort verwendete Methode robuster ist , vorausgesetzt, Sie möchten wirklich doppelte Commits erstellen . Insbesondere bei Verwendung einer solchen for-Schleife wird immer noch versucht, den Rest zu erledigen, wenn einer der Cherry-Picks fehlschlägt. Das ist ... sehr, nicht gut, sagen wir mal.
Cascabel
2
Einverstanden. Deshalb benutze ich es nie, sondern mache es manuell. Aber Kirschbaum ist immer noch die Antwort, zumindest auf den Fragentitel. Ich habe die Antwort geändert.
Benjamin Bannier
1
Jemand, der sich für einen alten / falschen Zweig entschieden hat, und Cherry-Pick lassen mich diesen Commit in den richtigen Zweig einfügen (während ich sie weiterhin als Committer behalte). Perfekt.
Patrick
8
Ein seltener Anblick, eine gitAntwort, die einfach und direkt zur Lösung führt, anstatt sich durch die Feinheiten von git zu schlängeln, um zu beweisen, wie gut der Antwortende es weiß.
Przemek D
74

git cherry-pick : Übernehmen Sie die Änderungen, die durch einige vorhandene Commits eingeführt wurden

Angenommen, wir haben Zweig A mit (X, Y, Z) Commits. Wir müssen diese Commits zu Zweig B hinzufügen . Wir werden die cherry-pickOperationen nutzen.

Wenn wir verwenden cherry-pick, sollten wir Commits in Zweig B in derselben chronologischen Reihenfolge hinzufügen, in der die Commits in Zweig A erscheinen .

Cherry-Pick unterstützt zwar eine Reihe von Commits, aber wenn Sie Commits in diesem Bereich zusammenführen, wird dies sehr kompliziert

git checkout B
git cherry-pick SHA-COMMIT-X
git cherry-pick SHA-COMMIT-Y
git cherry-pick SHA-COMMIT-Z

Beispiel für einen Workflow:

Geben Sie hier die Bildbeschreibung ein

Wir können cherry-pickmit Optionen verwenden

-e oder --edit : Mit dieser Option können Sie mit git cherry-pick die Festschreibungsnachricht vor dem Festschreiben bearbeiten.

-n oder --no-commit : Normalerweise erstellt der Befehl automatisch eine Folge von Commits. Dieses Flag wendet die Änderungen an, die erforderlich sind, um jedes benannte Commit für Ihren Arbeitsbaum und den Index auszuwählen, ohne ein Commit vorzunehmen. Wenn diese Option verwendet wird, muss Ihr Index außerdem nicht mit dem HEAD-Commit übereinstimmen. Die Auswahl erfolgt gegen den Anfangszustand Ihres Index.

Hier ist ein interessanter Artikel über cherry-pick.

Lyes CHIOUKH
quelle
19

Sie können aus den Commits, die Sie kopieren möchten , einen Patch erstellen und den Patch auf den Zielzweig anwenden .

Charles Ma
quelle
16
Selbst wenn Sie aus irgendeinem Grund wirklich Patch (s) anstelle von Cherry-Pick (s) / Rebase verwenden möchten, ist der einfache Weg, dies zu tun, mit git format-patch <revision range>und git am *.patch.
Cascabel
Es erfordert checkoutzu einem anderen Zweig.
CoolMind
12

Oder wenn Sie etwas weniger auf der Seite des Evangelisten stehen, können Sie ein wenig hässlich vorgehen, wie ich es benutze. In deploy_template gibt es Commits, die ich als Zweigbereitstellung auf meinen Master kopieren möchte

git branch deploy deploy_template
git checkout deploy
git rebase master

Dadurch wird eine neue Zweigbereitstellung (ich verwende -f, um den vorhandenen Bereitstellungszweig zu überschreiben) auf deploy_template erstellt. Anschließend wird dieser neue Zweig auf den Master zurückgesetzt, wobei deploy_template unberührt bleibt.

Petr Sykora
quelle
1

Für den einfachen Fall, dass nur das letzte Commit von Zweig wss nach v2.1 kopiert wird, können Sie einfach die Commit-ID ( git log --oneline | head -n 1) abrufen und Folgendes tun:

git checkout v2.1
git merge <commit>
zeroimpl
quelle
Dies erfordert das Auschecken in einen anderen Zweig.
CoolMind
1

Der Cherry-Pick-Befehl kann die Liste der Commits aus der Standardeingabe lesen.

Der folgende Befehl Cherry-Picks schreibt vom Benutzer John erstellte Commits fest, die im Zweig "Entwickeln", jedoch nicht im Zweig "Freigeben" vorhanden sind, und zwar in chronologischer Reihenfolge.

git log develop --not release --format=%H --reverse --author John | git cherry-pick --stdin
Gebb
quelle