Ziehen Sie alle Commits aus einem Zweig und verschieben Sie die angegebenen Commits in einen anderen

102

Ich habe folgende Zweige:

  • master
  • production

und die folgenden entfernten Zweige:

  • origin/master
  • origin/production

Ich habe ein Skript, das den origin/masterZweig abruft und den Unterschied zu dem ermittelt, was sich seit meinem letzten Abruf ( log -p master..origin/master) geändert hat . Dann verschmelze ich origin/master.

Die gefundenen Commits werden an ein Codeüberprüfungstool weitergeleitet.

Ich möchte die erfolgreichen Commits - und nur sie - an die Produktionsabteilung weiterleiten und dann natürlich an origin/production.

Wie kann ich das machen?

Außerdem werden zwei Skripte ausgeführt: das eine, aus dem origin/masterCommit-Details abgerufen , in eine Datenbank übertragen und zusammengeführt werden, und das andere, das ich gerade schreibe, das die erfolgreichen Commits pushen muss.

Ich möchte, dass diese beiden Skripte ausgeführt werden und gleichzeitig die Rennbedingungen / Zusammenführungskonflikte vermieden werden. Da ich nur mit bestimmten Commits arbeiten möchte, gibt es vielleicht eine Möglichkeit, die Commits loszuwerden, die ich nicht möchte?

Sylvain
quelle
Was meinst du mit "erfolgreichen Commits"?
Bdonlan
derjenige, der überprüft und als erfolgreich markiert wurde. Hier spielt es keine Rolle, wichtig ist, dass es Commits gibt, die ich behalten und an einen anderen Zweig weiterleiten möchte, und andere, die ich loswerden / ignorieren möchte.
Sylvain

Antworten:

312

Der Begriff, den Sie suchen, ist ein "Kirschpickel". Nehmen Sie also ein einzelnes Commit aus der Mitte eines Zweigs und fügen Sie es einem anderen hinzu:

A-----B------C
 \
  \
   D

wird

A-----B------C
 \
  \
   D-----C'

Dies kann natürlich mit dem Befehl git cherry-pick erfolgen.

Das Problem bei diesem Commit ist, dass git feststellt, dass Commits den gesamten Verlauf vor sich enthalten. Wenn Sie also drei Commits wie diesen haben:

A-----B-----C

Und versuchen Sie, B loszuwerden, müssen Sie ein völlig neues Commit wie folgt erstellen:

A-----------C'

Wobei C 'eine andere SHA-1-ID hat. Ebenso beinhaltet das Auswählen eines Commits von einem Zweig zum anderen im Wesentlichen das Generieren eines Patches und das anschließende Anwenden dieses Patches, wodurch auch die Historie auf diese Weise verloren geht.

Diese Änderung der Festschreibungs-IDs unterbricht unter anderem die Zusammenführungsfunktion von git (obwohl es bei sparsamer Verwendung Heuristiken gibt, die dies dokumentieren). Noch wichtiger ist jedoch, dass funktionale Abhängigkeiten ignoriert werden. Wenn C tatsächlich eine in B definierte Funktion verwendet hat, werden Sie es nie erfahren.

Ein besserer Weg, dies zu handhaben, wäre vielleicht, feinkörnigere Zweige zu haben. Das heißt, anstatt nur einen 'Master' zu haben, haben Sie 'featureA', 'bugfixB' usw. Führen Sie eine Codeüberprüfung für einen gesamten Zweig gleichzeitig durch - wobei jeder Zweig sehr darauf ausgerichtet ist, nur eine Sache zu tun - und führen Sie diesen dann zusammen ein Zweig, wenn Sie fertig sind. Dies ist der Workflow, für den Git entwickelt wurde und in dem es gut ist :)

Wenn Sie darauf bestehen, Dinge auf der Ebene der Patches zu erledigen, sollten Sie sich Darcs ansehen - ein Repository wird als eine Reihe von Patches betrachtet, und daher wird das Kirschpflücken zur grundlegenden Operation. Dies hat jedoch seine eigenen Probleme, wie zum Beispiel sehr langsam zu sein :)

Bearbeiten: Ich bin mir auch nicht sicher, ob ich Ihre zweite Frage zu den beiden Skripten verstehe. Vielleicht könnten Sie es genauer beschreiben, möglicherweise als separate Frage, um zu verhindern, dass die Dinge verwirrend werden?

bdonlan
quelle
Bei meiner zweiten Frage möchte ich nur sicherstellen, dass die Prozesse zum Abrufen von Änderungen (1. Skript) und zum Verschieben bestimmter Commits an einen anderen Speicherort (2. Skript) ohne Race Condition / Zusammenführungskonflikt funktionieren, während mit verschiedenen Zweigen gearbeitet wird. Aber am Ende denke ich, dass das keine Rolle spielt, da ich die 2 Skripte zu einem zusammenführen könnte, so dass die 2 Skripte nicht gleichzeitig funktionieren :)
Sylvain
9
"Diese Änderung der Commit-IDs unterbricht
Narek
5
@Narek Er meint wahrscheinlich, dass Änderungen in Commit C 'mit denselben Änderungen in Commit C kollidieren, wenn Sie den zweiten Zweig zusammenführen. Das ist die Folge des Verlustes der Geschichte hinter Commit C.
Bytefu
1
"Und versuchen Sie, B loszuwerden" - warum versuchen Sie, B loszuwerden?
d512
3
@ user1334007, er meint, dass es früher ABC war. Aufgrund Ihrer Auswahl an C ist Ihr Zweig jetzt AD-C ', das nicht mehr' B 'enthält.
AnneTheAgile
1

Mir ist klar, dass dies eine alte Frage ist, auf die hier jedoch verwiesen wird: Wie man ein bestimmtes Commit in Git zusammenführt

Daher eine neuere Antwort: Verwenden Sie Feature-Zweige und Pull-Anforderungen.

Wie dies aussieht, wobei fA ein Commit mit Merkmal A und fB ein Commit mit Merkmal B ist:

            fA   fC (bad commit, don't merge)
           /  \ /
master ----A----B----C
                \  /
                 fB

Pull-Anfragen sind mit der Funktionalität von GitHub verbunden, aber ich meine wirklich nur, dass jemand die Verantwortung hat, die Feature-Zweige in Master zusammenzuführen.

MattJenko
quelle