Was sind Mergekonflikte?
Hier wird erläutert, wie Mergekonfliktauflösungen Entwicklern dabei helfen, das beste Ergebnis aus zwei überlappenden Quellen zu erzeugen.
Der GitHub-Flow
GitHub bietet neben einer Plattform zur Zusammenarbeit bei der Softwareentwicklung einen vorgeschriebenen Workflow für eine optimale Nutzung der verschiedenen Funktionen. Obwohl in dieser Lektion Mergekonflikte konkret behandelt werden, empfehlen wir dennoch, zunächst die Grundlagen des GitHub-Flows zu lesen.
Mergen von Branches
Stellen Sie sich ein Szenario vor, in dem ein Entwickler einen Branch namens feature-branch
basierend auf main
sowie zwei Commits erstellt. Während der Erstellung mergt eine andere Person einen Pull Request in main
, der nicht im Zusammenhang damit steht. Was geschieht, wenn unser Entwickler versucht, feature-branch
wieder mit main
zu mergen?
Die Antwort: Das ist unterschiedlich.
Obwohl feature-branch
aus main
erstellt wurde, wurde es nicht basierend auf dem Branch selbst erstellt. Er wurde vielmehr basierend auf dem HEAD-Commit von main
zu diesem Zeitpunkt erstellt. Ihm sind nicht alle Commits bekannt, die seitdem auf main
angewendet wurden. Die aktuell verfolgten Commits werden nicht unbedingt in den aktuellen Zustand der Verzweigung gefaltet, ohne die letzten Änderungen zu überschreiben.
Wenn sich herausstellt, dass die feature-branch
-Commits nicht mit parallelen Commits überlappen, die seit Erstellen des Branch an main
vorgenommen wurden, treten keine Probleme auf. Neue Dateien können hinzugefügt werden. Unveränderte Dateien können gelöscht werden. Codezeilen, die in main
geändert wurden, können in feature-branch
geändert werden, solange sie durch die parallele Arbeit seit Erstellen von feature-branch
nicht geändert wurden.
Was geschieht jedoch, wenn beide Reihen von Commits Änderungen an denselben Codezeilen enthalten? Bei diesem Mergeversuch würde aufgrund eines Mergekonflikts ein Fehler auftreten.
Was sind Mergekonflikte?
Mergekonflikte werden ausgelöst, wenn ein Entwickler versucht, Änderungen zu mergen, die parallele Änderungen unvermeidlich überschreiben würden. Es ist unerheblich, wie diese anderen Änderungen mit dem Basisbranch gemergt wurden. Git überschreibt nicht automatisch Änderungen zugunsten anderer Änderungen. Stattdessen wird die Person, die den Merge versucht, darauf hingewiesen, sodass sie diesen im eigenen Vergleichsbranch auflösen kann, bevor sie einen erneuten Mergeversuch startet.
Auflösen von Mergekonflikten
GitHub generiert eine vorübergehende Hybriddatei, welche die Unterschiede jedes Branches enthält, um Sie beim Auflösen von Mergekonflikten zu unterstützen. Laut Konvention steht der Text aus dem Vergleichsbranch über dem des Basisbranch, getrennt durch eine Zeile aus Gleichheitszeichen (=======
).
Mithilfe dieser Ansicht können Sie die Datei direkt bearbeiten, falls nur kleine Änderungen vorzunehmen sind. Wenn Sie sich dafür entscheiden, das finale Ergebnis zu behalten, wird es an den Vergleichsbranch committet. Alternativ dazu bevorzugen Sie möglicherweise die Arbeit mithilfe anderen Entwicklungstools, falls der Merge komplizierter ist. In beiden Fällen sollten Sie nicht vergessen, vor dem Committen alle Branchmarker zu entfernen. Wenn Sie vergessen, diese Marker vor dem Committen der Konfliktauflösung zu entfernen, bleiben sie in der Datei und werden nicht auskommentiert.
Hinweis
In dieser Lerneinheit wird erläutert, wie Mergekonflikte im Kontext eines Browsers aufgelöst werden. Auch viele Entwicklungsplattformen wie Visual Studio bieten integrierte Möglichkeiten zum Auflösen von Mergekonflikten.
Sobald alle Mergekonflikte in Ihrem Branch aufgelöst wurden, können Sie den Merge erneut versuchen.
Vermeiden von Mergekonflikten
Einige Mergekonflikte lassen sich nicht vermeiden. Jeder Merge könnte potenziell Mergekonflikte für andere Pull Requests erzeugen, die auf eine Genehmigung warten. Eine effektive Möglichkeit, die Komplexität von Mergekonflikten zu reduzieren, ist jedoch, den Branch oft zu pullen.
Frühes und häufiges Pullen
Der git pull
-Befehl pullt alle Basisbranchcommits, die bisher nicht auf Ihren aktuellen Branch angewendet wurden. Er ähnelt konzeptionell dem Befehl Get Latest, der von vielen Versionskontrollsystemen verwendet wird, um Ihnen das Aktualisieren Ihres lokalen Codes auf die neueste Version zu ermöglichen. Wenn Sie Updates für Ihren Branch pullen, mergen Sie alle Änderungen, die seit dem Erstellen (oder dem letzten Pullen) des Branch vorgenommen wurden.
Das Pullen von Updates für Ihren Branch könnte zu Mergekonflikten führen, aber das ist in Ordnung. Sie würden sie später sowieso erhalten, aber indem Sie sie früher erhalten, sind sie oft einfacher zu adressieren.
Zusätzlich zur Minderung der Auswirkung von Mergekonflikten ermöglicht das Pullen von Updates auch das Integrieren von Änderungen, für die ein Commit ausgeführt wurde, in Ihren Branch, während Sie arbeiten. Auf diese Weise können Sie potenzielle Probleme vorab beheben. Beispielsweise können Änderungen an der Klassendefinition in anderen Dateien vorgenommen werden, die bewirken, dass der Code nicht mehr kompiliert wird. Diese Änderung würde keinen Zusammenführungskonflikt verursachen, wenn Sie ihn später zusammengeführt haben, aber es würde den Build unterbrechen, wenn Sie ihn nicht zuerst getestet haben. Es ist eine bewährte Methode, Updates häufig zu pullen, um Ihren Branch so nah wie möglich am Basisbranch zu halten.
Bereinigen des Verlaufs mit git rebase
Mit dem Befehl git rebase
(oder git pull --rebase
) wird Ihr Branchverlauf erneut generiert, sodass der aktuelle HEAD-Commit des Basisbranch als Grundlage verwendet wird. Anders ausgedrückt wird Ihr Branch aktualisiert, sodass er sich verhält, als wäre er nur vom aktuellen Zustand des Basisbranch gebrancht worden. Dies bedeutet, dass alle Ihre Änderungen mit dem aktuellen Zustand des Basisbranch verglichen werden, nicht mit dem ursprünglichen Commit, von dem Sie ursprünglich gebrancht haben. Umbasieren kann die Nachverfolgung des Verlaufs nach Ihrem letztlichen Merge erheblich vereinfachen, da ihre Commits auf lineare Weise den vorherigen parallelen Commits folgen. Es empfiehlt sich, direkt vor dem Upstreammerge ein Rebase für Ihren Branch auszuführen.
Erfahren Sie mehr über git rebase und das Auflösen von Mergekonflikten nach einem git rebase.