Gibt es einen Unterschied zwischen Merges in Svn und Git oder Mercurial?


12

Nach meinem Verständnis ist SVN einfach zu verzweigen. Schwer zu verschmelzen. Warum das? Gibt es einen Unterschied, wie sie verschmelzen?

git  svn  mercurial  dvcs 

Antworten:


21

In meiner Antwort zum Stapelüberlauf finden Sie eine sehr konkrete Situation, in der Mercurial (und Git) problemlos zusammengeführt werden und in der Subversion einen falschen Konflikt darstellt. Die Situation ist ein einfaches Refactoring, das in einem Zweig ausgeführt wird, in dem Sie einige Dateien umbenennen.

In Bezug auf die Antwort des Hammers gibt es dort eine Reihe von Missverständnissen:

  • Subversion, Mercurial und Git verfolgen alle repository-weiten Snapshots des Projekts. Die Bezeichnung " Versionen" , " Überarbeitungen" oder " Änderungssätze" macht keinen Unterschied. Sie sind alle logisch atomare Schnappschüsse einer Reihe von Dateien.

  • Die Größe Ihrer Commits spielt beim Zusammenführen keine Rolle. Alle drei Systeme werden mit dem Standard-Drei-Wege-Zusammenführungsalgorithmus zusammengeführt, und die Eingaben für diesen Algorithmus sind

    • größte gemeinsame Ahnenversion
    • Version auf einem Zweig
    • Version auf einem anderen Zweig

    Es spielt keine Rolle, wie die beiden Zweigversionen erstellt wurden. Sie können seit der Vorgängerversion 1000 kleine Commits verwendet haben, oder Sie können 1 Commit verwendet haben. Alles, was zählt, ist die endgültige Version der Dateien. (Ja, das ist überraschend! Ja, viele DVCS-Guides verstehen das fürchterlich falsch.)

Er bringt auch einige gute Punkte zu den Unterschieden vor:

  • Subversion hat einige „Voodoo“ , wo Sie verschmelzen können /trunkin, sagen wir, /branches/foo. Mercurial und Git verwenden dieses Modell nicht - Verzweigungen werden stattdessen direkt in der Historie modelliert. Die Geschichte wird daher zu einem gerichteten azyklischen Graphen, anstatt linear zu sein. Dies ist ein viel einfacheres Modell als das von Subversion verwendete, und dies erspart eine Reihe von Eckfällen.

  • Sie können eine Zusammenführung leicht verzögern oder sogar jemand anderem überlassen, damit umzugehen. Wenn hg mergeSie eine Menge Konflikte haben, können Sie Ihren Kollegen darum bitten hg pull, und dann hat er genau den gleichen Zustand. Er kann also hg mergeKonflikte besser lösen als Sie.

    Dies ist bei Subversion sehr schwierig, da Sie ein Update durchführen müssen, bevor Sie ein Commit durchführen können. Sie können die Änderungen auf dem Server nicht einfach ignorieren und weiterhin in Ihrer eigenen anonymen Filiale festschreiben. Im Allgemeinen zwingt Subversion Sie, mit einer schmutzigen Arbeitskopie herumzuspielen, wenn Sie svn update. Dies ist riskant, da Sie Ihre Änderungen nicht an einem sicheren Ort gespeichert haben. Mit Git und Mercurial können Sie zuerst ein Commit durchführen und dann nach Bedarf aktualisieren und zusammenführen.

Der wahre Grund, warum Git und Mercurial besser miteinander verschmelzen als Subversion, ist eine Frage der Implementierung. Es gibt Umbenennungskonflikte, mit denen Subversion einfach nicht umgehen kann, obwohl klar ist, wie die richtige Antwort lautet. Mercurial und Git erledigen das problemlos. Aber es gibt keinen Grund, warum Subversion diese Probleme nicht lösen könnte - eine Zentralisierung ist sicherlich nicht der Grund.


4
gute Antwort! Ich würde zweimal abstimmen, wenn ich könnte. :) Ich würde auch hinzufügen , dass SVN Buch , das Sie beziehen sich auf in SO Antwort klar zugibt , dass „Subversion Merge-Tracking - Funktion eine äußerst komplexe interne Implementierung hat ...“ - dies allein ist ein ziemlich gutes Indiz dafür , dass Funktion unzuverlässig ist
gnat

2
... und selbst bei dieser äußerst komplexen Implementierung kann der gemeinsame Vorfahr nur in einfachen Fällen korrekt ermittelt werden.
Jan Hudec

Über verzögerte Zusammenführungen - verstehe es nicht - mit SVN kann mein Kollege zu / checkout trunk updaten und dann von meinem Zweig in ihn zusammenführen.
Gill Bates

@GillBates: Ich spreche von einer Situation, in der Sie noch keinen Zweig für Ihre Arbeit eingerichtet haben - wenn Sie trunkin SVN arbeiten. Mit einem DVCS können Sie ein Commit durchführen, ohne es zu teilen. In SVN wirkt sich dies svn commitjedoch direkt auf andere aus, die an demselben Zweig arbeiten. Selbst wenn wir beide in einer Filiale in SVN arbeiten, kann ich meine Arbeit nicht aufgeben, ohne mich sofort mit Ihrer Arbeit verbinden zu müssen. Das macht Commits etwas beängstigend - was eine beängstigende Eigenschaft für ein Versionskontrollsystem ist! :-)
Martin Geisler

6

Das Hauptproblem liegt in der Art und Weise, wie diese Systeme eine versionierte Verzeichnisstruktur darstellen.

Das Grundkonzept von Subversion, um das sich das gesamte System dreht, ist das einer Version (oder, in svn lingo, "Revision"): eine Momentaufnahme einer Datei zu einem bestimmten Zeitpunkt. Solange der Verlauf perfekt linear ist, ist alles in Ordnung. Wenn Sie jedoch Änderungen aus zwei unabhängigen Entwicklungslinien zusammenführen müssen, muss svn die aktuellen Versionen von beiden vergleichen und dann einen Drei-Wege-Vergleich zwischen der letzten gemeinsam genutzten Version durchführen und die beiden Kopfversionen. Linien, die in einem der Köpfe, aber nicht im anderen, geändert erscheinen, können leicht aufgelöst werden. Linien, die in beiden Köpfen genau gleich stark voneinander abweichen, sind schwieriger, aber normalerweise machbar. Zeilen, die auf unterschiedliche Weise abweichen, sind das, was svn sagen lässt: "Ich kann das nicht herausfinden, Mensch, bitte lösen Sie das für mich."

Im Gegensatz dazu werden Git- und Mercurial-Tracks eher als Versionen geändert . Das gesamte Repository ist eine Baumstruktur von Änderungssätzen, die jeweils von einem übergeordneten Element abhängt, wobei ein übergeordnetes Änderungssatz eine beliebige Anzahl von untergeordneten Elementen haben kann und der Baumstamm ein leeres Verzeichnis darstellt. Mit anderen Worten, git / hg sagt "zuerst hatte ich nichts, dann wurde dieser Patch angewendet, dann dieser Patch usw.". Wenn Sie zwei Entwicklungslinien zusammenführen müssen, weiß git / hg nicht nur, wie jeder Kopf aktuell aussieht und wie die letzte gemeinsame Version aussah, sondern auch, wie der Übergang stattgefunden hat, was eine viel intelligentere Zusammenführung ermöglicht.

Eine andere Sache, die das Zusammenführen in einem DVCS erleichtert, ist eine indirekte Folge der Trennung der Konzepte von Festschreiben und Pushund alle Arten von Cross-Merges zwischen zwei beliebigen Klonen desselben Repositorys zu jeder Zeit zuzulassen. Bei svn neigen die Benutzer dazu, große Änderungsmengen mit häufig nicht zusammenhängenden Änderungen festzuschreiben, da ein Festschreiben auch eine Aktualisierung des zentralen Repositorys darstellt, die alle anderen Teammitglieder betrifft. Wenn du eine kaputte Version begehst, werden alle sauer auf dich sein. Da die meisten Setups einen vernetzten SVN-Server beinhalten, werden beim Festschreiben auch Daten über das Netzwerk gepumpt. Dies bedeutet, dass der Workflow durch das Festschreiben erheblich verzögert wird (insbesondere, wenn Ihre Arbeitskopie veraltet ist und Sie zuerst ziehen müssen). Bei git und mercurial findet das Festschreiben lokal statt, und da beide sehr effizient mit lokalen Dateisystemen umgehen, wird es normalerweise sofort beendet. Infolgedessen nehmen die Leute (sobald sie sich daran gewöhnt haben) kleine inkrementelle Änderungen vor und wenn es dann funktioniert, Push ein Dutzend oder so begeht auf einmal. Wenn dann die Zeit für die Zusammenführung gekommen ist, verfügt der SCM über viel detailliertere Informationen und kann Konflikte sicher und automatisch besser lösen.

Und dann sind da noch die netten Details, die die Sache noch einfacher machen:

  • Sie können mehrere Köpfe haben und sich trotzdem auf einen festlegen. Im Gegensatz zu Subversion müssen Sie Pull, Update und Merge nicht kombinieren, bevor Sie einen erneuten Commit ausführen
  • Verzeichnisse werden nicht speziell behandelt. Stattdessen wird der Pfad nur als ein großer Dateiname betrachtet, und alle Ihre Verzeichnisse müssen zu jeder Zeit dieselbe Revision aufweisen. Dies bedeutet, dass Sie Subversion Voodoo nicht ausführen können, wenn sich die Unterordner eines Projekts in verschiedenen Revisionen befinden. Es ist jedoch auch weniger wahrscheinlich, dass die Arbeitskopie zu einem großen, nicht zu bewältigenden Durcheinander wird, und interessanterweise wird eine Verschiebung nicht als Löschen dargestellt -and-add (was in svn völlig kaputt gehen würde, wenn die Metadaten nicht nachgerüstet worden wären), sondern einfach als Umbenennung; Wenn Sie eine Datei verschieben, bleibt der gesamte Verlauf erhalten. Durch das Zusammenführen können sogar Änderungen an der verschobenen Datei vorgenommen werden, die nach dem Verschieben in einer nicht verschobenen Version derselben Datei in einem anderen Zweig vorgenommen wurden
  • Die meiste Zeit, Sie eigentlich gar nicht brauchen , um Zweig: Sie stattdessen nur das gesamte Repository klonen. Klonen ist billig, vor allem, wenn es auf demselben Dateisystem ausgeführt wird und wenn Sie den Klon entfernen möchten, löschen Sie einfach das Verzeichnis, in dem es sich befindet, und das ist es. Sie müssen dafür nicht einmal hg oder git verwenden.
  • Es gibt nur wenige (wenn überhaupt) Einschränkungen für das, was Sie zusammenführen können. Sie können sechs Klone desselben Repositorys haben und von A nach B, dann von C nach B, dann von B nach D, dann von C nach D und zurück zu B zusammenführen (oder vielmehr drücken oder ziehen; eine explizite Zusammenführung ist häufig nicht erforderlich) zu A, D bis E, zu jeder Zeit und so oft Sie möchten.
  • Sie können eine Zusammenführung testen, indem Sie eines der Repositorys klonen, die Sie zusammenführen möchten, und dann von dem anderen in das Repository ziehen. Wenn es das tut, was Sie wollen, können Sie zum eigentlichen Ziel zurückkehren. Wenn dies nicht der Fall ist, werfen Sie den Klon weg und beginnen von vorne.

2
Ich muss einige Korrekturen erwähnen und fügt zu beantworten: 1. SVN Revisionen sind global pro-Repository , Revision alle Dateien in Repo repräsentieren in irgendeinem Moment 2. Merge - Technologie sind im Grunde gemeinsam in SVN und DVCS - wenn die Datei in Merge - Dateien nur die geänderten Auf die gleiche Weise führt das Zusammenführen zu der gleichen Anzahl von Konflikten für SVN und DVCS - alle SCMs werden immer noch auf Zeichenfolgenebene ausgeführt, nicht auf einem logischen Block - Sie ignorieren grundlegende Muster. Branch | merge funktioniert in SVN, wenn / dev / brain und / dev / hands funktionieren
Lazy Badger

2
Teil 2: Intelligentes Zusammenführen in DVCS geschieht meistens , weil sie im Gegensatz zu Subversion Verschiebungen von Dateien verfolgen und verarbeiten und SVN dies überhaupt nicht tut. Dies bedeutet, dass jede Operation, die Dateien verarbeitet, auf einer Seite geändert und umbenannt wird zweitens wird scheitern. Das Verzweigen mit Zweigen und das Klonen sind nur verschiedene Strategien des Verzweigens mit den gleichen Lebensrechten, die man anwenden kann, um "... hängt von ... ab"
Lazy Badger,

@ LazyBadger: Au contraire. Subversion tut Spur bewegt / Umbenennungen, die teilweise falsche Konflikte verursacht , weil es von Umbenennungen in merge ist Handhabung einfach Buggy ist und zum Teil , weil es Sonderfälle , die nur schwer oder überhaupt nicht richtig zu handhaben . Letzteres ist der Grund, warum git (und mercurial kopierte es) Umbenennungen nicht nachverfolgt und sie beim Zusammenführen errät. Was gut funktioniert, wenn der Inhalt noch so ähnlich ist, dass er zusammengeführt werden kann (wenn Sie ihn brauchen), und wenn Sie es nicht anders machen.
Jan Hudec

@JanHudec - Entschuldigung, SVN-Handle verschiebt | benennt sich nicht um bei atomarer Aktion (DVCS-Methode - "Umbenennen"), sondern als "Löschen + ...", wodurch - Baumkonflikte entstehen, bei denen es in DVCS nicht vorkommt ( echtes Umbenennen) ). Mercurial- Tracks werden explizit umbenannt ( hg mvoder hg addremove --similarity...), Git verwendet Heuristik, aber beide behandeln Umbenennungen . Ich kann sogar mit 1 String Unterschied in zusammengeführten Dateien einen Baumkonflikt bekommen! Sie müssen einige Subversion-Aspekte noch einmal lernen, sorry.
Lazy Badger

5
Jetzt werden wir ziemlich technisch :-) Sowohl Subversion- als auch Mercurial-Tracks werden kopiert , nicht umbenannt. Beide Systeme verfolgen , rename a bwie copy a b; remove aund beide tun es in einem Atom begehen. Der Unterschied im Zusammenführungsverhalten ergibt sich aus der unterschiedlichen Behandlung von Eckfällen und aus Subversion, die mehr Zusammenführungen als Mercurial und Git zulässt. Schließlich erkennt Git Umbenennungen beim Zusammenführen und Protokollieren - wir denken darüber nach, dies auch in Mercurial hinzuzufügen.
Martin Geisler
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.