2016-03-24 4 views
2

Ich habe ein Problem zwischen meinen Git-Zweige, die ich bin mir nicht sicher, wie zu nähern. Nehmen wir an, ich habe für jede Version, an der ich gerade arbeite, separate Zweige. Zum Beispiel habe ich "Release-1" und "Release-2" als meine Zweige. Diese Releases sind sequenziell, das heißt, "Release-2" enthält alles in "Release-1", aber nicht umgekehrt. In meinem Fall habe ich versehentlich 'Release-2' in 'Release-1' eingefügt und schiebe es, ohne meinen Fehler zu bemerken. Eine erkannte ich, dass ich einen Fehler gemacht hatte, ging ich voraus und ausgestellt:Reparieren 'rückwärts' Git Fusion, die geschoben wurde

git revert -m 1 <sha-of-bad-merge-commit> 

Dies schien alles zu beheben; Keiner der "Release-2" -Code war in "Release-1" und alle schienen korrekt zu sein. Ich schob dies zu meinem Upstream und dachte, es sei gelöst. Schnell vorwärts zum heutigen Tag. Ich habe einen Bugfix im Zweig 'Release-1' angewendet. Jetzt möchte ich "Release-1" in "Release-2" zusammenführen, aber ich stoße auf Konflikte. Git glaubt, dass die Änderungen, die in der vorherigen Version vorgenommen wurden, in "Release-2" zusammengeführt werden sollten. Im Wesentlichen möchte Git die Änderungen von "Release-2" entfernen, die versehentlich in "Release-1" von "Release-2" eingeführt wurden, wenn ich versuche, zu fusionieren.

Ich habe versucht, eine Lösung zu erforschen und habe keine gefunden. Der nächste, den ich gefunden habe, wurde angewendet, um zu früh zu verschmelzen, zu einem späteren Zeitpunkt zurückzukehren und dann erneut zu verschmelzen. Die Lösung bestand darin, die Zurücksetzung rückgängig zu machen und dann die Zusammenführung erneut durchzuführen. Ich glaube nicht, dass das in diesem Fall funktionieren wird, denn das würde die Änderungen in "Release-1" wieder einführen, die nicht in "Release-1" sein sollen.

Anders als durch jede betroffene Datei Zeile für Zeile zu suchen, um den richtigen Satz von Änderungen auszuwählen, gibt es eine gute 'Git-basierte' Möglichkeit, dies zu nähern? Ich möchte nicht einfach die Änderungen aus dem Zweig "Release-2" übernehmen, wo es Konflikte gibt, da einige von ihnen legitim sein könnten. Außerdem habe ich darüber nachgedacht, einfach in den Bugfix-Zweig zu "Release-2" zu migrieren, aber dann wird das Problem wahrscheinlich in der Zukunft wieder auftauchen. Ich möchte das verhindern.

Hier ist eine grobe Zeichnung der Situation:

(Release-2) ---A----B----C---x---x---------*D* 
          \    /
(Release-1) ---x----Y------M---x---^M----Z 

Angenommen, A, B und C sind normale Commits, die ich für wollen 'loslassen-2.' Der Tipp von 'Release-1' ist Y und enthält nur 'Release-1'. Commit 'M' ist der Punkt, an dem ich versehentlich Commit 'C' verschmelze und 'Y' im 'Release-1'-Zweig festschreibe. Irgendwann bemerke ich meinen Fehler und stelle die Zusammenführung wieder her (commit '^ M'). Commit 'Z' hat dann meinen Hotfix drin. An dieser Stelle möchte ich "Release-1" wieder in "Release-2" zusammenführen. Ich mache das und lande bei 'D.' Hier habe ich mein Problem. Im Wesentlichen sagt meine Zusammenführung bei "D", dass sie alle Änderungen löschen möchte, die in "A", "B" und "C" gemacht wurden, was ich nicht möchte. Andere Dateien werden aufgrund der Zusammenführung als Konflikte angezeigt. Zum Beispiel wurden einige Dateien, die ich in 'Release-2' haben wollte, in 'Release-1' gelöscht, als ich die Zurücksetzung machte. Bei 'D' sagt mir Git nun, dass ein Merge-Konflikt vorliegt, weil ein Zweig die Datei gelöscht hat und der andere die Datei geändert hat.

Wenn jemand irgendwelche Vorschläge hat, würde ich mich freuen, sie zu hören. Vielen Dank!

Antwort

3

(Ich werde Ihre ^M begehen als Mrevert, Bezug zu nehmen, da der ^ Charakter in einigen der Befehle besondere Bedeutung hat, die folgen.)

git merge --abort Sie Ihr Versuch aufgeben zu D zu schaffen zu begehen.

Da Sie eine Reihe von Commits x--Mrevert--Z haben, und Sie müssen in x und Z ziehen 's ändert, aber nicht Mrevert ist, benötigen Sie einen dreistufigen Prozess:

  1. Verwenden git merge Mrevert^ zu ziehen in allen Änderungen bis zum Punkt Mrevert. (Die c^ Syntax bedeutet "das übergeordnete Element von commit c".)
  2. Verwenden Sie git merge -s ours Mrevert, um git mitzuteilen, dass die Änderungen von dem ^M Reversion Commit bereits in Ihrem Zweig sind. -s ours bedeutet, unsere (d. H. Release-2) Version des Baumes zu behalten, ohne sich um echtes "Merging" zu kümmern.
  3. Verwenden Sie git merge Z, um die Änderungen von Z zusammenzuführen.

Dies wird ein Commit Graph wie produzieren:

(Release-2) ---A----B----C---x---x---M1-----M2------M3 
          \  / / /
(Release-1) ---x----Y------M-------x---Mrevert----Z 

Wenn Sie git diff M1 M2 tun, werden Sie sehen, dass M2 keine Änderungen in Freigabe-2 nicht ziehen.

+1

Das ist * meistens * richtig und wäre * komplett * richtig, wenn nur das mit 'x' markierte' commitment 'zwischen 'M' und'^M' nicht vorhanden wäre. Ich denke, der Weg, dies zu tun, besteht darin, * drei * Merges statt zwei zu machen: eins zum Verschmelzen in 'x', eins mit' -s uns' zum Verschmelzen '^ M', und das letzte zum Verschmelzen in' Z. '. – torek

+0

@Matt Vielen Dank! Diese Lösung hat wie erwartet funktioniert. Der Grund, dass ich das "^" - Symbol mit dem "M" -Rückruf verwendet habe, war, dass ich der gleichen Art von Illustration folgte wie die hier aufgeführten: https://git-scm.com/blog/2010/03/02/ rückgängig machen-merges.html –

+0

@torek Ich bemerkte keine Probleme in der "x" commit, als ich den Anweisungen Matt geliefert folgte. Ich denke, dass dies darauf zurückzuführen ist, dass das Zurücksetzen-Commit das "x" überhaupt nicht beeinflusst, so dass es später wie erwartet zusammengeführt wird. Es gab einige Commits in 'M', die ich in 'Release-1.0' haben wollte, die in '^ M' zurückgesetzt wurden, also musste ich etwas zusätzliche Arbeit (ein Cherry-Pick des Commits nach dem Zurücksetzen) zu tun Holen Sie diese Änderungen bei Z. –