2013-04-01 4 views
21

Ich arbeitete ursprünglich im Zweig 'newfeature' und ich wurde aufgerufen, einen Fehler im Live-Zweig dringend zu beheben. Ich habe einen Zweig namens generalmaintenance erstellt, den Job erledigt und bin dann zum Entwickeln und Zusammenführen gewechselt. Ich möchte nun zum Zweig 'newfeature' zurückkehren und die Änderungen, die ich zuvor in den fusionierten, zusammenführen.Warum sagt GIT nach der Zusammenführung "Bereits aktuell", aber Unterschiede zwischen den Zweigen bestehen noch?

Als ich zu 'newfeature' wechselte und in 'develop' fusionierte, gab es Konflikte in 3 Dateien.

Ich bekam ein Gewirr, das die Konflikte löste und beschloss schließlich, den "Revert" -Befehl im Team-Menü von Aptana Studio 3 (das ist meine IDE) zu verwenden. Ich habe damit gerechnet, dass mir das vor der Zusammenführung wieder einfällt, was es anscheinend getan hat.

Wie auch immer, wenn ich in fusionieren ‚entwickelt‘ wieder, sagt sie, Already-up-to-date, aber wenn Dateien zwischen den beiden Zweigen zu vergleichen, sie sind sehr unterschiedlich, und die Veränderungen, die ich in dem anderen Zweig hinzugefügt werden nicht verschmolzen.

Wie werde ich jetzt die beiden Zweige zusammenführen?

Antwort

46

Zurückkehren Merges gegen Zurücksetzen Merges

Meine Vermutung ist, dass Sie tatsächlich Already-up-to-date sind.

Das Problem ist, dass git revert die Zusammenführung nicht rückgängig macht, es macht nur die Änderungen rückgängig, die die Zusammenführung mit sich brachte. Wenn Sie einen Zusammenführungs-Commit erstellen, kombinieren Sie die Commit-Historien dieser beiden Zweige.

Merging

 develop 
     | 
A---B---C 
\  \ 
    E---F---M 
      | 
     newfeature 

Im Fall oben wird in developnewfeature verschmolzen, wodurch die M begehen. Wenn Sie git log newfeature ausführen würden, würden Sie alle Commits von beiden Zweigen sehen, jedoch aus der Perspektive des newfeature Zweigs, alle diese Änderungen wurden durch das M Commit durchgeführt.

Der git revert Befehl alle Commits nicht entfernen Zurückkehren, schafft stattdessen es eine neue verpflichten, dass die Änderungen rückgängig gemacht, dass die enthaltenen commit. Wenn Sie zum Beispiel haben eine Festschreibung dieses diff enthält ...

-This is the old sentence. 
+This is ne new sentence. 

Dann ist diese rückgängig gemacht würde der revert Befehl ein neue begehen, die nur vorgeformten das Gegenteil diff schaffen, dreht es einfach die Beschilderung.

Dies ist wirklich nützlich für den Abbau von Schäden durch Commits, die andere Entwickler bereits haben. Es bewegt die Geschichte vorwärts, anstatt die Geschichte zu verändern.

Merges

es jedoch im Zusammenhang mit einer nicht-fastforward fusionieren kann eine unerwünschte Wirkung hat Zurückkehren.

 develop 
     | 
A---B---C 
\  \ 
    E---F---M---W 
       | 
     newfeature 

Unter der Annahme, W ist ein Rückfall zu begehen, können Sie sehen, wie Laufen git log newfeature noch alle Commits aus der Branche entwickeln sind. Daher werden zusätzliche Zusammenführungen von develop nicht funktionieren, da nichts in Ihrer Zweigstelle fehlt.

Verwenden git reset anstelle von zurück.

In Zukunft könnten Sie mit git reset --hard <ref> berücksichtigen wollen (wo <ref> der Hash-Wert der Merge-Commit) eine Zusammenführung rückgängig zu machen, wenn die Zusammenführung mit anderen Entwicklern geteilt worden ist. Im obigen Beispiel würde nach dem Erstellen des Zusammenführungs-Commits M das Ausführen des Befehls git reset --hard F zu folgendem führen.

 develop 
     | 
A---B---C 
\  \ 
    E---F---M 
     | 
    newfeature 

Wie Sie diese Technik sehen ist das nicht auslöschen begehen, wie manche Leute neigen dazu zu glauben, es bewegt sich einfach Ihre Zweig zurück zum commit Sie ausgewählt haben. Wenn Sie nun git log newfeature ausführen, erhalten Sie nur Commit F, E und A. Jetzt ist die Zusammenführung tatsächlich von Ihrem Zweigverlauf verschwunden, so dass ein späteres Zusammenführen in develop keine Probleme verursacht.

Diese Methode ist nicht ohne Komplikationen. Verstehen Sie, dass Sie jetzt Geschichte ändern, also wenn der Zweig newfeature in einen entfernten Zweig geschoben wurde, nachdem die M Zusammenführung gemacht wurde, dann wird git denken, dass Sie einfach veraltet sind und Ihnen sagen, dass Sie git pull ausführen müssen. Wenn Sie nur an diesem entfernten Zweig arbeiten, dann fühlen Sie sich frei force-push - git push -f <remote> <branch>. Dies hat den gleichen Effekt wie das Zurücksetzen, aber auf den entfernten Zweig.

Wenn diese Verzweigung von mehreren Entwicklern benutzt wird, die schon jetzt davon gezogen hätten - dann ist das eine schlechte Idee. Dies ist der Grund, warum git revert nützlich ist, da es Änderungen rückgängig macht, ohne den tatsächlichen Verlauf zu ändern.

Die Verwendung von Zurücksetzen auf den Verlauf ist wirklich nur Option für Commits, die nicht freigegeben wurden.

Die Lösung - Umkehrung der Reversion.

Wenn der Zusammenführungs-Commit bereits freigegeben wurde, dann ist der beste Ansatz wahrscheinlich die Verwendung von git revert für diese Zusammenführung. Wie bereits erwähnt, können Sie den Zweig jedoch nicht einfach wieder zusammenführen und erwarten, dass alle Änderungen aus diesem Zweig erneut angezeigt werden. Die Antwort besteht darin, das Zurücksetzen-Commit rückgängig zu machen.

Nehmen wir an, Sie haben einige Arbeiten an der develop Zweigstelle, nachdem Sie die Zusammenführung in newfeature verehrt haben. Deine Geschichte würde ungefähr so ​​aussehen.

  develop 
      | 
A---B---C---D 
\  \ 
    E---F---M---W 
       | 
     newfeature 

Wenn Sie develop in newfeature jetzt fusionieren, würden Sie nur D bekommen, weil es das einzige verpflichten, dass nicht bereits Teil der Geschichte des newfeature Zweig ist. Was Sie auch tun müssen, ist, dass W commit zurückgesetzt wird - git revert W sollte den Trick tun, gefolgt von git merge develop.

    develop 
        | 
A---B---C-----------D 
\  \   \ 
    E---F---M---W---M---G 
         | 
       newfeature 

Diese alle von den ursprünglichen merge Änderungen wieder commit - die von C und B tatsächlich wurden, aber in W zurückgekehrt, bringt es dann in D über einen neuen merge G befiehlt ich die revert zurückkehren würde empfehlen, vor Verschmelzung in den letzten Änderungen an develop, ich vermute, es in dieser Reihenfolge tun wird eine geringere Chance haben, Konflikte auszulösen.

TL; DR

Zurückkehren schafft eine 'revert zu begehen'. Wenn Sie eine Zurücksetzung rückgängig machen möchten, müssen Sie den Befehl revert für die Zurückkehr-Überschreibung ausführen, die beim ersten Zurücksetzen erstellt wurde. Es sollte leicht zu finden sein, git neigt dazu, automatisch Rückgaben zu kommentieren, so dass sie mit dem Wort "Reverted" beginnen.

git revert <commit>

+0

Vielen Dank Eddie, für die detaillierte Erläuterung (1) dafür. Werde es noch einmal studieren, um es zu verdauen und deine Lösung ausprobieren, bevor du deine Antwort akzeptierst. Ich bin 'leise zuversichtlich', dass dies die Lösung sein wird. –

+1

FYI: Ich habe ein paar kleinere, aber wichtige Änderungen vorgenommen, um ein paar Dinge zu korrigieren. Am wichtigsten ist, dass ich mein Beispiel für das Zurücksetzen des Merge-Commits korrigiert habe. Es war 'git revert M', ich korrigierte es zu' git revertW'. Auch der zweite Unterschied war falsch. Der eine, der eine Rücksetzung erklärt. Die +/- Symbole wurden korrigiert. – eddiemoya

+0

Unsere Lektion gelernt - vorsichtig git diff und Überprüfung der Commits, wenn aus der gleichen Branche, in der die reversed PR wurde generiert Fusion! – f01

Verwandte Themen