Sektionen
Benutzerspezifische Werkzeuge
Sie sind hier: Startseite Support Dokumentation docs Mercurial VCS: Einführung

Mercurial VCS: Einführung

Die wichtigsten Grundlagen für die Verwendung von Mercurial als dezentrales VCS.

Bitte zu erst dies hier lesen:

Grundlagen

Die wichtigsten Komandos

  • hg help - zeigt die Hilfe an
  • hg init - macht aus dem aktuellen Verzeichnis ein Mercurial Repository
  • hg clone - erzeugt eine Kopie eines Repositories
  • hg add - fügt eine oder mehrere Dateien/Ordner zum Repository hinzu
  • hg commit (ci) - erzeugt einen neuen ChangeSet
  • hg status (st) - zeigt Statusinformationen z.B. Dateiänderungen an
  • hg push - überträgt Änderungen in ein anderes Repository
  • hg pull - holt Änderungen aus einem anderen ins aktuelle Repository
  • hg update (up) - aktualisiert das Arbeitsverzeichnis mit dem Repository
  • hg merge - führt Änderungen mehrerer Personen an gleichen Dateien zusammen
  • hg revert - verwirft lokale Änderungen im Arbeitsverzeichnis (ersetzt Sie durch die Version im Repository)

Anwendung

Wir legen uns ein Verzeichnis an und machen daraus mit hg init ein Mercurial Repository.

$ mkdir repo1
$ cd repo1
/repo1 $ hg init

Im aktuellen Verzeichnis existiert nun ein versteckter Ordner .hg.

/repo1 $ ls -a
.  ..  .hg

Wir legen nun eine Textdatei an und fügen sie mit hg add zum Repository hinzu.

/repo1 $ touch test.txt
/repo1 $ hg add test.txt

Ein hg add ohne Parameter, würde rekursiv alle Dateien und Ordner dem Repository hinzufügen.

Wir ändern die Datei mit einem Texteditor wie folgt ab.

/repo1 $ cat test.txt 
Ein kleiner text.

Ein hg status oder hg st zeigt uns nun an, dass sich die Datei test.txt geändert hat.

/repo1 $ hg st
M test.txt

Diese Änderungen commiten wir wie folgt, mit hg commit und erzeugen damit ein neues ChangeSet.

/repo1 $ hg commit -m "eine erste Zeile eingefügt"

Alternativ zu hg commit kann man auch den ShortCut hg ci verwenden. Der Parameter -m ist optional und erlaubt es gleich einen Änderungsnotiz ChangeNote anzugeben. Wird der Parameter weg gelassen, öffnet sich ein Texteditor und man kann seine Änderungsnotiz dort eingeben.

Mit hg log können wir uns das Revisionslog anschauen.

/repo1 $ hg log
Änderung:        1:f5cc6800103e
Marke:           tip
Nutzer:          maik <maik.derstappen@inqbus.de>
Datum:           Sun May 15 20:41:32 2011 +0200
Zusammenfassung: eine erste Zeile eingefügt

Wir ändern die Datei nun wie folgt ab.

/repo1 $ cat test.txt 
Ein kleiner text.

Noch ein kleiner Text.

Mit hg status sehen wir, dass die Datei sich geändert hat.

/repo1 $ hg st
M test.txt

Was sich genau geändert hat, sehen wir mit hg diff.

/repo1 $ hg diff
diff -r f5cc6800103e test.txt
--- a/test.txt  Sun May 15 20:41:32 2011 +0200
+++ b/test.txt  Sun May 15 20:51:47 2011 +0200
@@ -1,1 +1,3 @@
Ein kleiner text.
+
+Noch ein kleiner Text.

Wir sehen, es wurden 2 Zeilen hinzugefügt. Wir löschen nun die erste Zeile mit dem Texteditor und schauen uns erneut mit hg diff die Änderungen an.

/repo1 $ hg diff
diff -r f5cc6800103e test.txt
--- a/test.txt  Sun May 15 20:41:32 2011 +0200
+++ b/test.txt  Sun May 15 20:54:38 2011 +0200
@@ -1,1 +1,2 @@
-Ein kleiner text.
+
+Noch ein kleiner Text.

Wir sehen an dem Minuszeichen, dass die erste Zeile entfernt wurde.

Nun erzeugen wir ein neues ChangeSet mit hg commit.

$ hg commit -m "Text eingefügt und erste Zeile gelöscht"

Im Revisionslog schauen wir uns, mit hg log erneut die Liste der Änderungen an.

/repo1 $ hg log
Änderung:        2:0e14ae4736fa
Marke:           tip
Nutzer:          maik <maik.derstappen@inqbus.de>
Datum:           Sun May 15 20:57:04 2011 +0200
Zusammenfassung: Text eingefügt und erste Zeile gelöscht

Änderung:        1:f5cc6800103e
Nutzer:          maik <maik.derstappen@inqbus.de>
Datum:           Sun May 15 20:41:32 2011 +0200
Zusammenfassung: eine erste Zeile eingefügt

Wir sehen, dass die 2. Änderung die lokale Revisionsnummer 2 bekommen hat. Diese gilt aber nur jetzt hier lokal, in diesem Repository und kann sich beim zusammenführen von Änderungen mit anderen Repositories auch ändern. Global eindeutig ist nur die längere Nummer hinter dem Doppelpunkt. Beide Nummern können z.B. wie folgt zum direkten ansprechen von Revisionen verwendet werden.

/repo1 $ hg diff -r f5cc6800103e
diff -r f5cc6800103e test.txt
--- a/test.txt  Sun May 15 20:41:32 2011 +0200
+++ b/test.txt  Sun May 15 21:01:04 2011 +0200
@@ -1,1 +1,2 @@
-Ein kleiner text.
+
+Noch ein kleiner Text.

Bis hierher haben wir nur alleine und mit einem Repository gearbeitet. Nun möchte aber ein 2. Entwickler in einem 2. Repository ebenfalls Änderungen vornehmen.

Hierzu kopiert er sich mit hg clone das vorhandene Repository.

/ $ hg clone repo1 repo2
Aktualisiere auf Zweig default
1 Dateien aktualisiert, 0 Dateien zusammengeführt, 0 Dateien entfernt, 0 Dateien ungelöst

Der Entwickler hat nun in seinem Verzeichnis repo2 alle Änderungen, die jemals in dem Ursprungsrepository gemacht wurden.

/ $ cd repo2
/repo2 $ ls -a
.  ..  .hg  test.txt

Mit hg log erhalt er wie erwartet die gesamte History.

/repo2 $ hg log
Änderung:        2:0e14ae4736fa
Marke:           tip
Nutzer:          maik <maik.derstappen@inqbus.de>
Datum:           Sun May 15 20:57:04 2011 +0200
Zusammenfassung: Text eingefügt und erste Zeile gelöscht

Änderung:        1:f5cc6800103e
Nutzer:          maik <maik.derstappen@inqbus.de>
Datum:           Sun May 15 20:41:32 2011 +0200
Zusammenfassung: eine erste Zeile eingefügt

Er ändert die Datei test.txt wie folgt ab.

/repo2 $ hg diff
diff -r 0e14ae4736fa test.txt
--- a/test.txt  Sun May 15 20:57:04 2011 +0200
+++ b/test.txt  Sun May 15 21:12:14 2011 +0200
@@ -1,2 +1,1 @@
-
Noch ein kleiner Text.

Nun erzeugt er wie gewohnt ein neues Changeset mit hg commit.

/repo2 $ hg commit -m "leerzeile am Anfang der Datei gelöscht"

Ein hg log zeigt ihm hier seine Änderung.

/repo2 $ hg log
Änderung:        3:6d3627ca53f5
Marke:           tip
Nutzer:          max <max.brauer@inqbus.de>
Datum:           Sun May 15 21:13:51 2011 +0200
Zusammenfassung: leerzeile am Anfang der Datei gelöscht

Änderung:        2:0e14ae4736fa
Nutzer:          maik <maik.derstappen@inqbus.de>
Datum:           Sun May 15 20:57:04 2011 +0200
Zusammenfassung: Text eingefügt und erste Zeile gelöscht

Änderung:        1:f5cc6800103e
Nutzer:          maik <maik.derstappen@inqbus.de>
Datum:           Sun May 15 20:41:32 2011 +0200
Zusammenfassung: eine erste Zeile eingefügt

Ein hg log im ursprünglichen repo1 zeigt diese Änderung nicht.

/repo1 $ hg log
Änderung:        2:0e14ae4736fa
Marke:           tip
Nutzer:          maik <maik.derstappen@inqbus.de>
Datum:           Sun May 15 20:57:04 2011 +0200
Zusammenfassung: Text eingefügt und erste Zeile gelöscht

Änderung:        1:f5cc6800103e
Nutzer:          maik <maik.derstappen@inqbus.de>
Datum:           Sun May 15 20:41:32 2011 +0200
Zusammenfassung: eine erste Zeile eingefügt

Um die lokalen Änderungen ins Ursprungsrepository zu übertragen, verwendet der Entwickler hg push.

/repo2 $ hg push ../repo1
Übertrage nach ../repo1
Suche nach Änderungen
Füge Änderungssätze hinzu
Füge Manifeste hinzu
Füge Dateiänderungen hinzu
Fügte 1 Änderungssätze mit 1 Änderungen an 1 Dateien hinzu

Ein erneutes hg log im repo1 wird nun die Änderungen des 2. Entwicklers zeigen. Damit auch die Dateien und Ordner in dem Arbeitsverzeichnis aktualisiert werden, führen wir hier im repo1 hg update aus.

$ hg update
1 Dateien aktualisiert, 0 Dateien zusammengeführt, 0 Dateien entfernt, 0 Dateien ungelöst

Erst jetzt sind die Dateien in den Arbeitsverzeichnissen identisch.

Was geschieht, wenn beide Entwickler gleichzeitig an den Dateien arbeiten? In dem Fall können die Änderungen mit hg merge automatisch zusammengeführt werden, sofern sie nicht in den gleichen Zeilen vorhanden sind.

Nehmen wir an die Entwickler haben die Datei wie folgt geändert und commitet.

Repo1:

/repo1 $ hg diff
diff -r 6d3627ca53f5 test.txt
--- a/test.txt  Sun May 15 21:13:51 2011 +0200
+++ b/test.txt  Sun May 15 21:24:11 2011 +0200
@@ -1,1 +1,1 @@
-Noch ein kleiner Text.
+Noch ein kleiner Text!

Repo2:

/repo2 $ hg diff
diff -r 6d3627ca53f5 test.txt
--- a/test.txt  Sun May 15 21:13:51 2011 +0200
+++ b/test.txt  Sun May 15 21:23:53 2011 +0200
@@ -1,1 +1,1 @@
-Noch ein kleiner Text.
+Mein kleiner Text.

Im repo2 holt sich der Entwickler jetzt die Änderungen mit hg pull aus dem repo1.

/repo2 $ hg pull ../repo1
Hole von ../repo1
Suche nach Änderungen
Füge Änderungssätze hinzu
Füge Manifeste hinzu
Füge Dateiänderungen hinzu
Fügte 1 Änderungssätze mit 1 Änderungen an 1 Dateien hinzu (+1 Köpfe)
("hg heads" zeigt alle Köpfe, nutze "hg merge" um sie zusammenzuführen)

Da es in beiden Repositories neue ChangSets gibt, gibt es jetzt 2 heads. Mit hg heads können wir uns die beiden heads anzeigen lassen.

/repo2 $ hg heads
Änderung:        5:745ea77cdf65
Marke:           tip
Vorgänger:       3:6d3627ca53f5
Nutzer:          maik <maik.derstappen@inqbus.de>
Datum:           Sun May 15 21:27:28 2011 +0200
Zusammenfassung: Satzzeichen geändert

Änderung:        4:85b405cf1bb2
Nutzer:          maik <maik.derstappen@inqbus.de>
Datum:           Sun May 15 21:27:52 2011 +0200
Zusammenfassung: in mein kleiner text geändert

Ein hg merge führt die Änderungen soweit möglich zusammen. Falls mehrere Änderungen in der selben Zeile vorhanden sind, wird der Nutzer aufgefordert zu entscheiden wie die Zeile ausehen soll. Dabei wird, wenn vorhanden ein MerginTool gestartet. Alternativ kann man den Konflikt auch manuell mit einem Texteditor auflösen.

siehe auch: http://mercurial.selenic.com/wiki/GermanTutorialConflict

/repo2 $ hg merge
merging test.txt
3 Dateien zum Editieren
0 Dateien aktualisiert, 1 Dateien zusammengeführt, 0 Dateien entfernt, 0 Dateien ungelöst
(Zusammenführen von Zweigen, vergiss nicht 'hg commit' auszuführen)

Die Änderungen werden nun mit hg commit zu einem neuen ChangeSet gemacht.

/repo2 $ hg ci -m "merge changes"

Die zusammengeführten Änderungen, können nun mit hg push ins repo1 übertragen werden.

/repo2 $ hg push ../repo1
Übertrage nach ../repo1
Suche nach Änderungen
Füge Änderungssätze hinzu
Füge Manifeste hinzu
Füge Dateiänderungen hinzu
Fügte 2 Änderungssätze mit 2 Änderungen an 1 Dateien hinzu

Wenn wir lokale Änderungen haben, die wir zurücksetzen möchten, so können wir dies mit hg revert machen.

$ hg diff
diff -r f4edebf2fa01 test.txt
--- a/test.txt  Sun May 15 21:39:04 2011 +0200
+++ b/test.txt  Sun May 15 21:52:13 2011 +0200
@@ -1,1 +1,3 @@
Mein kleiner Text!
+
+Neuer Text.

Die Datei hat also folgenen Inhalt in unserem Arbeitsverzeichnis.

$ cat test.txt 
Mein kleiner Text!

Neuer Text.

Ein hg revert macht nun diese Änderungen rückgängig.

$ hg revert test.txt

Die Datei hat jetzt wieder den Zustand, wie in der aktuellsten Revision im Repository.

$ cat test.txt 
Mein kleiner Text!

Weiter Dokumentation zu Mercurial

  • http://mercurial.selenic.com/wiki/GermanTutorial (deutsch)
  • http://mercurial.selenic.com (englisch)

Tipps

  • Leere Ordner werden in Mercurial beim hinzufügen ignoriert. Daher sollte immer mindestens eine Datei in einem Ordner existieren.