903 Stimmen

Wie wählt man eine Reihe von Commits aus und fügt sie in einen anderen Zweig ein?

Ich habe das folgende Repository-Layout:

  • Master-Zweig (Produktion)
  • Integration
  • arbeiten

Was ich erreichen möchte, ist eine Reihe von Commits aus dem Arbeitszweig zu nehmen und in den Integrationszweig zusammenzuführen. Ich bin ein ziemlicher Neuling in Git und kann nicht herausfinden, wie ich das genau machen kann (die Auswahl von Commit-Bereichen in einem Vorgang, nicht das Zusammenführen), ohne das Repository durcheinander zu bringen. Hat jemand einen Tipp oder eine Idee dazu? Vielen Dank!

1 Stimmen

5 Stimmen

Der TLDR; ist: git cherry-pick <one-sha-before-the-oldest-sha-to-pick>..<sha-of-latest-to-p‌​ick>

1076voto

VonC Punkte 1117238

Wenn es um eine Reihe von Übertragungen geht, ist das Herauspicken von Rosinen ist war nicht praktisch.

Als unten erwähnt por Keith Kim Mit Git 1.7.2+ wurde die Möglichkeit eingeführt, eine Reihe von Übertragungen auszuwählen (aber Sie müssen immer noch auf die Konsequenz der Rosinenpickerei für künftige Fusionen )

git cherry-pick" hat gelernt, einen Bereich von Übertragungen auszuwählen
(z.B. " cherry-pick A..B " und " cherry-pick --stdin "), so auch " git revert "; diese unterstützen nicht die schönere Sequenzierungssteuerung " rebase [-i] " hat jedoch.

damian Kommentare und warnt uns:

In der " cherry-pick A..B Formular", A sollte älter sein als B .
Wenn sie in der falschen Reihenfolge sind, schlägt der Befehl fehl. .

Wenn Sie sich für die Bereich B über D (einschließlich B ) das wäre B^..D (anstelle von B..D ).
Siehe " Git erstellt einen Zweig aus einer Reihe von vorherigen Übertragungen? " zur Veranschaulichung.

Als Jubiläen Erwähnt in den Kommentaren :

Dies setzt voraus, dass B ist keine Root-Übertragung; Sie erhalten eine " unknown revision " Fehler sonst.

Hinweis: Seit Git 2.9.x/2.10 (Q3 2016) können Sie einen Bereich von Commits direkt in einem verwaisten Zweig (leerer Kopf) auswählen: siehe " Wie man einen bestehenden Zweig in Git verwaisen lässt ".


Ursprüngliche Antwort (Januar 2010)

A rebase --onto wäre besser, bei dem Sie den angegebenen Bereich von Commits auf Ihrem Integrationszweig wiedergeben, als Charles Bailey beschreibt hier .
(suchen Sie auch nach "So verpflanzen Sie einen Themenzweig, der auf einem Zweig basiert, in einen anderen" in der git rebase man-Seite um ein praktisches Beispiel zu sehen git rebase --onto )

Wenn Ihr derzeitiger Zweig die Integration ist:

# Checkout a new temporary branch at the current location
git checkout -b tmp

# Move the integration branch to the head of the new patchset
git branch -f integration last_SHA-1_of_working_branch_range

# Rebase the patchset onto tmp, the old location of integration
git rebase --onto tmp first_SHA-1_of_working_branch_range~1 integration

Damit wird alles dazwischen wiedergegeben:

  • nach dem Elternteil von first_SHA-1_of_working_branch_range (daher die ~1 ): die erste Übertragung, die Sie wiederholen möchten
  • bis zu " integration "(der auf den letzten Commit verweist, den Sie wiedergeben wollen, aus der working Zweig)

zu " tmp " (der darauf hinweist, wo integration vorher gezeigt hat)

Wenn es bei der Wiederholung einer dieser Übertragungen zu einem Konflikt kommt:

  • entweder lösen Sie es und führen " git rebase --continue ".
  • oder überspringen Sie diesen Patch, und führen Sie stattdessen " git rebase --skip "
  • oder die ganze Sache mit einem " git rebase --abort " (und legen Sie die integration Zweig auf der tmp Zweig)

Danach rebase --onto , integration wird bei der letzten Übergabe des Integrationszweigs zurück sein (d.h. " tmp "Zweig + alle wiedergegebenen Übertragungen)

Mit Rosinenpickerei oder rebase --onto nicht vergessen, dass dies Auswirkungen auf nachfolgende Zusammenführungen hat, da hier beschrieben .


Ein reines " cherry-pick " Lösung ist hier diskutiert und würde in etwa so aussehen:

Wenn Sie einen Patch-Ansatz verwenden möchten, sind "git format-patch|git am" und "git cherry" Ihre Optionen.
Derzeit, git cherry-pick akzeptiert nur eine einzige Übergabe, aber wenn Sie den Bereich wählen wollen B über D das wäre B^..D im Git-Jargon, also

git rev-list --reverse --topo-order B^..D | while read rev 
do 
  git cherry-pick $rev || break 
done 

Aber wie auch immer, wenn Sie eine Reihe von Übertragungen "wiederholen" müssen, sollte das Wort "wiederholen" Sie dazu bringen, die " rebase "Funktion von Git.

2 Stimmen

Wenn Sie Commits haben, die Eltern haben, die die -m Option, wie gehen Sie mit diesen Übertragungen um? Oder gibt es eine Möglichkeit, diese Commits herauszufiltern?

0 Stimmen

@aug -m soll sie für Sie erledigen, indem es die Hauptlinie auswählt, auf die die -m Parameter, den Sie für diese Rosinenpickerei gewählt haben.

0 Stimmen

Das Problem ist, dass wenn man eine Reihe von Commits auswählt, es die übergeordneten Commits korrekt auswählt, aber wenn es dann auf einen normalen Commit trifft, schlägt es fehl und sagt, dass der Commit kein Merge ist. Ich schätze, meine Frage ist besser formuliert, wie man es schafft, die -m Option nur, wenn sie auf einen übergeordneten Commit trifft, wenn sie einen Bereich von Commits auswählt? Wenn ich im Moment die Option -m のように git cherry-pick a87afaaf..asfa789 -m 1 gilt er für alle Übertragungen innerhalb des Bereichs.

172voto

Keith Kim Punkte 1521

Seit Git v1.7.2 kann Cherry Pick eine Reihe von Commits akzeptieren:

git cherry-pick gelernt, einen Bereich von Commits auszuwählen (z. B. cherry-pick A..B y cherry-pick --stdin ), so hat git revert diese unterstützen nicht die schönere Sequenzkontrolle rebase [-i] hat jedoch.

121 Stimmen

Beachten Sie, dass cherry-pick A..B keine Zusage A erhalten (Sie müssten A~1..B dafür), und bei Konflikten macht Git nicht automatisch weiter, wie es bei Rebase der Fall ist (zumindest ab 1.7.3.1)

5 Stimmen

Es ist auch gut zu wissen, dass git cherry-pick A..B C funktioniert nicht so, wie man es naiverweise erwarten würde. Es wird nicht alles in dem Bereich ausgewählt A..B und verpflichten sich C ! Zu diesem Zweck müssen Sie sich in zwei Zeilen aufteilen, und zwar in git cherry-pick A..B und dann git cherry-pick C . Wenn Sie also einen Bereich haben, müssen Sie ihn separat ausführen.

121voto

KostasA Punkte 4642

Angenommen, Sie haben 2 Zweige,

"branchA" : enthält die Commits, die kopiert werden sollen (von "commitA" nach "commitB")

"ZweigB": der Zweig, von dem die Übertragungen von ZweigA" übertragen werden sollen

1)

 git checkout <branchA>

2) Ermitteln der IDs von "commitA" und "commitB".

3)

git checkout <branchB>

4)

git cherry-pick <commitA>^..<commitB>

5) Falls Sie einen Konflikt haben, lösen Sie ihn und geben Sie

git cherry-pick --continue

um den Prozess der Rosinenpickerei fortzusetzen.

0 Stimmen

Hat wunderbar funktioniert! Vielen Dank!

4 Stimmen

Was bewirkt das "^" in dem Befehl "git cherry-pick <commitA>^..<commitB>" unter 4)?

0 Stimmen

37voto

djs Punkte 4356

Sind Sie sicher, dass Sie die Zweige nicht tatsächlich zusammenführen wollen? Wenn der Arbeitszweig einige aktuelle Commits enthält, die Sie nicht wollen, können Sie einfach einen neuen Zweig mit einem HEAD an der gewünschten Stelle erstellen.

Wenn Sie nun wirklich eine Reihe von Commits auswählen wollen, aus welchem Grund auch immer, ist eine elegante Möglichkeit, dies zu tun, einfach ein Patchset zu ziehen und es auf Ihren neuen Integrationszweig anzuwenden:

git format-patch A..B
git checkout integration
git am *.patch

Dies ist im Wesentlichen das, was git-rebase ohnehin tut, aber ohne die Notwendigkeit, Spiele zu spielen. Sie können hinzufügen --3way à git-am wenn Sie fusionieren müssen. Vergewissern Sie sich, dass sich in dem Verzeichnis, in dem Sie dies tun, keine anderen *.patch-Dateien befinden, wenn Sie die Anweisungen wortwörtlich befolgen...

3 Stimmen

Wie bei anderen Revisionsbereichen ist zu beachten, dass es sich um A^ einbeziehen A .

28voto

Saikat Punkte 10782

Entkernung mit Git start_commit_sha_id ^.. end_commit_sha_id

z.B.. git cherry-pick 3a7322ac^..7d7c123c

Angenommen, Sie sind auf branchA wo Sie Commits auswählen möchten ( Start- und End-Commit-SHA für den Bereich ist gegeben und Left-Commit-SHA ist älter ) von branchB . Der gesamte Bereich der Übertragungen (beide inklusive) wird in branchA .

El Beispiele die in der offiziellen Dokumentation angegeben sind, sind sehr nützlich.

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