Tutorial - unverträgliche Änderungen zusammenführen
Wir haben in GermanTutorialMerge gesehen, wie wir einfache Änderungen zusammenführen können.
Mercurial kann auch mit komplexeren Fällen umgehen. Es ist nicht unüblich, daß zwei Personen die gleichen Zeilen einer Datei ändern und dann herausfinden müssen, wie die einzelnen Änderungen zusammenzuführen sind. Dieser Fall heißt Konflikt, und was wir dann tun müssen, nennt man auflösen.
Also erzeugen wir jetzt künstlich einen Fall, wo es einen Konflikt geben wird. Wie im letzten Teil auch, machen wir als erstes einen Klon von my-hello:
$ cd .. $ hg clone my-hello my-hello-not-cvs
Jetzt fügen wir eine weitere Quellzeile in hello.c ein:
$ cd my-hello-not-cvs $ vi hello.c
Wir ändern main:
int main(int argc, char **argv)
{
printf("hello, world!\n");
printf("sure am glad I'm not using CVS!\n");
return 0;
}
Und wir committen die Änderung:
$ hg commit -m "Give thanks for dodging bullet"
In TutorialFirstChange haben wir bereits ein changeset im Repository my-hello-new-output erzeugt, das ebenfalls eine Quellzeile hinzufügt. Was passiert, wenn wir die Änderung jetzt hereinziehen?
$ hg pull ../my-hello-new-output pulling from ../my-hello-new-output searching for changes adding changesets adding manifests adding file changes added 1 changesets with 1 changes to 1 files (+1 heads) (run 'hg heads' to see heads, 'hg merge' to merge)
Soweit gut! Machen wir jetzt einen Update.
$ hg update abort: update spans branches, use 'hg merge' or 'hg update -C' to lose changes
(vgl. Branch)
Wie auch in TutorialMerge, brauchen wir nun ein hg merge. Und wie vorher auch wird das Merge-Programm aufgerufen. Hier wird es die Änderungen nicht automatisch zusammenführen können, weil in den gleichen Zeilen der Quelldateien unterschiedlich geändert wurde, einmal vom Changeset das wir eben committed haben, und einmal von dem, das wir hereingezogen haben.
$ hg merge
An dieser Stelle hängt es davon ab, welche Programme auf unserem Rechner installiert sind. Wenn wir Glück haben, ist ein graphisches Merge-Tool installiert, und wir können die Änderungen, die zum Konflikt geführt haben, nebeneinander sehen und entscheiden, wie wir den Konflikt auflösen können.
Unten angezeigt ist der erzeugte Konflikt im vim-Editor auf einem Linux-System.
/* * hello.c * * Placed in the public domain by Bryan O'Sullivan * * This program is not covered by patents in the United States or other * countries. */ #include <stdio.h> int main(int argc, char **argv) { printf("hello, world!\n"); <<<<<<< /home/motoko/project/my-hello-not-cvs/hello.c.orig.197516148 printf("sure am glad I'm not using CVS!\n"); ||||||| /tmp/hello.c~base.aYR8Pf ======= printf("sure am glad I'm using Mercurial!\n"); >>>>>>> /tmp/hello.c~other.F7OpXy return 0; }
Mercurial benutzt pro Datei einen 3-Wege-Merge. Das bedeutet, daß es drei Dateien gibt, die beim Zusammenführungsprozess herangezogen werden:
- Lokale Datei (aus dem hiesigen Repository)
- Andere Datei (ursprünglich aus dem anderen Repository, d.h. die Version, die aus den hereingezogenen Changesets resultiert
- gemeinsamer Vorläufer (die letzte Version der Datei, bevor sie verzweigt)
Mehr Hintergrundinformation zu 3-Wege-Merges gibt es auf ThreeWayMerge im Revctrl wiki.
Wenn wir kein graphisches Mergetool installiert haben, werden wir in den Editor gebracht. Dort müssten wir den Konflikt dann von Hand auflösen, was höchst fehleranfällig und lästig ist. Das beste ist es, den Editor zu beenden, und das hg rollback Kommando zu benutzen, zum die Auswirkung des pull-Befehls rückgängig zu machen, ein passendes Merge-Programm zu installieren, und es noch einmal zu versuchen.
(Hinweis: Vor Mercurial-Version 0.9 war hg update -m statt hg merge zu benutzen, nud hg undo statt hg rollback).
(Hinweis: Was machen wir mit dem übriggebliebenen hello.c.orig?).
Und wie vorher müssen wir die zusammengeführten Änderungen wieder ins Repository committen, wenn der Merge erfolgt ist:
$ hg commit -m "Merged changes from my-hello-new-output"
Der Befehl sollte keine Ausgabe erzeugen.
Gehen wir weiter zu GermanTutorialConclusion.
Siehe auch: ImergeExtension