Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Mercurial - ein verteiltes Versionskontrollsystem

Mercurial - ein verteiltes Versionskontrollsystem

Mercurial ist ein verteiltes Versionskontrollsystem. Die Befehle und Funktionen sind einfach zu lernen.

Da es unabhängig vom einem Server arbeitet kann jeder lokal und auch ohne Internetverbindung Dokumente oder Quellcode damit verwalten. Trotzdem kann man mit Mercurial die Repositories untereinander austauschen und so auch über weite Entfernungen zusammen arbeiten.

Mercurial ist komplett in Python geschrieben und lässt sich deshalb einfach erweitern.

Viele bekannte Open Source Projekte und Firmen setzen Mercurial ein. So zum Beispiel Atlassian, Dovecot, Gajim, Google, Facebook, Mozilla, OpenOffice, OpenSolaris, Python, PyPy, RabbitMQ, Unity, Vim oder Xen.

Markus Zapke-Gründemann

November 01, 2012
Tweet

More Decks by Markus Zapke-Gründemann

Other Decks in Programming

Transcript

  1. Markus Zapke-Gründemann • Softwareentwickler seit 2001 • Softwareentwicklung mit Python,

    Django und Mercurial • Selbstständig seit 2008 • Seit 2011 Geschäftsführer bei Inqbus
  2. Verteilte Versionskontrollsysteme • Kein zentrales Repository nötig (aber möglich) •

    Jeder Client hat eine komplette Kopie des Repository • Fast alle Operationen können ohne ein zentrales Repository ausgeführt werden • Neue Entwicklungsmodelle möglich
  3. Mercurial • Verteiltes Versionskontrollsystem • Mercurial v0.1 im April 2005

    • Fast vollständig in Python geschrieben • Plattformunabhängig • Einfach zu erlernen • Einfach Erweiterbar durch Python Extensions • Open Source (GNU GPL 2)
  4. Mercurial installieren & einrichten $ pip install Mercurial $ vim

    ~/.hgrc $ cat ~/.hgrc [ui] username = Markus Zapke-Gründemann <[email protected]>
  5. hg

  6. Eine Datei hinzufügen $ echo "print('Hello world!')" > hello.py $

    hg status ? hello.py $ hg add adding hello.py $ hg st A hello.py
  7. Der erste Commit $ hg commit -m "Initial commit." $

    hg log changeset: 0:538ecb2ccb6a user: Markus Zapke-Gründemann <[email protected]> date: Thu Nov 01 08:23:14 2012 +0100 summary: Initial commit.
  8. Die Datei ändern $ echo "print('Hello user.')" >> hello.py $

    hg st M hello.py $ hg diff diff --git a/hello.py b/hello.py --- a/hello.py +++ b/hello.py @@ -1,1 +1,2 @@ print('Hello world!') +print('Hello user.')
  9. Der zweite Commit $ hg commit -m "Added line two."

    $ hg log changeset: 1:b847a3052569 tag: tip user: Markus Zapke-Gründemann <[email protected]> date: Thu Nov 01 08:24:05 2012 +0100 summary: Added line two. changeset: 0:538ecb2ccb6a user: Markus Zapke-Gründemann <[email protected]> date: Thu Nov 01 08:23:14 2012 +0100 summary: Initial commit.
  10. Unterschiede feststellen $ hg diff -r 0:1 diff --git a/hello.py

    b/hello.py --- a/hello.py +++ b/hello.py @@ -1,1 +1,2 @@ print('Hello world!') +print('Hello user.') $ hg diff -r 0:tip diff --git a/hello.py b/hello.py --- a/hello.py +++ b/hello.py @@ -1,1 +1,2 @@ print('Hello world!') +print('Hello user.')
  11. Zeitreisen $ hg identify b847a3052569 tip $ hg update 0

    1 files updated, 0 files merged, 0 files removed, 0 files unresolved $ cat hello.py print('Hello world!') $ hg id 538ecb2ccb6a $ hg up 1 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg id b847a3052569 tip
  12. Aufräumen $ echo "Lorem ipsum dolor sit amet." >> hello.py

    $ hg st M hello.py $ hg up -C 1 files updated, 0 files merged, 0 files removed, 0 files unresolved $ hg st
  13. Zusammenfassung $ hg init REPOSITORY # Repository erstellen $ hg

    status # Status der Dateien im Repository anzeigen
  14. Zusammenfassung $ hg init REPOSITORY # Repository erstellen $ hg

    status # Status der Dateien im Repository anzeigen $ hg st # Alias für status
  15. Zusammenfassung $ hg init REPOSITORY # Repository erstellen $ hg

    status # Status der Dateien im Repository anzeigen $ hg st # Alias für status $ hg add # Dateien zum Repository hinzufügen
  16. Zusammenfassung $ hg init REPOSITORY # Repository erstellen $ hg

    status # Status der Dateien im Repository anzeigen $ hg st # Alias für status $ hg add # Dateien zum Repository hinzufügen $ hg commit # Commit hinzugefügter und geänderter Dateien
  17. Zusammenfassung $ hg init REPOSITORY # Repository erstellen $ hg

    status # Status der Dateien im Repository anzeigen $ hg st # Alias für status $ hg add # Dateien zum Repository hinzufügen $ hg commit # Commit hinzugefügter und geänderter Dateien $ hg log # Geschichte anzeigen
  18. Zusammenfassung $ hg init REPOSITORY # Repository erstellen $ hg

    status # Status der Dateien im Repository anzeigen $ hg st # Alias für status $ hg add # Dateien zum Repository hinzufügen $ hg commit # Commit hinzugefügter und geänderter Dateien $ hg log # Geschichte anzeigen $ hg diff # Änderungen an der Arbeitskopie anzeigen
  19. Zusammenfassung $ hg init REPOSITORY # Repository erstellen $ hg

    status # Status der Dateien im Repository anzeigen $ hg st # Alias für status $ hg add # Dateien zum Repository hinzufügen $ hg commit # Commit hinzugefügter und geänderter Dateien $ hg log # Geschichte anzeigen $ hg diff # Änderungen an der Arbeitskopie anzeigen $ hg diff -r REV1:REV2 # Änderungen zwischen Revisionen anzeigen
  20. Zusammenfassung $ hg init REPOSITORY # Repository erstellen $ hg

    status # Status der Dateien im Repository anzeigen $ hg st # Alias für status $ hg add # Dateien zum Repository hinzufügen $ hg commit # Commit hinzugefügter und geänderter Dateien $ hg log # Geschichte anzeigen $ hg diff # Änderungen an der Arbeitskopie anzeigen $ hg diff -r REV1:REV2 # Änderungen zwischen Revisionen anzeigen $ hg update REV # Zu einer Revision wechseln
  21. Zusammenfassung $ hg init REPOSITORY # Repository erstellen $ hg

    status # Status der Dateien im Repository anzeigen $ hg st # Alias für status $ hg add # Dateien zum Repository hinzufügen $ hg commit # Commit hinzugefügter und geänderter Dateien $ hg log # Geschichte anzeigen $ hg diff # Änderungen an der Arbeitskopie anzeigen $ hg diff -r REV1:REV2 # Änderungen zwischen Revisionen anzeigen $ hg update REV # Zu einer Revision wechseln $ hg up REV # Alias für update
  22. Zusammenfassung $ hg init REPOSITORY # Repository erstellen $ hg

    status # Status der Dateien im Repository anzeigen $ hg st # Alias für status $ hg add # Dateien zum Repository hinzufügen $ hg commit # Commit hinzugefügter und geänderter Dateien $ hg log # Geschichte anzeigen $ hg diff # Änderungen an der Arbeitskopie anzeigen $ hg diff -r REV1:REV2 # Änderungen zwischen Revisionen anzeigen $ hg update REV # Zu einer Revision wechseln $ hg up REV # Alias für update $ hg identify # Aktuelle Revision identifizieren
  23. Zusammenfassung $ hg init REPOSITORY # Repository erstellen $ hg

    status # Status der Dateien im Repository anzeigen $ hg st # Alias für status $ hg add # Dateien zum Repository hinzufügen $ hg commit # Commit hinzugefügter und geänderter Dateien $ hg log # Geschichte anzeigen $ hg diff # Änderungen an der Arbeitskopie anzeigen $ hg diff -r REV1:REV2 # Änderungen zwischen Revisionen anzeigen $ hg update REV # Zu einer Revision wechseln $ hg up REV # Alias für update $ hg identify # Aktuelle Revision identifizieren $ hg id # Alias für identify
  24. Zusammenfassung $ hg init REPOSITORY # Repository erstellen $ hg

    status # Status der Dateien im Repository anzeigen $ hg st # Alias für status $ hg add # Dateien zum Repository hinzufügen $ hg commit # Commit hinzugefügter und geänderter Dateien $ hg log # Geschichte anzeigen $ hg diff # Änderungen an der Arbeitskopie anzeigen $ hg diff -r REV1:REV2 # Änderungen zwischen Revisionen anzeigen $ hg update REV # Zu einer Revision wechseln $ hg up REV # Alias für update $ hg identify # Aktuelle Revision identifizieren $ hg id # Alias für identify $ hg up -C # Alle Änderungen ohne Commit rückgängig machen
  25. Weitere Befehle $ hg help # Hilfe ausgeben $ hg

    help COMMAND # Hilfe zu einem Befehl anzeigen
  26. Weitere Befehle $ hg help # Hilfe ausgeben $ hg

    help COMMAND # Hilfe zu einem Befehl anzeigen $ hg copy SOURCE DEST # Eine Datei kopieren
  27. Weitere Befehle $ hg help # Hilfe ausgeben $ hg

    help COMMAND # Hilfe zu einem Befehl anzeigen $ hg copy SOURCE DEST # Eine Datei kopieren $ hg cp SOURCE DEST # Alias für copy
  28. Weitere Befehle $ hg help # Hilfe ausgeben $ hg

    help COMMAND # Hilfe zu einem Befehl anzeigen $ hg copy SOURCE DEST # Eine Datei kopieren $ hg cp SOURCE DEST # Alias für copy $ hg remove FILE # Eine Datei löschen
  29. Weitere Befehle $ hg help # Hilfe ausgeben $ hg

    help COMMAND # Hilfe zu einem Befehl anzeigen $ hg copy SOURCE DEST # Eine Datei kopieren $ hg cp SOURCE DEST # Alias für copy $ hg remove FILE # Eine Datei löschen $ hg rm FILE # Alias für remove
  30. Weitere Befehle $ hg help # Hilfe ausgeben $ hg

    help COMMAND # Hilfe zu einem Befehl anzeigen $ hg copy SOURCE DEST # Eine Datei kopieren $ hg cp SOURCE DEST # Alias für copy $ hg remove FILE # Eine Datei löschen $ hg rm FILE # Alias für remove $ hg mv SOURCE DEST # Eine Datei verschieben
  31. Weitere Befehle $ hg help # Hilfe ausgeben $ hg

    help COMMAND # Hilfe zu einem Befehl anzeigen $ hg copy SOURCE DEST # Eine Datei kopieren $ hg cp SOURCE DEST # Alias für copy $ hg remove FILE # Eine Datei löschen $ hg rm FILE # Alias für remove $ hg mv SOURCE DEST # Eine Datei verschieben $ hg revert FILE # Eine Revision wieder herstellen
  32. Weitere Befehle $ hg help # Hilfe ausgeben $ hg

    help COMMAND # Hilfe zu einem Befehl anzeigen $ hg copy SOURCE DEST # Eine Datei kopieren $ hg cp SOURCE DEST # Alias für copy $ hg remove FILE # Eine Datei löschen $ hg rm FILE # Alias für remove $ hg mv SOURCE DEST # Eine Datei verschieben $ hg revert FILE # Eine Revision wieder herstellen $ hg annotate FILE # Informationen zu jeder Zeile
  33. hg heads $ hg up 0 1 files updated, 0

    files merged, 0 files removed, 0 files unresolved $ echo "# A comment." >> hello.py $ hg commit -m "Added a comment." created new head
  34. $ hg heads changeset: 2:7e974277052b tag: tip parent: 0:538ecb2ccb6a user:

    Markus Zapke-Gründemann <[email protected]> date: Thu Nov 01 08:41:52 2012 +0100 summary: Added a comment. changeset: 1:b847a3052569 user: Markus Zapke-Gründemann <[email protected]> date: Thu Nov 01 08:24:05 2012 +0100 summary: Added line two. hg heads 0 1 2 4 3 5
  35. hg merge $ hg merge merging hello.py 0 files updated,

    1 files merged, 0 files removed, 0 files unresolved (branch merge, don't forget to commit) $ hg diff diff --git a/hello.py b/hello.py --- a/hello.py +++ b/hello.py @@ -1,2 +1,2 @@ print('Hello world!') -# A comment. +print('Hello user.') $ hg commit -m "Merged."
  36. Entfernte Repositories $ hg clone http://[email protected]/repo # Alice schreibt neuen

    Code. $ hg in ... $ hg pull ... $ hg up # hack hack hack $ hg out $ hg push
  37. $ hg help Mercurial Distributed SCM list of commands: add

    add the specified files on the next commit addremove add all new files, delete all missing files annotate show changeset information by line for each file archive create an unversioned archive of a repository revision backout reverse effect of earlier changeset bisect subdivision search of changesets bookmarks track a line of development with movable markers branch set or show the current branch name branches list repository named branches bundle create a changegroup file
  38. $ hg help --debug Mercurial Distributed SCM list of commands:

    add add the specified files on the next commit addremove add all new files, delete all missing files annotate, blame show changeset information by line for each file ... commit, ci commit the specified files or all outstanding changes copy, cp mark files as copied for the next commit debugancestor find the ancestor revision of two revisions in a given index debugbuilddag builds a repo with a given DAG from scratch in the current empty repo debugbundle lists the contents of a bundle debugcheckstate validate the correctness of the current dirstate debugcommands list all available commands and options
  39. hg grep $ hg grep "def forget\(" mercurial/subrepo.py:17895: def forget(self,

    ui, match, prefix): mercurial/subrepo.py:17895: def forget(self, ui, match, prefix): mercurial/commands.py:17892:def forget(ui, repo, *pats, **opts): mercurial/cmdutil.py:17891:def forget(ui, repo, match, prefix, explicitonly): hgext/largefiles/lfutil.py:17878: def forget(self, f): mercurial/context.py:17832: def forget(self, files, prefix=""): mercurial/dirstate.py:14273: def forget(self, f): mercurial/localrepo.py:11301: def forget(self, list): mercurial/hg.py:1072: def forget(self, files): mercurial/hg.py:1072: def forget(self, list):
  40. [alias] [alias] # diff stat dst = diff --stat #

    diff nur für geänderte Dateien dmod = !hg status $($HG root) -mn | xargs hg diff # status mit relativen Pfaden str = !hg status $($HG root) $HG_ARGS
  41. Extensions installieren [extensions] # Extension ist im PYTHONPATH color =

    # Pfad zur Extension ist manuell konfiguriert hgshelve = ~/.hgext/hgshelve/hgshelve.py
  42. mercurial_keyring $ pip install mercurial_keyring [extensions] mercurial_keyring = [auth] myremote.schemes

    = https myremote.prefix = hg.example.com/repo myremote.username = bob http://pypi.python.org/pypi/mercurial_keyring
  43. merge vs. rebase [extensions] rebase = $ hg pull --rebase

    C1 C2 L1 R1 L2 R2 C1 C2 L1 R1 L2 R2
  44. Phases immutable shared public X X draft X secret $

    hg phase -r 8184::8186 8184: public 8185: secret 8186: secret $ hg phase -v --draft 8185 phase change for 1 changesets $ hg phase -r 8184::8186 8184: public 8185: draft 8186: secret http://mercurial.selenic.com/wiki/Phases
  45. branches vs. bookmarks • branches sind in Mercurial permanent •

    bookmarks eignen sich deshalb besser für Feature branches • Ab Mercurial 2.3 gibt es verbesserte Unterstützung für bookmarks bei pull und merge
  46. bookmarks $ hg bookmark feature1 $ hg bookmarks * feature1

    1:0b89bcda3dcf $ hg up 2 $ hg bookmark feature2 $ hg bookmarks feature1 1:0b89bcda3dcf * feature2 2:f1cd0e213eec $ hg up feature1 1 files updated, 0 files merged, 1 files removed, 0 files unresolved $ hg bookmarks * feature1 1:0b89bcda3dcf feature2 2:f1cd0e213eec $ hg bookmark --delete feature2
  47. bookmarks $ hg outgoing -B comparing with http://hg.example.com/repo searching for

    changed bookmarks feature1 1:0b89bcda3dcf $ hg push -B feature1 pushing to http://hg.example.com/repo searching for changes no changes found exporting bookmark feature1 $ hg pull pulling from http://hg.example.com/repo ... divergent bookmark feature1 stored as feature1@default (run 'hg heads .' to see heads, 'hg merge' to merge) $ hg merge
  48. $ hg init mainrepo $ cd mainrepo $ hg init

    subrepo $ echo subrepo = subrepo > .hgsub $ hg add .hgsub $ hg commit -m "Subrepositories added" $ echo "main repo" > README $ echo "sub repo" > subrepo/README $ hg st ? README $ hg st -S ? README ? subrepo/README $ hg add adding README $ hg add -S adding subrepo/README subrepo erstellen
  49. $ hg diff diff --git a/README b/README new file mode

    100644 --- /dev/null +++ b/README @@ -0,0 +1,1 @@ +main repo $ hg diff -S diff --git a/README b/README new file mode 100644 --- /dev/null +++ b/README @@ -0,0 +1,1 @@ +main repo diff --git a/subrepo/README b/subrepo/README new file mode 100644 --- /dev/null +++ b/subrepo/README @@ -0,0 +1,1 @@ +sub repo diff mit subrepos
  50. $ hg commit abort: uncommitted changes in subrepo subrepo (use

    --subrepos for recursive commit) $ hg commit -S -m "Added README" committing subrepository subrepo $ cat .hgsubstate 8496febd9224bdb2a2e5c9dbff051b166f5cfece subrepo $ hg id -R subrepo --debug 8496febd9224bdb2a2e5c9dbff051b166f5cfece tip commit mit subrepos
  51. $ cd .. $ hg clone mainrepo mainrepo-clone updating to

    branch default cloning subrepo subrepo from /tmp/mainrepo/subrepo 3 files updated, 0 files merged, 0 files removed, 0 files unresolved $ tree -a -L 2 mainrepo-clone mainrepo-clone !"" .hg # !"" 00changelog.i # !"" branch # !"" cache # !"" dirstate # !"" hgrc # !"" requires # $"" store !"" .hgsub !"" .hgsubstate !"" README $"" subrepo !"" .hg $"" README clone mit subrepos
  52. totalnodes.py """totalnodes Prints total number of nodes in a repo.

    """ def totalnodes(ui, repo, **opts): """Prints total number of nodes in a repo.""" if opts['prefix']: ui.write(opts['prefix']) ui.write('%d\n' % len(repo)) cmdtable = { 'totalnodes': (totalnodes, [('p', 'prefix', '', 'prefix option')], '[options]') } buglink = 'http://bugs.example.com/' testedwith = '2.2 2.3'