it-swarm.com.de

Warum sagt die GIT nach der Fusion "Bereits auf dem neuesten Stand", aber es gibt immer noch Unterschiede zwischen den Zweigen?

Ich arbeitete ursprünglich in der Filiale "Newfeature" und wurde aufgerufen, dringend einen Fehler in der Live-Filiale zu beheben. Ich habe einen Zweig für den sogenannten "Generalmaintenance" erstellt, den Job erledigt, dann die Entwicklung vorgenommen und ihn zusammengeführt. Jetzt möchte ich zum "Newfeature" -Zweig zurückkehren und mich in die Änderungen einarbeiten, die ich zuvor darin eingemischt habe.

Als ich zu "newfeature" wechselte und in "development" zusammengeführt wurde, gab es Konflikte in 3 Dateien.

Ich geriet in ein Gewirr, das die Konflikte löste, und entschied mich schließlich dazu, den Befehl "Wiederherstellen" im "Team" -Menü von Aptana Studio 3 (meiner IDE) zu verwenden. Ich hatte erwartet, dass dies mich vor dem Zusammenschluss zurückrollen würde, was offenbar geschehen ist.

Jedenfalls, wenn ich wieder in "Develop" einfüge, heißt es Already-up-to-date, aber beim Vergleichen von Dateien zwischen den beiden Zweigen sind sie sehr unterschiedlich und die Änderungen, die ich in dem anderen Zweig hinzugefügt habe, werden nicht zusammengeführt.

Wie werde ich die beiden Zweige jetzt zusammenführen?

27
Peter Snow

Zusammenführungen rückgängig machen oder Zusammenführungen zurücksetzen

Ich vermute, dass Sie tatsächlich Already-up-to-date sind.

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

Zusammenführen

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

Im obigen Fall wird develop mit newfeature zusammengeführt, wodurch das Commit M erstellt wird. Wenn Sie git log newfeature ausführen würden, würden Sie alle Festschreibungen aus beiden Zweigen sehen. Aus der Sicht der newfeature-Verzweigung wurden jedoch alle diese Änderungen von der M-Festschreibung durchgeführt.

Zurücksetzen

Der Befehl git revert entfernt keine Festschreibungen, sondern erstellt eine neue Festschreibung, die die in der Festschreibung enthaltenen Änderungen rückgängig macht. Wenn Sie beispielsweise ein Commit hatten, das diesen Unterschied enthält ...

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

Wenn Sie dies dann wieder rückgängig machen, würde der Befehl revert ein neues Commit erstellen, das gerade das entgegengesetzte Diff ausführt. Es kippt einfach die Vorzeichen.

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

Dies ist sehr nützlich, um Schäden rückgängig zu machen, die durch Commits anderer Entwickler verursacht wurden. Es bringt die Geschichte voran, anstatt sie zu verändern.

Zusammenführungen rückgängig machen

Im Kontext einer nicht schnellen Zusammenführung kann dies jedoch einen unerwünschten Effekt haben.

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

Angenommen, W ist ein Reverse-Commit, können Sie sehen, wie beim Ausführen von git log newfeature weiterhin alle Commits aus dem Entwicklungszweig berücksichtigt werden. Zusätzliche Zusammenführungen von develop funktionieren daher nicht, da in Ihrem Zweig nichts fehlt.

Verwenden von git reset anstelle von revert.

Möglicherweise möchten Sie in Zukunft die Verwendung von git reset --hard <ref> (wobei <ref> der Commit-Hash der Zusammenführung ist) in Betracht ziehen, um eine Zusammenführung rückgängig zu machen, wenn diese Zusammenführung nicht für andere Entwickler freigegeben wurde. Im obigen Beispiel würde das Ausführen des Befehls git reset --hard F nach dem Erstellen des Zusammenführungs-Commits M zu folgendem Ergebnis führen.

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

Wie Sie sehen, wird das Commit durch diese Technik nicht zunichte gemacht, wie manche Leute meinen, sondern Ihr Zweig wird einfach auf das von Ihnen ausgewählte Commit zurückgesetzt. Wenn Sie jetzt git log newfeature ausführen, erhalten Sie nur Commit F, E und A. Jetzt ist die Zusammenführung tatsächlich aus dem Branchenverlauf entfernt, sodass ein späterer Versuch, sie in develop erneut zusammenzuführen, keine Probleme mehr verursacht.

Diese Methode ist nicht ohne Komplikationen. Stellen Sie fest, dass Sie gerade den Verlauf ändern. Wenn also der Zweig newfeature nach dem Zusammenführen von M auf einen fernen Zweig verschoben wurde, wird git Sie einfach für veraltet halten und Ihnen das mitteilen Sie müssen git pull ausführen. Wenn Sie nur an diesem Remote-Zweig arbeiten, können Sie force-Push - git Push -f <remote> <branch> verwenden. Dies hat die gleichen Auswirkungen wie das Zurücksetzen, jedoch auf den Remote-Zweig.

Wenn dieser Zweig von mehreren Entwicklern genutzt wird, die inzwischen schon davon abgezogen hätten - dann ist das eine schlechte Idee. Dies ist der eigentliche Grund, warum git revert nützlich ist, da Änderungen rückgängig gemacht werden, ohne dass der aktuelle Verlauf geändert wird.

Das Zurücksetzen des Verlaufs ist nur für Commits möglich, die nicht freigegeben wurden.

Die Lösung - Umkehren der Umkehrung.

Wenn das Zusammenführungs-Commit bereits geteilt wurde, ist es wahrscheinlich am besten, git revert für diese Zusammenführung zu verwenden. Wie bereits erwähnt, können Sie den Zweig dann nicht einfach wieder zusammenführen und erwarten, dass alle Änderungen aus diesem Zweig wieder angezeigt werden. Die Antwort besteht darin, das Zurücksetzen rückgängig zu machen.

Nehmen wir an, Sie haben am Zweig develop gearbeitet, nachdem Sie die Zusammenführung in newfeature verehrt haben. Ihre Geschichte würde ungefähr so ​​aussehen.

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

Wenn Sie jetzt develop in newfeature zusammenführen, erhalten Sie nur D, da dies das einzige Commit ist, das nicht bereits Teil des Verlaufs des Zweigs newfeature ist. Sie müssen auch zurücksetzen, dass W commit - git revert W den Trick ausführen soll, gefolgt von git merge develop.

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

Dies stellt alle Änderungen wieder her, die durch das ursprüngliche Zusammenführungs-Commit vorgenommen wurden - die tatsächlich von C und B vorgenommen wurden, jedoch in W zurückgesetzt wurden. Anschließend wird D über ein neues übernommen Merge Commit G Ich würde empfehlen, das Revert vor dem Einfügen der letzten Änderungen in develop zurückzusetzen. Ich vermute, dass die Wahrscheinlichkeit geringer ist, dass dies in dieser Reihenfolge erfolgt Konflikte auslösen.

TL; DR

Durch das Zurücksetzen wird ein Zurücksetzen-Commit erstellt. Wenn Sie eine Wiederherstellung rückgängig machen, müssen Sie den Befehl revert für die Wiederherstellung ausführen, die bei der ersten Wiederherstellung erstellt wurde. Es sollte leicht zu finden sein. Git neigt dazu, Reverts automatisch zu kommentieren, sodass sie mit dem Wort "Reverted" beginnen.

git revert <commit>

54
eddiemoya

Eine hackige Lösung gefunden. Aber es funktioniert.

Was auch immer eddiemoya geantwortet hat, ist total hilfreich. Vielen Dank für die Erklärung. Ich bin auf eine ähnliche Situation gestoßen. In git diff <branch> konnte ich viel Inhalt sehen, aber git merge war bereits auf dem neuesten Stand.

Ich konnte das genaue Zurücksetzungs-Commit aufgrund vieler Revertionen im Protokoll nicht finden. (Ja, schlimme Sache. Sollte gar nicht erst passiert sein)

Lösung

git checkout branchX -- .

Dadurch werden alle Änderungen von branchX zu meinem aktuellen Zweig vorgenommen. Verwenden Sie einen Ihrer bevorzugten Git-Clients, machen Sie die Bühne frei und stellen Sie zurück, was nicht beabsichtigt ist.

Machen Sie ein neues Commit und seien Sie glücklich :)

0
Katti