kutombawewe.net

Müssen erfahrene Entwickler noch mit Zusammenführungskonflikten umgehen?

Ich bin noch ein Software-Ingenieur in der Ausbildung, aber ich habe das folgende Sprichwort mehrmals gehört:

Gute Programmierer müssen sich nicht mit Zusammenführungskonflikten befassen.

Immer wenn ich mit anderen an einem Projekt arbeite, verliere ich nervig viel Zeit und Mühe bei der Lösung von Zusammenführungskonflikten. Also begann ich mich zu fragen, wie wahr dieses Sprichwort ist. Mir sind Techniken wie GitFlow und Agile bekannt, mit denen Entwickler ihre Arbeit effizient aufteilen, häufiger festschreiben und mehrere Codezweige verwalten können, sodass Zusammenführungskonflikte viel weniger wahrscheinlich sind. Aber sicher passieren sie immer noch und können möglicherweise Chaos anrichten?

Mit anderen Worten, wie viel Zeit und Mühe verlieren erfahrene Entwickler bei der Lösung von Zusammenführungskonflikten (wenn sie an ihren Projekten arbeiten könnten)? Können verfügbare Techniken die Auswirkungen von Zusammenführungskonflikten wirklich negieren?

57
lemeneux

Ich finde es etwas unaufrichtig zu sagen, dass gute Entwickler niemals Zusammenführungskonflikte haben, aber sie können sicherlich die Häufigkeit reduzieren, mit der dies geschieht. Es ist auch sehr wichtig, sich daran zu erinnern, dass Softwareentwicklung eine Teamaktivität ist. Aktionen anderer Teammitglieder können auch die Wahrscheinlichkeit von Zusammenführungskonflikten erhöhen oder verringern.

Zunächst ist es wichtig zu verstehen, wie Konflikte häufig zusammengeführt werden:

  • Zwei Personen nehmen unterschiedliche Änderungen an derselben Codezeile vor
  • Jemand beschließt, die gesamte Datei neu zu formatieren, damit jede Zeile geändert wird
  • Eine Datei löschen und dann ersetzen (das ist ein Baumkonflikt)
  • Code wird gleichzeitig von zwei verschiedenen Personen gelöscht und hinzugefügt (nicht ungewöhnlich bei Visual Studio-Dateien .vsproj).

Entwicklung Teams haben Wege gefunden, um diese Situationen zu vermeiden:

  • Stellen Sie sicher, dass jedes Teammitglied in verschiedenen Teilen des Codes arbeitet (d. H. Bei der Aufgabenzuweisung behandelt wird).
  • Codestandards, die vorschreiben, ob Sie Leerzeichen oder Tabulatoren verwenden, Standards benennen usw., sodass keine Neuformatierung des gesamten Code erforderlich ist
  • GitFlow, damit jeder an seinem eigenen Zweig arbeitet und Konflikte in der Pull-Request-Phase lösen kann (alle nachgelagerten Zusammenführungen funktionieren wunderbar)
  • Häufiges und routinemäßiges Zusammenführen aus der Entwicklung, um sicherzustellen, dass Ihr Feature-Zweig nie zu veraltet ist
  • Stellen Sie sicher, dass Ihre Funktionen klein genug sind, damit sie in 1-3 Tagen ausgeführt werden können.

Mit solchen Änderungen können Sie die Wahrscheinlichkeit von Konflikten erheblich minimieren. Sie werden sie niemals vollständig beseitigen können.

97
Berin Loritsch

Wahrscheinlich ist das Zitat unvollständig:

Gute Programmierer müssen sich nicht mit Zusammenführungskonflikten auseinandersetzen ...
... weil gute Programmierer Druckkraft ausüben.

Im Ernst, der einzige Weg, um Zusammenführungskonflikte zu vermeiden, besteht darin, alleine zu arbeiten (und selbst das hilft nicht; mir ist passiert, dass ich bei persönlichen Projekten Zusammenführungskonflikte mit mir selbst hatte). In einem Unternehmen, das erfahrene Entwickler anstellt, gibt es jedoch drei Faktoren, die den Schmerz von Zusammenführungskonflikten verringern:

  1. Hervorragende Kommunikation innerhalb des Teams.

    Das heißt, Sie wissen, woran Ihre Mitarbeiter arbeiten, und sie wissen, was Sie tun. Wenn Sie also möglicherweise einen Bereich ändern, an dem jemand aus Ihrem Team arbeitet, fragen Sie (oder sagen Sie es). Auf diese Weise reduzieren Sie das Risiko eines schmerzhaften Commits erheblich.

    Dies gilt insbesondere für die Refactoring-Aufgaben, die einen großen Teil der Codebasis erheblich beeinträchtigen oder Änderungen vornehmen können, deren Zusammenführung schmerzhaft ist. Angenommen, Sie ändern den Typ einer bestimmten Variablen überall, während Ihr Kollege eine Funktion implementiert, in der diese Variable verwendet wird. Sie riskieren nicht nur einen schmerzhaften Zusammenführungskonflikt, sondern brechen auch den Build während der Zusammenführung.

  2. Großartige Architektur.

    Wenn Sie an einer Legacy-Codebasis mit 4K-LOC-Dateien arbeiten und eine grundlegende Änderung benötigen, um Dutzende von Dateien zu ändern, besteht die Möglichkeit, dass bei jeder Änderung ein Zusammenführungskonflikt auftritt.

    Wenn die Architektur jedoch gut genug ist, reduzieren Sie das Risiko eines Zusammenführungskonflikts auf zwei Situationen: (1) wenn Sie eine Schnittstelle ändern, oder (2) wenn zwei Mitarbeiter genau denselben Teil der Anwendung ändern . Im ersten Fall kommunizieren Sie und reduzieren so das Risiko einer schmerzhaften Verschmelzung noch mehr. Im zweiten Fall führen Sie eine Paarprogrammierung durch und entfernen die Zusammenführung vollständig.

  3. Richtige Schnittstelle zu anderen Teams.

    Manchmal kommt es zu Zusammenführungskonflikten zwischen verschiedenen Teams. Angenommen, ein Team ändert ein Modul, während ein anderes den Code ändert, der dieses Modul verwendet.

    Erfahrene Entwickler tendieren dazu, geeignete Schnittstellen wie SOA zu verwenden, wodurch separate Teile des Systems technisch unabhängiger werden. Darüber hinaus stützen sie sich viel stärker auf bestimmte Praktiken wie Push-Anforderungen, um zu vermeiden, dass der Code eines anderen direkt geändert wird.

    Dies sind im Wesentlichen die ersten beiden Punkte, aber teamübergreifend: Sie kommunizieren besser und stellen sicher, dass sich die Teile besser vermischen.

27

Ein Kollege von mir traf auf einen Entwickler, der sich nicht mit Zusammenführungskonflikten befassen musste.

Er nahm einige Änderungen vor, führte sie zusammen und einige Tage später waren die Änderungen weg. Er fand heraus, dass jemand anderes (auch auf einem anderen Kontinent) Dateien ersetzt hatte, anstatt sie zusammenzuführen.

Er setzte die Änderungen wieder ein, leicht verärgert - und ein paar Tage später waren die Änderungen wieder weg.

Zu diesem Zeitpunkt hatte er ein langes Gespräch mit seinem Manager, der wiederum ein langes Gespräch mit dem Manager des anderen Teams führte, das möglicherweise Drohungen mit körperlicher Gewalt beinhaltete oder nicht, und der Manager des anderen Teams hatte offenbar ein langes Gespräch mit dem Entwickler in Frage, und das Verhalten hörte auf.

Erfahrene Entwickler können jedoch einige Zusammenführungskonflikte vermeiden.

  1. Wenn Sie eine Datei umbenennen, führen Sie eine Zusammenführung durch, bei der das Umbenennen der Datei (und offensichtlich dadurch verursachte Änderungen, wie das Ändern von include-Anweisungen oder Projektdateien) absolut die einzige Änderung ist.

  2. Stellen Sie sicher, dass alle Editoreinstellungen gleich sind, damit Sie keine Änderungen erstellen, indem Sie nur den Code betrachten.

  3. Sie erhalten Zusammenführungskonflikte, wenn zwei Personen den Code ändern an derselben Stelle. Wenn Sie also zu einer Datei hinzufügen, fügen Sie diese nicht am Ende hinzu, sondern an der logisch korrekten Stelle. Auf diese Weise sind Zusammenführungskonflikte viel weniger wahrscheinlich, wenn ein anderer Entwickler dasselbe tut.

  4. Führen Sie von Zeit zu Zeit die gemeinsame Codebasis in Ihrem Zweig zusammen, sodass Sie nie viele Zusammenführungskonflikte haben. Ein Konflikt ist einfach, 10 in einer Zusammenführung sind ein Problem.

  5. Das Zusammenführen von Ihrem Zweig zur gemeinsamen Codebasis muss nie einen Konflikt verursachen. Das liegt daran, dass Sie (4) getan haben, bevor Sie versucht haben, die Zusammenführung durchzuführen, sodass die Zusammenführung Ihren Code unverändert übernimmt.

Gerade bemerkt: Ja, es ist wahr, gute Entwickler haben niemals Zusammenführungskonflikte, die von ihrem Zweig in die gemeinsame Codebasis übergehen. Weil Zusammenführungskonflikte früher behandelt wurden.

21
gnasher729

Wie andere Antworten beschrieben haben, kommt es zu Zusammenführungskonflikten, unabhängig von Erfahrung oder Fähigkeiten, und ein Sprichwort, das behauptet, dass es sich um eine Art Schwäche handelt, die auf mangelnde Fähigkeiten zurückzuführen ist, ist lächerlich.

Andere Antworten haben Möglichkeiten aufgezeigt, wie erfahrene Entwickler lernen können, Zusammenführungskonflikte weniger wahrscheinlich zu machen, von der Verhinderung von Formatierungschaos über häufige Zusammenführungen bis hin zu einer besseren Teamkoordination. Ich denke jedoch, dass das von Ihnen angesprochene umfassendere Konzept eine gewisse Wahrheit enthält: Erfahrene Entwickler können besser werden Umgang mit Zusammenführungskonflikten, wenn sie auftreten.

Das Lösen von Zusammenführungskonflikten ist schwierig. Sie müssen die Konflikte finden, die Konfliktmarkierungen verstehen, herausfinden, was sich auf jeder Seite unter Berücksichtigung des Kontextes des Codes geändert hat (möglicherweise mit schwer zu erkennenden Problemen wie der Formatierung), und möglicherweise einzelne Commits von beiden Seiten der Zusammenführung nach nachschlagen die ursprüngliche Absicht verstehen, den Konflikt tatsächlich lösen, mögliche Auswirkungen der Änderung an anderer Stelle in der Codebasis (oder sogar in anderen Repositorys, wenn APIs oder Schnittstellen beteiligt sind) ansprechen, kompilieren, testen, festschreiben usw. Sie müssen sich daran erinnern, wie Lassen Sie das Versionskontrollsystem während dieses Vorgangs tun, was Sie wollen. Und dann gibt es kompliziertere Fälle: Konflikte mit verschobenen/gelöschten Dateien und Verzeichnissen; Konflikte mit Binärdateien; Konflikte mit generierten Dateien (einschließlich Visual Studio- und Xcode-Konfigurationsdateien; selbst wenn der Konflikt einfach ist, ist die Datei selbst erst bekannt, wenn Sie Erfahrung damit haben); Konflikte, die so schlimm sind, dass Sie die Person auf der anderen Seite der Zusammenführung finden und gemeinsam herausfinden; jede Menge Spaß.

Das ist alles eine Menge Dinge, mit denen man sich befassen muss. Es kann ein bisschen panisch sein: Sie fahren aufgeregt mit, um etwas zu erledigen, und plötzlich werden Sie mit Fehlermeldungen, seltsamen ">>>>>>" - Dingen in der Mitte Ihrer Dateien und a konfrontiert Bündel unbekannter Codes, die plötzlich von irgendwo anders auftauchten. Wie bei jeder anderen Programmieraufgabe kann Erfahrung dazu beitragen, die Fähigkeiten aufzubauen, um effizienter und weniger schmerzhaft damit umzugehen. Das erste Mal, wenn Sie auf einen Zusammenführungskonflikt stoßen, ist dies eine verwirrende Tortur, während das 500. Mal routinemäßiger ist. Zu diesem Zeitpunkt:

  • Sie können das Versionskontrollsystem verwenden, um die benötigten Informationen abzurufen und die gewünschten Änderungen vorzunehmen.
  • Sie sind mit dem Konfliktformat vertraut, lesen Unterschiede und visualisieren die Änderungen der Zusammenführung.
  • Möglicherweise haben Sie Tools, Open Source oder Werbung, um bei Zusammenführungen zu helfen aufgegriffen und gelernt, wie man sie effektiv einsetzt. Diese können immens helfen, so sehr, dass ich es fett schreiben werde: Gute Tools können dazu beitragen, Zusammenführungskonflikte weniger schmerzhaft zu machen .
  • Sie wissen, welche Arten von Konflikten in Ihren Projekten typisch sind (IDE-Konfigurationsdateien, das Ende von Zeichenfolgendateien, andere Hotspots, die sich häufig ändern), und passen Prozesse entweder an, um sie zu verhindern, oder können sie sehr schnell lösen. Häufige Konflikte wie "Oh, wir haben beide neue Zeichenfolgen am Ende der Datei hinzugefügt" lassen sich leicht beheben.
  • Sie können vorhersehen, welche Arten von Refactoring-Aufgaben Konflikte mit dem Rest Ihres Teams verursachen können, und koordinieren, um Schmerzen zu lindern.
  • Sie wissen, wann Sie nicht zusammenführen müssen. Wenn Sie eine Zusammenführung versuchen und feststellen, dass Sie einer von einer anderen Person gelöschten Funktion einen Parameter hinzugefügt haben, ist es möglicherweise besser, Ihre Strategie außerhalb des Rahmens des Konfliktlösungsprozesses zu stoppen und zu überdenken.
  • Sie wissen, wann Sie ein echtes Durcheinander gemacht haben, und es wird einfacher sein, die Zusammenführung erneut zu starten.
  • Sie wissen, wann sich die zugrunde liegende Codebasis zu stark geändert hat, um das "Zusammenführen" zu einer angemessenen Beschreibung Ihrer Arbeit zu machen. Sie notieren sich also die Änderungen, die Sie tatsächlich vornehmen möchten, werfen Ihre Änderungen weg und beginnen erneut mit einem neuen sauberen HEAD. Wenn Sie beispielsweise nur eine neue Bilddatei hinzufügen möchten und in der Zwischenzeit jemand alle Bilder des Projekts in Sprites umgewandelt hat, werden Sie nicht mehr wirklich zusammengeführt, sondern erledigen die Aufgabe auf eine andere Art und Weise. Blasen Sie also Ihre bisherigen Anstrengungen weg und machen Sie es auf die neue Art und Weise.

Mit all dem werden die meisten Zusammenführungskonflikte zur Routine, sodass weniger Zeit und Mühe aufgewendet wird, um sie zu lösen. Sie passieren immer noch und verursachen gelegentlich erhebliche Frustrationen, verursachen aber normalerweise weit weniger Chaos.

6
Zach Lipton

Es ist nicht so sehr die Existenz von Zusammenführungskonflikten, sondern wie sehr sie ein Problem verursachen.

Der "Schaden" durch Zusammenführungskonflikte mit unerfahrenen Entwicklern wird als großes Problem angesehen. Die Leute erfinden verrückte Quellcodeverwaltungsschemata oder verwenden die Quellcodeverwaltung nicht mehr zusammen, um diese „massiven“ Probleme zu vermeiden.

Mit einem erfahrenen Team verursachen Zusammenführungskonflikte jedoch kaum Probleme und werden schnell gelöst.

Ich denke, es gibt zwei Hauptunterschiede im Ansatz, die dazu beitragen:

  1. Verwenden Sie die Quellcodeverwaltung ordnungsgemäß. Feature-Zweige, viele kleine Commits, Ziehen vor dem Schieben, Testen vor dem Schieben usw.

  2. Die Veränderungen anderer Menschen verstehen. Wenn Sie die Funktions- und Codeänderungen verstehen, die mit Ihrer Änderung in Konflikt geraten sind, ist das Zusammenführen der beiden einfach.

Achten Sie bei Stand-Ups auf andere Aufgaben, sprechen Sie mit anderen Personen darüber, wie sie die Änderung umsetzen und wo Sie Konflikte verursachen können. Vereinbaren Sie im Voraus, wie die Dinge funktionieren sollen.

5
Ewan

Kontinuierliche Integration .

Um zu verstehen, warum CI berücksichtigt, dass die Änderungen in diesem Zweig mit einer oder mehreren Änderungen am Master in Konflikt stehen müssen, um einen Zusammenführungskonflikt zu erleben:

             A  B  C
master    *--*--*--*--*
           \         /
feature-x   *--------

Je länger der Zweig existiert, desto mehr Änderungen werden am Master vorgenommen, und desto höher ist die Wahrscheinlichkeit, dass eine dieser Änderungen einen Konflikt verursacht (selbst wenn die Änderung am Zweig sehr gering ist):

             A  B  C  D  E  F  G  H
master    *--*--*--*--*--*--*--*--*--*
           \                        /
feature-x   *-----------------------

Wir können verschiedene Maßnahmen ergreifen, um die Wahrscheinlichkeit von Konflikten zwischen zwei Änderungen zu verringern (z. B. das Vermeiden einer Neuformatierung oder eine sorgfältige Organisation der Arbeit, um zu vermeiden, dass mehrere Entwickler im selben Bereich arbeiten). Der einfachste Ansatz besteht jedoch darin, Änderungen schneller zusammenzuführen und zu reduzieren die Anzahl der am Master vorgenommenen Änderungen und damit die Wahrscheinlichkeit eines Konflikts:

             A     B  C
master    *--*--*--*--*--*
           \   /    \   /
feature-x   *--      *--

Wenn Sie CI richtig üben, sollte sich jeder zu einem gemeinsamen Zweig verpflichten mehrmals pro Tag, d. H. Alle paar Stunden. Das ist schnell genug, dass es in den meisten Fällen keine Änderungen am Master gibt, geschweige denn widersprüchliche Änderungen. Was noch besser ist, ist, dass selbst wenn Sie einen Konflikt sehen, Ihre Änderungen gering sind und die Lösung des Konflikts daher relativ einfach sein sollte - im schlimmsten Fall (wenn Sie Ihre Änderung vollständig verwerfen und erneut implementieren müssen), bei dem Sie verloren haben meistens ein paar Stunden arbeiten.


In den Kommentaren wurde vorgeschlagen, dass Entwickler regelmäßig from master anstelle von master zusammenführen sollten, was definitiv hilft, aber nicht so sehr wie die kontinuierliche Integration. In der folgenden Grafik hat beispielsweise jedes Commit auf dem Master (A, B und C) die Möglichkeit, mit einem der Commits auf dem Zweig (X, Y oder Z) in Konflikt zu geraten, was insgesamt 9 potenzielle Konflikte zur Folge hat. Wenn Sie am Ende einmal mit dem Master verschmelzen, müssen alle 9 potenziellen Konflikte gleichzeitig gelöst werden:

             A  B  C
master    *--*--*--*--*
           \         /
feature     *--*--*--
            X  Y  Z

Wenn wir stattdessen nach jeder Änderung am Master vom Master in unseren Feature-Zweig übergehen:

             A     B     C
master    *--*-----*-----*---*
           \  \     \     \ /
feature     *--*--*--*--*--*
            X     Y     Z

Dann müssen wir uns jedes Mal, wenn wir zusammenführen, mit den folgenden Konflikten befassen:

  • Bei der ersten Zusammenführung müssen wir alle Konflikte zwischen den Commits A und X lösen
  • In der zweiten Zusammenführung lösen wir alle Konflikte zwischen B und X, B und Y.
  • Bei der letzten Zusammenführung lösen wir alle Konflikte zwischen C und X, C und Y, C und Z.

Beachten Sie jedoch, dass wir Konflikte zwischen A und Y nie lösen mussten, da Änderung A in unseren Feature-Zweig eingefügt wurde, bevor Änderung Y vorgenommen wurde. Insgesamt haben wir es geschafft, 3 der 9 potenziellen Zusammenführungskonflikte zu vermeiden, indem wir regelmäßig vom Master zusammengeführt wurden.

Beachten Sie auch, dass jedes Mal, wenn wir die Anzahl potenzieller Konflikte zusammenführen, die Anzahl der potenziellen Konflikte zunimmt. Je länger der Feature-Zweig besteht, desto mehr Änderungen (und damit potenzielle Konflikte) werden am Master vorgenommen. Der wahre Killer ist jedoch, dass jede Änderung, die wir am Feature-Zweig vornehmen hat einen multiplikativen Effekt auf die Anzahl potenzieller Konflikte bei jeder Zusammenführung.

Lassen Sie uns nun überlegen, was passiert wäre, wenn wir CI praktiziert hätten:

             A     B     C
master    *--*--*--*--*--*--*
           \   / \   / \   /
feature     *--   *--   *--
            X     Y     Z

Diesmal mussten wir uns mit folgenden Zusammenführungskonflikten befassen:

  • Beim Zusammenführen von Change X mit Master mussten wir alle Konflikte zwischen A und X lösen
  • Beim Zusammenführen von Änderung Y mussten wir alle Konflikte zwischen X und V lösen
  • Beim Zusammenführen von Z mussten wir alle Konflikte zwischen Z und C lösen

Nach wie vor mussten wir keine Konflikte zwischen A und Y lösen, da Änderung A bereits in unseren Feature-Zweig eingefügt wurde, bevor wir Änderung Y vorgenommen haben. Diesmal mussten wir jedoch auch die Änderungen X und B, X und C nicht zusammenführen , oder Y und C, wobei 6 der 9 möglichen Konflikte vermieden werden.

Weitere Informationen/Anleitungen zum regelmäßigen Zusammenführen mit dem Master finden Sie in dieser Frage:

Ist es besser, "oft" zusammenzuführen oder erst nach Abschluss eine große Zusammenführung von Feature-Zweigen durchzuführen?

1
Justin

"Programmierer machen ständig Fehler " --- John Carmack

Leute, die Behauptungen aufstellen wie "Ich bin ein Rockstar-Entwickler" oder "Gute Programmierer müssen sich nicht mit Zusammenführungskonflikten auseinandersetzen ...", sind meistens Poser, die in der allgemeinen Softwareentwicklungs-Community reichlich vorhanden zu sein scheinen und sollte als solche zusammenfassend ignoriert werden.

Das Erstellen von Software, die in der Produktion von tatsächlichen Personen außer Ihnen selbst verwendet wird, ist keine triviale Angelegenheit. Sie werden Fehler machen ... und die Leute, mit denen Sie arbeiten, werden oft Fehler machen. Eine Einschätzung der technischen Kompetenz eines jeden darauf zu stützen, ob er sich mit Zusammenführungskonflikten befassen muss oder nicht, ist auf den ersten Blick Unsinn.

0
user405887

Wer das gesagt hat, hat eine bestimmte Vorstellung von "gutem Codierer" im Sinn, die wahrscheinlich so aussieht:

  • Der gute Programmierer arbeitet alleine an einem großartigen Programm, das er oder sie alleine entworfen hat.
  • Es gibt keine Gabeln des Programms oder Verzweigungszweige oder ähnliches, und daher gibt es keine Rebasing-Aktivitäten, die Konflikte verursachen.
  • Wenn in alten Versionen des Programms Fehler gefunden werden, aktualisieren die Benutzer entweder pflichtbewusst auf die aktuelle Baseline oder die nachgeschalteten Paketbetreuer portieren die erforderlichen Korrekturen von der aktuellen Baseline zurück (daher sieht Good Coder die beteiligten Konflikte nie).
  • In dem seltenen Fall, dass ein Außenstehender eine Korrektur oder Verbesserung für das Great Program bereitstellt, muss er einen Patch bereitstellen, der sauber auf den aktuellen Entwicklungskopf angewendet wird, damit der Good Coder vor jeglichen Vorwärtsportierungsbemühungen mit Konfliktlösung geschützt ist.
  • Schließlich ändert Good Coder niemals die Reihenfolge seiner Commits (z. B. mit der interaktiven Rebase von git).
0
Kaz