Mit Mercurial Dateien verwalten

Aus LinuxUser 05/2014

Mit Mercurial Dateien verwalten

© Sabaca, sxc.hu

Auf den Zweig gekommen

Die Versionsverwaltung Mercurial ermöglicht es, beim Programmieren mit Ideen zu spielen und Neues auszuprobieren, ohne hart erarbeitete Ergebnisse zu verlieren.

Bevor ein Bash-Skript genau das ausführt, was sein Ersteller wünscht, braucht es in der Regel einige Überarbeitungen. Damit die Zwischenschritte nicht verloren gehen, speichern viele Programmierer und Autoren die jeweils letzte Version unter einem eigenen Dateinamen.

So sammeln sich dann screenshot1.sh, screenshot2.sh und so weiter auf der Festplatte. Nicht nur die vielen Dateien stellen dabei ein Problem dar: Spätestens nach einer Woche weiß selbst der hartgesottenste Eidetiker nicht mehr, was genau denn nun screenshot2.sh von der Vorversion unterscheidet.

Hier schafft die Versionsverwaltung Mercurial Abhilfe. Sie lässt sich einfach bedienen, ist in der Praxis vielfach erprobt und bietet zahlreiche Funktionen. Im Gegensatz zu vielen anderen Programmen dieser Art setzt Mercurial kein zentrales Repository voraus. Das hindert trotzdem weitere Helfer nicht daran, ganz einfach am Projekt mitzuarbeiten: Wenn es gar nicht anders geht, schicken sich die Beteiligten die Änderungen ganz einfach per Mail.

Installation

Alle größeren Distributionen bieten Mercurial in ihren Paketquellen an. In der Regel heißt das passende Paket einfach mercurial. Unter Ubuntu 13.10 spielen Sie es mittels des folgenden Kommandos ein:

$ sudo apt-get install mercurial

Anschließend erstellen Sie mit einem Texteditor die zugehörige Konfigurationsdatei ~/.hgrc und legen in dieser einen Abschnitt [ui] nach dem Strickmuster aus Listing 1 an. Damit kennt die Software Ihre Daten, ohne diese verweigert es sonst den Dienst.

Listing 1

[ui]
username = Max Mustermann <max@mustermann.de>

Um die Änderungen an den zu versionierenden Dateien aufzuzeichnen, müssen Sie zunächst in Ihrem Home-Verzeichnis eine entsprechende Lagerstätte einrichten. In den folgenden Beispielen benutzen wir dazu das Arbeitsverzeichnis skripte:

$ mkdir skripte
$ cd skripte
$ hg init

Falls Sie sich nun fragen, warum das Binary eines Programms namens Mercurial hg heißt: Mercurial ist das englische Wort für Quecksilber, und dessen chemisches Symbol lautet Hg (griech.: Hydrargyros, “flüssiges Silber”). Statt manuell legen Sie bei Bedarf ein Arbeitsverzeichnis auch direkt mit Mercurial an:

$ hg init skripte

In jedem Fall erstellt Mercurial im Arbeitsverzeichnis ein verstecktes Unterverzeichnis namens .hg. In diesem sogenannten Repository lagern zukünftig nicht nur alle Änderungen, sondern zusätzlich auch einige weitere Informationen, darunter das Datum für jede Änderung und eine kurze Beschreibung. Das Arbeitsverzeichnis enthält ab sofort immer die aktuellen Fassungen der versionierten Dateien.

Während Sie an den Dateien in Ihrem Arbeitsverzeichnis nach Lust und Laune Änderungen vornehmen dürfen, sollten Sie das Verzeichnis .hg weder verändern noch löschen. Andernfalls laufen Sie Gefahr, alle älteren Versionen Ihrer Dateien zu zerstören oder zu verlieren.

Aufnahmeprüfung

Vielleicht möchten Sie nicht alle Dateien im Arbeitsverzeichnis mit Mercurial überwachen – etwa, wenn ein Bash-Skript seine Zwischenergebnisse in größeren temporären Dateien ablegt. Damit sich Mercurial an solchen Daten nicht unnötig abarbeitet, geben Sie explizit an, welche Files Sie mit Mercurial im Auge behalten möchten:

$ hg add screenshot.sh readme.txt

Damit beachtet das Programm ab sofort die beiden angegebenen Dateien. Möchten Sie tatsächlich sämtliche Dateien versionieren, stellen Sie mit hg add alle auf einmal unter die Fuchtel der Versionsverwaltung (Abbildung 1). Mercurial notiert sich dabei allerdings nur die Dateien, die zu diesem Zeitpunkt im Verzeichnis liegen. Kommt später eine weitere hinzu, müssen Sie diese nachträglich mit hg add Datei hinzufügen.

Abbildung 1: Möchten Sie die Dateien in einem Verzeichnis beobachten, wechseln Sie in dieses, erstellen darin ein Repository und melden dann alle Dateien bei der Versionsverwaltung an.

Abbildung 1: Möchten Sie die Dateien in einem Verzeichnis beobachten, wechseln Sie in dieses, erstellen darin ein Repository und melden dann alle Dateien bei der Versionsverwaltung an.

Check-in

Mercurial kennt jetzt das Arbeitsverzeichnis, hat darin einen Speicherplatz für die älteren Versionen angelegt (das Repository) und weiß, welche Dateien Sie zukünftig bearbeiten wollen. Im nächsten Schritt sichern Sie den aktuellen Stand der Dateien mit folgendem Kommando:

$ hg commit

Mercurial startet daraufhin den Standard-Texteditor der Distribution, meist also Vi oder Nano (Abbildung 2). Je nach Distribution dürfen Sie sich auch einen Editor aus einer Liste aussuchen. In jedem Fall verlangt Mercurial eine kurze Beschreibung für die zu erfassende(n) Datei(en). Falls Sie darauf verzichten und den Editor einfach beenden, bricht Mercurial den kompletten Vorgang ab.

Abbildung 2: Sichern Sie den aktuellen Stand von Mercurial per Commit, verlangt das Programm nach einer Beschreibung für die Version.

Abbildung 2: Sichern Sie den aktuellen Stand von Mercurial per Commit, verlangt das Programm nach einer Beschreibung für die Version.

Es lohnt sich, an dieser Stelle mehr zu schreiben als nur “Die erste Version” oder Ähnliches. Wenn Sie beschreiben, was Sie da überhaupt im Repository ablegen, tun Sie sich später leichter, sobald die Logfiles lang ausfallen. Alle Zeilen, die mit einem HG: beginnen, ignoriert Mercurial. Speichern Sie den Text und beenden Sie den Editor. In Nano etwa klappt das mit [Strg]+[O],[Eingabe],[Strg]+[X].

Jetzt haben Sie die Möglichkeit, weitere Änderungen an der von der Versionskontrolle überwachten Datei vorzunehmen. Die Unterschiede zur gerade eingelagerten Version listet jederzeit der Befehl hg diff auf. Die resultierenden Ausgaben entsprechen jenen des Kommandozeilenprogramms Diff: Sie erhalten die Namen der betroffenen Dateien, dann die Nummer der Zeile, die Sie verändert haben, und darunter die eigentliche Änderung (Abbildung 3).

Abbildung 3: In der Datei <code srcset=

screenshot.sh hat sich etwas verändert.” width=”300″ height=”182″ /> Abbildung 3: In der Datei screenshot.sh hat sich etwas verändert.

Mercurial protokolliert Änderungen nicht von sich aus. Vielmehr bleibt es Ihnen überlassen, das Werkzeug darauf hinzuweisen, dass jetzt eine neue Version einer oder mehrerer Dateien vorliegt. Dies geschieht wiederum mit dem bekannten Befehl hg commit. Die dabei notwendige Beschreibung übergeben Sie am einfachsten mit dem Parameter -m. Mercurial verzichtet dann darauf, extra einen Editor zu öffnen:

$ hg commit -m 'Die zweite Version'

Haben Sie eine Version eingecheckt, stellen dann aber fest, dass Sie mit dieser nicht zufrieden sind, macht hg rollback die Aktion rückgängig. Das ist etwa dann nützlich, wenn Sie in der letzten Commit-Nachricht einen Tippfehler entdeckt haben.

Liegen in Ihrem Arbeitsverzeichnis mehrere Dateien, so finden Sie schnell mit hg status heraus, welche der Dateien Sie geändert haben. In der zugehörigen Ausgabe aus Abbildung 4 steht das M vor dem Dateinamen für “modified”, also geändert.

Abbildung 4: Ein <code srcset=

hg status zeigt, dass sich die Datei screenshot.sh verändert hat. Die Sicherheitskopie screenshot.sh~ hat der Texteditor angelegt. Das Fragezeichen weist darauf hin, dass diese nicht unter der Kontrolle von Mercurial steht.” width=”300″ height=”86″ /> Abbildung 4: Ein hg status zeigt, dass sich die Datei screenshot.sh verändert hat. Die Sicherheitskopie screenshot.sh~ hat der Texteditor angelegt. Das Fragezeichen weist darauf hin, dass diese nicht unter der Kontrolle von Mercurial steht.

Haben Sie sich bei der Arbeit einmal verzettelt, dann stellt der Befehl hg update --clean die letzte Version wieder her. Doch Vorsicht: Dabei gehen alle seit dem letzten Commit vorgenommenen Änderungen verloren. Welche älteren Versionen im Repository lagen, verrät das Kommando hg log. Sie erhalten eine Liste ähnlich der aus Abbildung 5.

Abbildung 5: Hier gab es zwei Commits, wobei Mercurial die neueste Version oben anzeigt (achten Sie auch auf die Nummerierung hinter <code srcset=

Änderung).” width=”300″ height=”134″ /> Abbildung 5: Hier gab es zwei Commits, wobei Mercurial die neueste Version oben anzeigt (achten Sie auch auf die Nummerierung hinter Änderung).

Dort erfahren Sie unter anderem über Date wann die Version ins Repository gewandert ist beziehungsweise der Commit erfolgte, und wer der Autor der Änderungen war. Mit hg log --patch zeigt Mercurial zusätzlich noch die Änderungen zur jeweiligen Vorversion an.

Identifikation

Jede Version erhält zudem eine relativ kryptische Identifikationsnummer – in Abbildung 5 lautet diese 0:7427a280a3e4. Die Zahl vor dem Doppelpunkt nennt die Versionsnummer, im Mercurial-Jargon als Revision oder Changeset bezeichnet. Die Null entspricht der Ausgangsversion, dann folgt die Revision 1 und so weiter.

Mit jedem Commit erhöht sich automatisch die Revision. Um zu einer älteren Revision zurückzukehren, verwenden Sie den Befehl hg update. Nach einem hg update 0 liegt im Arbeitsverzeichnis wieder die ältere Revision 0 (Abbildung 6). Beachten Sie, dass die nachfolgenden Revisionen weiterhin im Repository enthalten bleiben. Mit hg update 1 springen Sie folglich zur nächsten Revision 1.

Abbildung 6: Hier liegt jetzt im Arbeitsverzeichnis wieder der Stand von 18:06 Uhr. Die Dateien haben also den Inhalt, den sie beim ersten Commit hatten.

Abbildung 6: Hier liegt jetzt im Arbeitsverzeichnis wieder der Stand von 18:06 Uhr. Die Dateien haben also den Inhalt, den sie beim ersten Commit hatten.

Die Nummern der Revisionen erweisen sich bei der täglichen Arbeit als recht sperrig. Daher besteht die Möglichkeit, jeder Version einen beliebigen Namen, englisch: “Tag”, anzuheften. Programmierer wählen meist eine individuelle Versionsnummer. Der folgende Befehl gibt der Revision 3 den Namen bluemchen:

$ hg tag -r 3 bluemchen

Zu dieser springen Sie dann ab sofort nicht mehr nur mit hg update 3, sondern auch mit hg update bluemchen. Für die letzte Version im Repository gibt es zudem den Alias-Namen tip. Mit ihm kommen Sie immer wieder schnell zur aktuellsten Version zurück.

Konfliktlösung

Entdecken Sie im Skript einen Fehler, der schon in vorherigen Revisionen enthalten war, springen Sie erst per hg update zurück, korrigieren den Fehler, und führen dann ein hg commit durch. Die so in der älteren Version vorgenommenen Änderungen übernehmen Sie anschließend mit dem Kommando hg merge in die aktuelle Version.

Falls das aufgrund eines Konflikts fehlschlägt, lassen Sie sich zunächst mit hg resolve --list die betroffenen Dateien anzeigen. Anschließend führen Sie diese mit folgendem Kommando zusammen:

$ hg resolve Datei

Hilft das nicht, bleibt nur der Ausweg, den Konflikt manuell zu beheben. Die problematischen Stellen hat Mercurial dabei schon im Skript markiert (Abbildung 7). Danach markieren Sie mittels des Kommandos

$ hg resolve --mark Datei

die betroffene Datei als korrigiert und führen einen Commit aus (Abbildung 8). Der Befehl hg log zeigt anschließend jeweils neben dem Punkt Vorgänger an, in welcher Version Sie den Fehler behoben haben (Abbildung 9).

Abbildung 7: Hier wusste Mercurial nicht, welche Zeile es verwenden sollte.

Abbildung 7: Hier wusste Mercurial nicht, welche Zeile es verwenden sollte.

Abbildung 8: Hier hat der Autor einen Fehler in einer früheren Revision korrigiert (<code srcset=

hg update 0, hg commit) und dann diese Korrekturen mit der aktuellen Version zusammengeführt (hg merge). Den dabei entstandenen Konflikt musste er manuell lösen.” width=”300″ height=”216″ /> Abbildung 8: Hier hat der Autor einen Fehler in einer früheren Revision korrigiert (hg update 0, hg commit) und dann diese Korrekturen mit der aktuellen Version zusammengeführt (hg merge). Den dabei entstandenen Konflikt musste er manuell lösen.

Abbildung 9: Mercurial merkt sich im Log selbst komplexe Operationen in verschiedenen Revisionen.

Abbildung 9: Mercurial merkt sich im Log selbst komplexe Operationen in verschiedenen Revisionen.

Wenn Sie eine Datei umbenennen, verschieben oder löschen möchten, gilt es, den jeweils passenden Mercurial-Befehl dafür zu nutzen (Listing 2). Würden Sie die herkömmlichen Befehle cp, mv oder rm verwenden, bekäme das Versionskontrollsystem von den Aktionen nichts mit. Durch die eigenen Kommandos protokolliert Mercurial aber, was wann mit welcher Datei passiert, und kann diesen Vorgang später wieder rückgängig machen.

Listing 2

$ hg cp original.txt kopie.txt
$ hg mv original.txt umbenannt.txt
$ hg rm original.txt

Grüner Zweig

Angenommen, das Bash-Skript screenshot.sh aus unserem Beispiel schießt mittlerweile brav seine Screenshots. Bei der Suche im Netz stolpern Sie jedoch über das neue Programm supershot.sh, das Sie unbedingt in Ihr Skript einbauen möchten.

Um jetzt den bestehenden funktionierenden Code nicht zu zerstören, haben Sie die Möglichkeit, einen neuen Zweig in der Entwicklung (englisch: “branch”) zu erstellen:

$ hg branch supershot

Der Befehl erstellt einen neuen Zweig mit dem frei gewählten Namen supershot und wechselt in ihn hinein (Abbildung 10). Dort nehmen Sie nun die gewünschten Änderungen auf und führen einen Commit aus. Zum alten Zweig zurück gelangen Sie jederzeit via hg update default, in den Branch supershot springt analog hg update supershot.

Abbildung 10: Wenn Sie einen Branch erstellen, haben Sie zwei verschiedene Entwicklungslinien oder Zweige, zwischen denen Sie hin- und herspringen können.

Abbildung 10: Wenn Sie einen Branch erstellen, haben Sie zwei verschiedene Entwicklungslinien oder Zweige, zwischen denen Sie hin- und herspringen können.

Sie dürfen beliebig viele Branches anlegen und so verschiedene Versionen der Skripte weiterentwickeln. Alle derzeit vorhandenen Entwicklungszweige listet hg branches auf. Befinden Sie sich im Branch default und möchten die Änderungen aus dem Branch supershot herüberholen, rufen Sie einfach den Befehl hg merge supershot auf.

Klonkrieger

Als Alternative zum Erstellen eines Entwicklungszweigs bietet Mercurial an, das komplette Repository zu klonen:

$ hg clone ~/skripte ~/test

Anschließend liegt im Verzeichnis test eine exakte, unabhängige Kopie einschließlich des Repositorys vor. Jetzt können Sie die Skripte in test nach Lust und Laune anpassen, ohne das Originalskript zu verändern. Klonen dürfen Sie übrigens beliebig oft: So bietet es sich etwa an, einen Klon auf einen USB-Stick zu packen und unterwegs daran zu arbeiten.

Gefallen Ihnen die Änderungen im Verzeichnis test, dann können Sie sie mit wenigen Handgriffen in das Originalskript übernehmen. Dazu wechseln Sie zunächst wieder in das Verzeichnis skripte und lassen sich die Unterschiede der beiden Verzeichnisse anzeigen:

$ hg incoming --patch ~/test

TIPP

Erst wenn Sie einen Commit im Verzeichnis test ausgeführt haben, kann hg incoming --patch die Änderungen anzeigen und hg pull sie übernehmen.

Der Parameter --patch holt zusätzlich die Änderungen auf den Schirm. Um diese zu übernehmen, “ziehen” Sie die letzte Revision des Verzeichnisses test in den Ordner skripte:

$ hg pull ~/test

Dieser Befehl gleicht erst einmal nur das Repository ab. Die Dateien im Verzeichnis skripte fasst Mercurial jedoch noch nicht an. Sofern Sie diese Dateien nicht verändert, sondern nur unter test gearbeitet haben, wechseln Sie einfach mit hg update tip zum aktuellen Stand.

Haben Sie hingegen die Dateien in test und skripte verändert, führen Sie per hg merge und hg resolve die Dateien zusammen. Ein abschließendes hg commit vollendet die Arbeit.

Helfershelfer

Sollen andere Autoren mithelfen, erstellen diese sich einfach einen eigenen Klon. Damit besitzen diese ein eigenes Arbeitsverzeichnis, in dem sie Änderungen vornehmen. Die Modifikationen holen Sie dann per pull wieder in Ihr Verzeichnis.

Haben Sie zwischenzeitlich selbst Änderungen vorgenommen, drücken Sie diese übrigens bei Bedarf in einen anderen Klon hinein. Das funktioniert genauso wie ein pull:

$ hg push ~/test

Um Mitstreitern das Klonen einfach zu machen, werfen Sie mit hg serve den in Mercurial integrierten Webserver an. Jetzt besteht die Möglichkeit, mit einem Browser die IP-Adresse des Computers auf Port 8000 anzusteuern, also beispielsweise http://192.168.1.10:8000 aufzurufen. Dort sehen Sie jetzt die komplette Historie (Abbildung 11).

Abbildung 11: Der eingebaute Webserver von Mercurial erlaubt den Zugriff auf die Historie.

Abbildung 11: Der eingebaute Webserver von Mercurial erlaubt den Zugriff auf die Historie.

Über diese Adresse ziehen Sie dann auch einen Klon und holen Änderungen per Pull ab (Listing 3, erste Zeile). Alternativ greifen Sie via SSH auf entfernte Rechner zu (Listing 3, zweite Zeile).

Listing 3

$ hg clone http://192.168.1.10:8000
$ hg clone ssh://tim@example.com/hg/skripte

Bei Bedarf verschicken Sie Änderungen per Mail. Dazu exportieren Sie alle Änderungen per hg export tip > aenderung.diff. Die erstellte Datei schicken Sie nun an Ihre Mitstreiter, die diese Datei mittels hg import aenderung.diff einfach importieren.

Fazit

Neben den vorgestellten Funktionen bietet Mercurial noch zahlreiche weitere. Alle auf Ihrem System vorhandenen Möglichkeiten listet hg help auf. Mit hg help Befehl liefert das Programm weitere Informationen zum Befehl, also hg help commit etwa zu hg commit.

Möchten Sie tiefer in Mercurial einsteigen und interessieren sich insbesondere für die Arbeitsweisen im Hintergrund, dann legen wir Ihnen das kostenlose Buch “Mercurial: The Definitive Guide” von Bryan O’Sullivan ans Herz [2]. Weitere Einführungen finden sich im Mercurial-Wiki [3].

Eine Versionsverwaltung hilft übrigens nicht nur beim Programmieren, sondern auch um beliebige andere Dokumente im Blick zu behalten – das gilt insbesondere, wenn Sie im Team gemeinsam an einer Datei arbeiten. 

Infos

[1] Mercurial: http://mercurial.selenic.com

[2] Mercurial: The Definitive Guide http://hgbook.red-bean.com

[3] Tutorials im Mercurial-Wiki: http://mercurial.selenic.com/wiki/Tutorial

DIESEN ARTIKEL ALS PDF KAUFEN
EXPRESS-KAUF ALS PDF
LinuxUser 05/2014 KAUFEN
EINZELNE AUSGABE
ABONNEMENTS
TABLET & SMARTPHONE APPS
E-Mail Benachrichtigung
Benachrichtige mich zu:

Hinweis: Dieser Artikel ist älter als ein Jahr, enthaltene Informationen sind möglicherweise veraltet.

0 Kommentare
Älteste
Neuste Beste Bewertung
Inline Feedbacks
Alle Kommentare anzeigen
Nach oben