Mercurial Distributed SCM - Die verteilte Alternative zu CVS

Thomas Arendsen Hein


Table of Contents

Abstract
Einleitung
Begriffe
Verteilte SCMs
Mercurials Design
Revlogs
Schreiben einer Revision
Lesen einer Revision
Erste Schritte mit Mercurial
Importieren eines Projektes
Entwicklung mit einem öffentlichen Repository
Informationen im Repository finden
Webinterface
Erweiterungen für Mercurial
Links
Copyright

Abstract

Mercurial Distributed SCM (http://selenic.com/mercurial/) ist ein verteiltes Source Code Managementsystem, welches durch seine Schnelligkeit und Effizienz für die Verwaltung von großen Projekten wie Xen geeignet ist. Die einfache Installation und leichte Bedienung macht es jedoch auch für kleine Projekte interessant, an denen nur eine oder wenige Personen beteiligt sind.

Der Vortrag vermittelt Grundlagen zum verteilten Source Code Management und beantwortet die Frage, warum es immer sinnvoll ist, ein verteiltes System zu verwenden.

Nach einem kleinen Überblick über verwandte Systeme wird die Benutzung von Mercurial für die Verwaltung eigener Projekte beschrieben. Einen besonderen Stellenwert hat hier der Umstieg von CVS, der durch die CVS-ähnlichen Befehle von Mercurial erleichtert wird.

Desweiteren wird der Einsatz von Mercurial für verschiedene Entwicklungsmodelle erläutert und auch ein kurzer Einblick in die interne Funktionsweise gegeben.

Mercurial Distributed SCM ist Freie Software unter der GNU GPL. Die Entwicklung findet größtenteils in Python statt, und Mercurial läuft nicht nur auf UNIX-Systemen, sondern auch unter Windows und MacOS X.

Einleitung

Der aktuelle DocBook/XML-Quellcode dieses Dokumentes ist im Mercurial-Repository http://hg.intevation.org/thomas/mercurial-lt2006 zu finden. Die nach HTML konvertierte Version liegt unter http://intevation.de/~thomas/mercurial-lt2006/.

Begriffe

  • Die Revisionsverwaltung und ihre Synonyme Revisionskontrolle (Revision Control) und Versionsverwaltung (Version Control) beschreibt die Protokollierung von Änderungen an Dokumenten. Dies kann ein einfacher Änderungsindex im Dokument, oder ein durch Hilfsprogramme unterstützter Vorgang sein.

    Solche Hilfsprogramme werden Revisionskontrollsystem (Revision Control System; RCS) oder Versionskontrollsystem (Version Control System; VCS) genannt.

  • Das Software Configuration Management (SCM) umfasst neben der Revisionsverwaltung auch die Verwaltung des Build-Prozesses.

    Hierfür gibt es integrierte Lösungen, aber gerade im Bereich Freier Software wird oft eine Kombination aus einem Programm zur Revisionsverwaltung (z.B. CVS) und anderen Build-Tools (autotools, make, distutils usw.) verwendet.

  • Mit Source Code Managementsystem (SCM) bezeichnet man im Wesentlichen ein Programm zur Revisionsverwaltung, aber hier gibt es bestimmte Mindestanforderungen, u.a. die Verwaltung von mehreren Dokumenten in einem gemeinsamen Kontext und die Zusammenführung von gleichzeitigen Änderungen an einer Datei.

    Der Übergang ist hier fließend: Das bekannte Revision Control System (RCS) von Prof. Walter F. Tichy ist wohl gerade noch kein SCM, während das Concurrent Versions System (CVS) schon eines ist.

Die Doppelbelegung der Abkürzungen RCS und SCM führt gelegentlich zu Verwirrungen, welches nun der richtige Begriff sei und wie man ihn verwenden müsse. Ich verzichte daher auf die weitere Verwendung der Abkürzung RCS und werde mit SCM immer nur Source Code Managementsysteme bezeichnen.

Verteilte SCMs

In meiner Übersicht zu verteilten SCM-Systemen beschränke ich mich auf aktuelle Freie Software, die platformübergreifend zur Verfügung steht. Dadurch fallen zwar einige weit verbreitete Kandidaten (z.B. git/cogito, BitKeeper und Perforce) durch das Raster, aber ich halte diese Punkte heutzutage für essenziell.

  • monotone (mtn) wurde 2003 zuerst veröffentlicht und ist in C++ geschrieben. Ein sehr solides System, allerdings ist die Benutzerführung noch nicht gut gelöst, was aber verbessert werden soll. Ein Nachteil ist für mich, dass mal nicht so einfach Repositories zum Experimentieren ableiten kann, da pro Benutzer üblicherweise eine SQLite-Datenbank angelegt wird, aus der sich solche Experimente nur schwierig löschen lassen.

  • darcs wurde Ende 2002 veröffentlicht und ist in Haskell geschrieben. Theoretisch ein gutes System, welches Abhängigkeiten zwischen Patches erkennen und darauf reagieren kann. Leider kostet dies in der Praxis sehr viel Performance, manchmal sogar so viel, dass ein Merge nicht abgeschlossen werden kann.

  • bazaar-ng (bzr) wurde Anfang 2005 veröffentlicht, hat jedoch als Nachfolger von Bazaar (baz) eine längere Geschichte, und ist in Python geschrieben. Es kann eigentlich alles, was man von einem SCM erwarten sollte, ist jedoch für größere Projekte noch zu langsam.

  • codeville (cdv) wurde 2004 veröffentlicht und ist in Python geschrieben. Die Entwicklung verläuft nur langsam, so dass Codeville derzeit eher als Testplatform für (sehr gute) Merge-Algorithmen angesehen wird.

  • SVK ist ein Aufsatz für SVN, der es auch ohne Verbindung zum zentralen Server erlaubt, Änderungen einzuchecken und später zu übertragen. Eigentlich ist dies noch kein verteiltes SCM, aber aufgrund der weiten Verbreitung von SVN sicherlich erwähnenswert.

  • Mercurial (hg) wurde im April 2005 veröffentlicht und ist in Python geschrieben, unterstützt durch zwei C-Module. Hg ist das chemische Symbol für Quecksilber (English: mercury; Griechisch: hydrargyrum) und wird sowohl als Synonym für Mercurial, als auch als einfach einzugebender Befehlsname verwendet.

Mercurials Design

Revlogs

Mercurial hat ein einziges Datenformat zur Speicherung von Dateirevisionen, wobei das Manifest und das Changelog (s.u.) ebenfalls in diesem Format gespeichert werden: Das Revlog.

Jede Revision wird entweder vollständig komprimiert oder nur als Delta gegenüber der vorigen Revision im gleichen Revlog gespeichert. Eine vollständige Datei wird immer dann gespeichert, wenn zum wiederherstellen der Datei zu viele Delta-Daten gelesen werden müssen. Auf diese Weise kann eine bestimmte Dateirevision schnell wieder gelesen werden, ohne dabei unnötig Plattenplatz zu verschwenden.

Damit nur die benötigten Teile des Revlog gelesen werden müssen, gibt es zusätzlich eine Index-Datei mit Einträgen mit fester Größe für jede Revision. Eine Node-ID ist dabei ein Hashwert über den Dateiinhalt und die Eltern-Node-IDs, wodurch eine Revision sicher identifiziert werden kann.

  • Node-ID der Dateirevision

  • Node-IDs der Elternrevisionen

  • Länge des Datenblocks

  • Dateioffset für den Anfang des Datenblocks

  • Revisionsnummer der letzten vollen Version

  • Revisionsnummer des zugehörigen Changesets

Das Manifest ist im wesentlichen eine Datei, deren Inhalt die Node-IDs und Dateinamen der in einer Revision gespeicherten Dateien auflistet. Hier können auch Meta-Informationen gespeichert werden, derzeit ist dies aber nur das Executable-Bit.

Im Changelog werden neben dem Autor und der von diesem angegebenen Beschreibung der Änderungen auch das Commit-Datum, die Liste der geänderten Dateien und die Node-ID des Manifests gespeichert.

Schreiben einer Revision

Da beim Schreiben eines Revlogs nur am Ende Daten angehängt werden, gibt es einen einfachen Mechanismus, um bei abgebrochenen Transaktionen den letzten Zustand wieder herzustellen: Mercurial merkt sich die Länge jeder Revlog-Datei und schneidet beim einem Programmabbruch die Dateien einfach an dieser Stelle ab.

Geschrieben werden zuerst die Revlogs der Dateien, danach die Index-Dateien, gefolgt von Revlog und Index des Manifests und abschließend die des Changelogs.

Lesen einer Revision

Dadurch das Revlog-Format muss zum Wiederherstellen einer Datei (bzw. Manifest oder Changelog) nur einmal sequentiell durch die Indexdatei und danach die benötigten Datenblöcke gelesen werden. Durch die Kompression müssen weniger Daten gelesen und mehr Daten können im Cache gehalten werden, so dass mit etwas CPU-Einsatz der Flaschenhals Festplatte (oder gar Netzwerk) ausgeglichen wird.

Beim Lesen einer Projektrevision wird zuerst der Index des Changelog gelesen, danach das Revlog. Erst jetzt werden die Index-Dateien und Revlogs des Manifests und der Projektdateien gelesen. Auf diese Weise benötigt ein Lesezugriff kein Locking, was das gleichzeitige Lesen durch mehrere Personen (z.B. bei öffentlichen Repositories) stark beschleunigt: Solange der Changelog-Index nicht geschrieben wurde, weiß ein lesender Prozess nichts von den neuen Daten. Wenn er aber geschrieben wurde, sind bereits alle neuen Daten verfügbar.

Erste Schritte mit Mercurial

Importieren eines Projektes

Mercurial benötigt keinen Server. Ein einziger Befehl reicht aus, um ein normales Verzeichnis unter die Kontrolle von Mercurial zu stellen: hg init

Das Repository wird vollständig in einem einzigen Unterverzeichnis .hg verwaltet. Mit hg add kann man alle Dateien für die Verwaltung im Repository anmelden, wobei Unterverzeichnisse automatisch durchsucht werden. Optional kann noch eine Datei .hgignore angelegt werden, um bestimmte Dateinamen (z.B. Backups oder build-Verzeichnisse) zu ignorieren. Hierbei kann zwischen regulären Ausdrücken und Shell-Mustern gewählt werden.

Mit hg commit (oder kurz hg ci) kann man nun die erste Version des Projektes einchecken. Zum Eingeben einer Commit-Beschreibung wird ein Editor gestartet, alternativ kann ein Text auch mit der Option -m/--message direkt mit dem Befehl eingegeben werden. Im Gegensatz zu zentralen SCMs ist hierfür keine Verbindung zu einem Server notwendig!

Hier ein Beispiel für die obigen Schritte:

	$ cd projekt-0.1
	$ hg init     # erstellt das .hg-Verzeichnis im aktuellen Verzeichnis
	$ hg add      # alle Dateien beim Repository anmelden
	adding foo
	adding bar/baz
	...
	$ hg commit -m "Projekt Version 0.1 importiert"
      

Weitere Projektversionen können nun importiert werden, indem entweder die aktuellen Dateien in das Arbeitsverzeichnis kopiert werden (wobei natürlich Dateien gelöscht werden sollten, die in neueren Versionen nicht existieren), oder indem das .hg-Verzeichnis (und ggf. die .hgignore-Datei) in das Verzeichnis mit der neueren Version (z.B. dem ausgepackten tar-Archiv) verschoben wird.

Mit dem Befehl hg addremove werden automatisch neue Dateien angemeldet und nicht mehr existierende Dateien abgemeldet, dies kann aber auch durch die Option -A/--addremove für den commit-Befehl abgekürzt werden:

	$ cd ..
	$ tar xzf projekt-0.2.tar.gz
	$ mv projekt-0.1/.hg* projekt-0.2
	$ cd projekt-0.2
	$ hg ci -Am "Projekt Version 0.2 importiert"

	$ cd ..
	$ tar xzf projekt-0.3.tar.gz
	$ mv projekt-0.2/.hg* projekt-0.3
	$ cd projekt-0.3
	$ hg ci -Am "Projekt Version 0.3 importiert"

	$ rm -rf projekt-0.[12] && mv projekt-0.3 projekt
      

Natürlich kann man die einzelnen Projektversionen noch mit Namen (Tags) versehen, damit sie später leicher wiederzufinden sind, oder z.B. mit der gpg-Erweiterung signieren. Dies lässt sich aber auch später noch nachholen.

Falls das Projekt bereits mit einem anderen SCM verwaltet wird, lohnt es sich eventuell, diese Daten zu konvertieren, um alte commit-Beschreibungen und Autor-Informationen zu erhalten. Die Wiki-Seite ConvertingRepositories beschäftigt sich mit den verschiedenen Konvertierungstools.

Entwicklung mit einem öffentlichen Repository

Oftmals möchte man sich an einem existierenden Projekt beteiligen. Wenn dieses ein öffentlich zugängliches Mercurial-Repository hat, kann man dieses auf den eigenen Rechner übertragen (klonen). Mit dem geklonten Repository kann man jetzt, im Gegensatz zur Arbeit CVS-Repositories oder anderen nicht verteilten Systemen, vollständig offline Arbeiten.

	$ hg clone http://hg.intevation.org/mercurial     # Projekt klonen
	requesting all changes
	adding changesets
	adding manifests
	adding file changes
	added 2023 changesets with 4098 changes to 315 files
	$ cd mercurial
	$ hg log -l2  # die letzten zwei Änderungen anzeigen
	changeset:   2022:a59da8cc35e4
	user:        Thomas Arendsen Hein <thomas@intevation.de>
	date:        Wed Mar 29 22:58:34 2006 +0200
	summary:     New option -i/--ignored for 'hg status' to show ignored files.

	changeset:   2021:fc22ed56afe3
	user:        Thomas Arendsen Hein <thomas@intevation.de>
	date:        Wed Mar 29 22:35:21 2006 +0200
	summary:     Fix hg push and hg push -r sometimes creating new heads without --force.
      

Obwohl dies nicht unbedingt erforderlich ist, hat es sich als praktisch erwiesen, wenn man das geklonte Projektrepository nicht für eigene Änderungen verwendet, sondern diese in einem Arbeitsklon macht. Wenn das Dateisystem dies unterstützt, werden hierfür Hardlinks verwendet, so dass nur der Platz für das Arbeitsverzeichnis (die ausgecheckten Dateien) doppelt belegt wird.

Eigene Änderungen

Im folgenden Beispiel soll eine Datei geändert, eine gelöscht und eine neu hinzugefügt werden:

	  $ cd ..
	  $ hg clone mercurial mercurial-work
	  $ cd mercurial-work
	  $ hg id
	  a59da8cc35e4 tip
	  $ vim README                # Änderungen vornehmen
	  $ hg remove notes.txt
	  $ echo foo > foo
	  $ hg add foo
	  $ hg status                 # geänderte Dateien auflisten
	  M README
	  A foo
	  R notes.txt
	  $ hg id
	  a59da8cc35e4+ tip
	  $ hg diff                   # Änderungen als diff anzeigen
	  diff -r a59da8cc35e4 README
	  --- a/README    Wed Mar 29 22:58:34 2006 +0200
	  +++ b/README    Tue Apr 04 22:44:08 2006 +0200
	  @@ -1,4 +1,5 @@ MERCURIAL QUICK-START
	  MERCURIAL QUICK-START
	  +test

	  Setting up Mercurial:

	  diff -r a59da8cc35e4 foo
	  --- /dev/null   Thu Jan 01 00:00:00 1970 +0000
	  +++ b/foo       Tue Apr 04 22:44:08 2006 +0200
	  @@ -0,0 +1,1 @@
	  +foo
	  diff -r a59da8cc35e4 notes.txt
	  --- a/notes.txt Wed Mar 29 22:58:34 2006 +0200
	  +++ /dev/null   Thu Jan 01 00:00:00 1970 +0000
	  @@ -1,146 +0,0 @@
	  -Some notes about Mercurial's design
	  -
	  -Revlogs:
	  ...
	  $ hg commit                 # Änderungen einchecken
	  $ hg id
	  c192c1676b65 tip
	

Einen Überblick über die eigenen Änderungen gegenüber einem anderen Repository liefert der Befehl hg outgoing (kurz hg out). Es werden alle Changesets aufgelistet, welche im diesem Repository vorhanden sind, aber nicht in einem anderen:

	  $ hg outgoing ../mercurial
	  searching for changes
	  changeset:   2023:c192c1676b65
	  user:        Thomas Arendsen Hein <thomas@intevation.de>
	  date:        Tue Apr 04 22:44:08 2006 +0200
	  summary:     My first change
	

Um diese Änderungen an andere Entwickler weiterzugeben, kann mit hg export ein Patch als Textdatei generiert werden, der z.B. per Mail verschickt un in einem anderen Repository importiert werden kann:

	  $ hg export 2023 > ../my-first-change.patch
	  $ head ../my-first-change.patch
	  # HG changeset patch
	  # User Thomas Arendsen Hein <thomas@intevation.de>
	  # Node ID c192c1676b65b9adfef627e3c5ae6a9e62ce5bf2
	  # Parent  a59da8cc35e416de70a456c8ebfc35e1ccb4ecbb
	  My first change

	  diff -r a59da8cc35e4 -r c192c1676b65 README
	  --- a/README    Wed Mar 29 22:58:34 2006 +0200
	  +++ b/README    Tue Apr 04 22:44:08 2006 +0200
	  @@ -1,4 +1,5 @@ MERCURIAL QUICK-START
	

Alternativ kann man auch ...

  • mit hg bundle einen Patch als Binärdatei generieren, bei der auch nicht darstellbaren Zeichen oder Meta-Informationen (z.B. executable-Flagge) erhalten bleiben.

  • das eigene Repository per http veröffentlichen, am besten über ein CGI-Skript oder über den eingebauten Webserver, den man mit hg serve startet. Notfalls kann man aber auch das .hg-Verzeichnis auf einem normalen Webserver legen und dem Empfänger sagen, dass er das old-http://-Protokoll verwenden muss.

  • oder mit hg push (z.B. über ssh) das Repository an einen Ort schieben, auf den der Empfänger Zugriff hat.

Änderungen im öffentlichen Repository verfolgen

Wenn im öffentlichen Repository neue Changesets verfügbar sind, können die dortigen Änderungen zu den eigenen hinzugemischt (gemergt) werden. Wenn man noch einen unveränderten Klon dieses Repositorys hat, wird man üblicherweise die Ändergungen zuerst dorthin ziehen und dann weiter verteilen. Um einen Befehl in einem anderen Repository auszuführen, ohne dafür das aktuelle Arbeitsverzeichnis zu wechseln, kann die globale Option -R/--repository verwendet werden. Der Befehl zum Ziehen von Änderungen heisst hg pull und benutzt die beim ersten clone-Befehl verwendete Adresse, sofern nichts anderes angegeben wird.

Durch den pull-Befehl wird nur das Repository (.hg-Verzeichnis) beeinflusst. Das Arbeitsverzeichnis wird nicht aktualisiert, hierzu dient der Befehl hg update (oder kurz hg up).

	  $ hg -R ../mercurial pull
	  pulling from http://hg.intevation.org/mercurial
	  searching for changes
	  adding changesets
	  adding manifests
	  adding file changes
	  added 6 changesets with 6 changes to 4 files
	  (run 'hg update' to get a working copy)
	  $ hg -R ../mercurial update
	

Die sechs neuen Changesets befinden sich nun in dem ursprünglichen Klon, aber noch nicht in der Arbeitskopie. Bevor man die Changesets hierhin übernimmt, kann man sich diese zuerst mit dem Befehl hg incoming (kurz hg in) anschauen. Mit der Option -v/--verbose wird nicht nur erste Zeile der commit-Beschreibung angezeigt, sondern alle Zeilen, zusätzlich kann man mit der Option -p/--patch auch das diff der Änderungen anzeigen:

	  $ hg incoming -vp
	  changeset:   2028:1f1fc418a96c
	  tag:         tip
	  user:        Matt Mackall <mpm@selenic.com>
	  date:        Fri Mar 31 03:25:35 2006 -0600
	  files:       mercurial/sshrepo.py
	  description:
	  ssh: skip noise generated by remote shell

	  we send a dummy command with known output to get in sync

	  diff -r 94d3170399e1 -r 1f1fc418a96c mercurial/sshrepo.py
	  --- a/mercurial/sshrepo.py      Thu Mar 30 19:28:41 2006 -0800
	  +++ b/mercurial/sshrepo.py      Fri Mar 31 03:25:35 2006 -0600
	  @@ -35,6 +35,16 @@ class sshrepository(remoterepository):

		  ui.note('running %s\n' % cmd)
		  self.pipeo, self.pipei, self.pipee = os.popen3(cmd, 'b')
	  +
	  +        # skip any noise generated by remote shell
	  +        r = self.do_cmd("between", pairs=("%s-%s" % ("0"*40, "0"*40)))
	  ...
	

Nach einem Review der Änderungen können diese nun in die Arbeitskopie gezogen werden. Da in der Arbeitskopie aber schon eigene Änderungen eingecheckt wurden, erhält man hierbei zwei sogenannte Heads (Köpfe), unter denen die beiden Entwicklungszweige (der eigene und der per pull gezogene) als Hals liegen, während die meisten Änderungen sich im gemeinsamen Körper befinden. Der neueste Kopf ist auch immer über den symbolischen Namen tip (sozusagen Nasenspitze) ansprechbar.

	  $ hg pull
	  pulling from /path/to/mercurial
	  searching for changes
	  adding changesets
	  adding manifests
	  adding file changes
	  added 6 changesets with 6 changes to 4 files (+1 heads)
	  (run 'hg heads' to see heads, 'hg merge' to merge)
	  $ hg heads
	  (zeigt zwei Branches: Die per 'pull' geholten und die eigenen)
	  changeset:   2029:1f1fc418a96c
	  tag:         tip
	  user:        Matt Mackall <mpm@selenic.com>
	  date:        Fri Mar 31 03:25:35 2006 -0600
	  summary:     ssh: skip noise generated by remote shell

	  changeset:   2023:c192c1676b65
	  user:        Thomas Arendsen Hein <thomas@intevation.de>
	  date:        Tue Apr 04 22:44:08 2006 +0200
	  summary:     My first change
	

Um diese beiden Entwicklungszweige wieder zu verbinden, sollte der Befehl hg merge benutzt werden. Hiermit wird das aktuell im Arbeitsverzeichnis ausgecheckte Changeset (der zweite Kopf) mit dem Tip-Changeset vereinigt. Das aktuell ausgecheckte Changeset kann mit dem Befehl hg identify (kurz hg id) angezeigt werden, wobei ein angehängtes Plus-Zeichen bedeutet, dass es lokale Änderungen gibt, die noch nicht eingecheckt sind. Nach einem Merge tauchen hier die Changeset-Hashes der beiden Köpfe auf, gefolgt von einem Plus-Zeichen, da ein Merge wie jede andere Änderung bestätigt werden muss:

	  $ hg id
	  c192c1676b65
	  $ hg merge
	  (Änderungen an der gleichen Datei werden ggf. zusammengeführt)
	  $ hg id
	  c192c1676b65+1f1fc418a96c+ tip
	  $ hg commit -m "merge with upstream"
	  $ hg id
	  69094159be17 tip
	  $ hg heads
	  changeset:   2030:69094159be17
	  tag:         tip
	  parent:      2023:c192c1676b65
	  parent:      2029:1f1fc418a96c
	  user:        Thomas Arendsen Hein <thomas@intevation.de>
	  date:        Tue Apr 04 22:44:28 2006 +0200
	  summary:     merge with upstream
	

Mit dem letzten hg heads sieht man das Merge-Changeset, bei dem die beiden zusammengeführten Köpfe als Parents erscheinen.

Graphische Visualisierung des entstandenen Repositories

Um die jetzt entstande Struktur graphisch zu visualisieren, gibt es verschiedene Möglichkeiten. Eine davon ist die hgk-Erweiterung, mit der man über den Befehl hg view ein Tcl/Tk-Interface starten kann:

hgk ist eine Portierung von Paul Mackerras' gitk, welches inzwischen in git integriert wurde. Weitere Möglichkeiten der graphischen Visualisierung sind u.a.:

  • Export des Versionsbaumes für das gesamte Repository oder für eine einzelne Datei als .dot-Datei, die dann mit Graphviz angezeigt werden kann.

  • Eine hgk-ähnliche Funktion im Webinterface von Mercurial, welche die graphische Darstellung über eine JavaScript-Bibliothek abwickelt. Diese Funktion wurde erst Anfang April entwickelt und ist daher noch nicht in einer Release-Version von Mercurial verfügbar.

Alternative Entwicklungsmodelle

Die eben beschriebene Entwicklung orientiert sich noch sehr an den von CVS gewohnten Strukturen. Für größere Projekte mit vielen unabhängigen Entwicklern kann man z.B. auf ein verteilteres Konzept umschwenken, bei dem hierarchisch Änderungen in Teilen des Gesamtprojekts von verschiedensten Entwicklern in ihren eigenen Repositories gehalten werden und andere die gewünschten Änderungen aus diesen Repositories in ihren Repositories zusammenführen. Ein solches Konzept wird z.B. bei der Entwicklung des Linux-Kernels verfolgt.

Informationen im Repository finden

Bei der Suche nach einer bestimmten Änderung ergibt sich das Problem, dass man sicherlich nicht immer den jeweiligen Changeset-Hash (die Node-ID des Changelogs) oder die Revisionsnummer kennt. Um Änderungen im Projekt zu finden, bietet Mercurial folgende Möglichkeiten an:

  • Mit hg log -k/--keyword Suchtext kann man sich die Changesets anzeigen lassen, in denen der Suchtext im Autor, in der Beschreibung oder in den geänderten Dateien vorkommt.

  • Mit hg log Pfad_oder_Datei kann man die angezeigen Changesets auf diejenigen beschränken, in denen Änderungen in den angegebenen Dateien oder Verzeichnis erfolgt sind.

  • Mit hg log --style=changelog kann man eine ChangeLog-Datei im GNU-Stil erzeugen, die z.B. auf einer Webseite veröffentlicht werden kann, um Anwender über die Änderungen zwischen zwei Release-Versionen zu informieren.

  • Mit hg log -r/--rev A:B kann die Anzeige auf einen Bereich von Revisionen eingeschränkt werden, hierbei sind auch Tags möglich, so dass man z.B. nach Änderungen zwischen den Release-Versionen 1.2 und 1.4 suchen kann.

Die Optionen von hg log lassen sich natürlich nahezu beliebig kombinieren.

Desweiteren gibt es noch den Befehl hg annotate, welcher eine oder mehrere Dateien ausgibt und dabei für jede Zeile markieren kann, von wem sie wann in welcher Revision geändert wurde.

Es gibt auch noch den Befehl hg grep zum Durchsuchen der Inhalte der Dateien, der nicht nur den aktuell ausgecheckten Stand durchsucht, sondern auch Versionen aus der Vergangenheit.

Webinterface

Über ein CGI-Skript können auf einem Webserver ähnlich wie z.B. auch mit ViewCVS mehrere Repositories angeboten werden:

Das Webinterface eines einzelnen Repositories kann nicht nur über das obige CGI-Skript angeboten werden, sondern auch über den bereits beschriebenen Befehl hg serve, der den eingebauten Webserver startet. Die Startseite eines Repositories zeigt Changesets, vergleichbar mit hg log auf der Kommandozeile:

Im Webinterface lassen sich alle Informationen anzeigen, die auch über die Kommandozeile erreichbar sind. Allerdings ist die Navigation zwischen einzelnen Changesets leichter, da man z.B. nur auf den Changeset-Hash klicken muss, um mehr Informationen zu erhalten:

Erweiterungen für Mercurial

Im bisherigen Text wurden bereits kurz die Erweiterungen für das Signieren von Revisionen mit gpg und für das Tcl/Tk-Interface genannt. Diese sogenannten Extensions werden benutzt, um nicht essentiell wichtige Funktionen zu implementieren, ohne dabei den Kern von Mercurial unnötig zu vergrößern.

Weitere verfügbare Extensions sind:

  • Mercurial Queues (mq): Ein System zur Verwaltung von Patch-Serien, modelliert nach dem Vorbild von Quilt.

  • History Sensitive Merge (histmerge): Ein intelligenterer Merge-Algorithmus basierend auf einem Prototyp des Precise Codeville Merge.

  • Bisect-Extension (hbisect): Hilft bei der Suche nach dem Auslöser für einen Fehler, indem man eine Revision angibt, bei der ein Fehler noch nicht auftrat und eine Revision, bei der der Fehler auftritt. Die Bisect-Extension führt den Entwickler über eine binäre Suche durch eine Liste von zu testenden Revisionen, bis die exakte Revision gefunden wurde, bei der der Fehler zum ersten mal sichtbar ist.

  • E-Mail-Extension (patchbomb): Erleichtert das Verschicken einer Serie von Patches per E-Mail, z.B. an eine Entwickler-Mailingliste. Dies ist auch eine Möglichkeit, mit einem nach Mercurial konvertierten Repository an der Entwicklung eines Projektes teilzunehmen, welches ein zentrales CVS-Repository verwendet, auf das man keinen Schreibzugriff hat.

  • SSH-Gateway (hg-ssh): Mercurial benötigt nur einen einfachen SSH-Zugang, um Changesets über Rechnergrenzen hinweg sicher zu übertragen. hg-ssh ist ein Wrapper um Mercurial, um sicher zu stellen, dass verschiedene Entwickler nur auf die ihnen zugeordneten Repositories Zugriff haben, wobei sie sich sogar ein einziges Account teilen können.

    Auf diese Weise lässt sich auch ähnlich wie mit zentralen CVS-Repositories arbeiten, aber jeder Entwickler erhält die zusätzliche Freiheit, nicht auf eine Verbindung zum CVS-Server angewiesen zu sein, um Änderungen einzuchecken oder ein Diff zu beliebigen Versionen anzusehen.

Extensions stellen üblicherweise neue Befehle für den Benutzer zur Verfügung. Man kann Mercurial aber auch über sogenannte Hooks erweitern, die in einer Konfigurationsdatei bestimmten Ereignissen oder Dateien zugeordnet werden. Beispiele hierfür sind das automatische Konvertieren von Zeilenenden für Textdateien unter Windows oder Benachrichtigungen an Mailinglisten, wenn in einem Repository neue Changesets eingetroffen sind.

Links

Die Entwickler und viele Benutzer sind übrigens regelmäßig auf irc.freenode.net im Channel #mercurial anzutreffen.

Copyright

This document is available under the following licenses:

  • Permission is granted to redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version.

  • Permission is granted to copy, distribute and/or modify this document under the terms of the GNU Free Documentation License, Version 1.2 or (at your option) any later version published by the Free Software Foundation; with no Invariant Sections, no Front-Cover Texts, and no Back-Cover Texts.