view mercurial.tex @ 48:906351c9cbb6

Un-squeze frame.
author Martin Geisler <mg@lazybytes.net>
date Thu, 20 Aug 2009 21:10:26 +0200
parents 01fe12d8be87
children c6c69ba22a23
line wrap: on
line source

\documentclass[t,noamsthm]{beamer}

\usepackage{listings}
\lstdefinelanguage{hgshell}{
  moredelim=[l][\bfseries]{\%},
}
\lstdefinelanguage{ini}{
  moredelim=[s][\bfseries]{[}{]},
}
\lstset{
  language=hgshell,
  basicstyle=\footnotesize\ttfamily,
  columns=fixed,
  showstringspaces=false,
  frame=single,
  framerule=0.4pt,
  rulecolor=\color{white!50!black},
  %backgroundcolor=\color{white},
}

\usepackage{tikz}
\usetikzlibrary{chains,positioning,shapes,fit}
\pgfdeclarelayer{background}
\pgfdeclarelayer{foreground}
\pgfsetlayers{background,main,foreground}

\tikzstyle{branch}=[blue!60, ->, >=latex, line join=round]
\tikzstyle{tag}=[below, thick, draw=yellow!50!orange, fill=yellow!50]
\tikzstyle{timeline}=[thick, ->]
\tikzstyle{rev}=[minimum size=3mm, draw=red!50!black!50, top
  color=white, bottom color = red!50!black!20]
\tikzstyle{repository}=[cylinder,shape border rotate=90, draw=structure,
  shade, left color=structure!50, right color=structure!50,
  middle color=structure!10, aspect=0.15, minimum height=20mm,
  text width=20mm, text centered]
\tikzstyle{working copy}=[text width=15mm, inner sep=5pt,
  draw=yellow!40!red,
  top color=yellow!10!white,
  bottom color=yellow!20!white]
\tikzstyle{short}=[shorten <=3pt, shorten >=3pt]
\tikzstyle{every join}=[->]

\mode<presentation>{
  \setbeamertemplate{navigation symbols}{}
  \setbeamertemplate{footline}[frame number]
  \setbeamertemplate{background}{
    \begin{tikzpicture}<0->[overlay, remember picture]
      \node at (current page.center) {
        \includegraphics[height=0.9\textheight]{hg-droplets}
      };
      \fill[white,opacity=0.95] (current page.north west)
                      rectangle (current page.south east);
    \end{tikzpicture}
  }
}
\mode<handout>{
  \usepackage{pgfpages}
  \pgfpagesuselayout{4 on 1}[a4paper,landscape,border shrink=5mm]
}

\AtBeginSection[]{
  \begin{frame}<beamer>{Outline}
    \tableofcontents[currentsection]
  \end{frame}
}

\usepackage[english]{babel}
\usepackage[latin1]{inputenc}
\usepackage[T1]{fontenc}
\usepackage[expert]{lucidabr}

\title{Mercurial}
\author{Martin Geisler}

\newcommand{\hgcmd}[1]{\texttt{\color{green!50!black}#1}}
\newcommand{\hgext}[1]{\texttt{#1}}

\begin{document}

\begin{frame}
  \maketitle
\end{frame}

\begin{frame}{Outline}
  \tableofcontents
\end{frame}

\section{Introduction}

\subsection{Basic Concepts}

\begin{frame}{What do we want from a version control system?}
  Very basic features:
  \begin{itemize}
  \item let you save changes
  \item browser the history
  \end{itemize}

  \pause
  Basic features:
  \begin{itemize}
  \item collaboration
  \item branches
  \item tags
  \end{itemize}

  \pause
  Nice features:
  \begin{itemize}
  \item speed!
  \item much more, as you will see\dots
  \end{itemize}
\end{frame}

\subsection{Historic Context}

\begin{frame}{Revision Control System (RCS)}
  Version control from the 1980s:
  \begin{itemize}
  \item store changes (date, commit message)
  \item browse history
  \end{itemize}

  \bigskip

  \begin{tikzpicture}
    \begin{scope}[start chain]
      \node<2->[on chain,left] at (0, 0.5) {hello.c};
      \node<3->[on chain,xshift=-8mm, rev] {};
      \node<4->[on chain,join,rev] {};
      \node<5->[on chain,join,rev] {};
    \end{scope}
    \begin{scope}[start chain]
      \node<2->[on chain,left] at (0, 0) {Makefile};
      \node<3->[on chain,xshift=-8mm,rev] {};
      \node<6->[on chain,join,rev] {};
    \end{scope}
  \end{tikzpicture}
\end{frame}

\begin{frame}{Concurrent Versions System (CVS)}
  Version control in the 1990s:
  \begin{itemize}
  \item collaboration over the network
  \item several working copies
  \item one central repository
  \end{itemize}

  \pause

  \begin{center}
  \begin{tikzpicture}
    \begin{scope}[start chain, node distance=16mm]
      \node[working copy, on chain, label=above:Alice] (Alice)
           {hello.c\\ Makefile};
      \node[repository, on chain, label=above:CVS Server] (repository) {};
      \node[working copy, on chain, label=above:Bob] (Bob)
           {hello.c\\ Makefile};
    \end{scope}

    \begin{scope}[scale=0.5,transform shape]
      \begin{scope}[start chain]
        \node[on chain,left, yshift=3mm, xshift=-2mm] at (repository)
             {hello.c};
        \node[on chain,xshift=-8mm,rev] {};
        \node[on chain,join,rev] {};
      \end{scope}
      \begin{scope}[start chain]
        \node[on chain,left, yshift=-3mm, xshift=-2mm] at (repository)
             {Makefile};
        \node[on chain,xshift=-8mm,rev] {};
        \node<3->[on chain,join,rev] {};
      \end{scope}
    \end{scope}

    \draw<3>[->, short] (Alice) -- node[above] {commit} (repository);
    \draw<4>[->, short] (repository) -- node[above] {update} (Bob);
  \end{tikzpicture}
  \end{center}
\end{frame}

\begin{frame}{So, everything is good?}
  CVS has many limitations:
  \begin{itemize}
  \item no atomic commits
  \item no rename information
  \item branches? I hope you have a CVS guru at hand\dots
  \end{itemize}
\end{frame}

\begin{frame}{Subversion (SVN)}
  Version control from this millennia --- ``\emph{CVS done right}'':
  \begin{itemize}
  \item atomic commits
  \item tracks renames
  \item supports some operations without network access
    \pause
  \item clean and simple design compared to CVS
  \end{itemize}
\end{frame}

\begin{frame}{Merging in Subversion}
  SVN is a centralized system:
  \begin{center}
    \begin{tikzpicture}[node distance=1cm]
      \node[repository, label=above:Repository] (repository) {};
      \node[rev] (r1) at (-7mm, 0) {};
      \node[rev] (r2) at (0, 0) {};
      \node[rev] (r3) at (7mm, 0) {};
      \draw[->] (r1) -- (r2);
      \draw[->] (r2) -- (r3);

      \node[working copy, label=below:Alice, left=of repository] (a) {
        hello.c\\
        Makefile
      };
      \node[working copy, label=below:Bob, below left=of repository] (b) {
        hello.c\\
        Makefile
      };
      \node[working copy, label=below:Carla, below=of repository] (c) {
        hello.c\\
        Makefile
      };

      \node[working copy, label=below:Dan, below right=of repository] (d) {
        hello.c\\
        Makefile
      };

      \node[working copy, label=below:Eve, right=of repository] (e) {
        hello.c\\
        Makefile
      };

      \draw[<->, short] (a) -- (repository);
      \draw[<->, short] (b) -- (repository);
      \draw[<->, short] (c) -- (repository);
      \draw[<->, short] (d) -- (repository);
      \draw[<->, short] (e) -- (repository);
    \end{tikzpicture}
  \end{center}

  \begin{itemize}
  \item merging takes place in client
  \item merging takes place on server(!)
  \end{itemize}
\end{frame}

\begin{frame}{SVN Merge in Client}
  When you do \hgcmd{svn update}, you merge:
  \begin{itemize}
  \item this can of course result in conflicts
  \item you must resolve the merge before you go on
  \item might be difficult to handle everything at once
  \end{itemize}
  \pause

  What if you want to abandon a merge?
  \begin{itemize}
  \item you can revert files with conflicts to their old state
  \item but other files may have been updated
  \item beware of mixed revisions\dots
  \end{itemize}
\end{frame}

\begin{frame}{Mixed Revisions?!}
  SVN lets you work with an \alert{inconsistent} working copy:
  \begin{itemize}
  \item Alice and Bob have revision 1
  \item Alice changes \path{hello.c} $\to$ revision 2
  \item Bob changes \path{Makefile} $\to$ \alert{revision 3}
  \end{itemize}
  \pause

  They both have mixed revisions in their working copies:
  \begin{center}
    \begin{tikzpicture}
      \tikzstyle{working copy}+=[text width=25mm]
      \node[working copy, label=below:Alice] (a) {
        hello.c (r2)\\
        Makefile (r1)
      };
      \node[working copy, label=below:Bob, right=of a] (b) {
        hello.c (r1)\\
        Makefile (r3)
      };
    \end{tikzpicture}
  \end{center}

  Difficult for Carla to reproduce either working copy.
\end{frame}

\begin{frame}{Server-Side Merges}
  Mixed revisions are a result of allowing server-side merges
  \begin{itemize}
  \item can we forbid server-side merges?
  \item not really --- it would ruin branches in SVN
  \end{itemize}
\end{frame}


\begin{frame}{Branches}
  A key concept:
  \begin{itemize}
  \item parallel lines of development
  \item used to track releases
  \item used to isolate disruptive changes
  \end{itemize}

  \begin{tikzpicture}
    \path[use as bounding box] (0, -1.5) rectangle (10, 1.5);
    \draw<2->[timeline] (0, -1) -- +(10, 0) node[below left] {time};

    \draw<5>[branch, blue!30, line width=2mm]
      (v10) -- ++(1,1)
            -- coordinate[pos=0.4] (v101) ++(3,0);

    \draw<6->[branch, blue!30, line width=2mm]
      (v10) -- ++(1,1)
            -- coordinate[pos=0.2] (v101)
               coordinate[pos=0.7] (v102) ++(6,0);

    \draw<2-3>[branch, line width=3mm]
      (0,0) -- coordinate[pos=0.4] (v10) +(2.5,0);

    \draw<4-6>[branch, line width=3mm]
      (0,0) -- coordinate[pos=0.2] (v10) +(5,0);

    \draw<3->[thick] (v10) ++(0, 0.3) -- ++(0, -0.6) node[tag] {1.0};
    \draw<5->[thick] (v101) ++(0, 0.2) -- +(0, -0.4) node[tag] {1.0.1};
    \draw<6->[thick] (v102) ++(0, 0.2) -- +(0, -0.4) node[tag] {1.0.2};
  \end{tikzpicture}
\end{frame}

\begin{frame}{Merging}
  The opposite of branching:
  \begin{itemize}
  \item combines two branches
  \item used to merge back bugfixes
  \item used to integrate feature branches
  \end{itemize}

  \begin{tikzpicture}
    \path[use as bounding box] (0, -1.5) rectangle (10, 1.5);
    \draw[timeline] (0, -1) -- +(10, 0) node[below left] {time};

    \draw<1-2>[branch, blue!30, line width=2mm]
      (v10) -- ++(1,1)
            -- coordinate[pos=0.2] (v101)
               coordinate[pos=0.7] (v102) ++(6,0);

    \draw<3->[branch, blue!30, line width=2mm]
      (v10) -- ++(1,1)
            -- coordinate[pos=0.2] (v101)
               coordinate[pos=0.7] (v102) ++(6,0)
            -- +(1, -1);

    \draw<2->[branch, blue!30, line width=2mm]
      (v101) ++(0.8, 0) -- +(1,-1);

    \draw<1>[branch, line width=3mm]
      (0,0) -- coordinate[pos=0.2] (v10) +(5,0);

    \draw<2>[branch, line width=3mm]
      (0,0) -- coordinate[pos=0.125] (v10) +(8,0);

    \draw<3>[branch, line width=3mm]
      (0,0) -- coordinate[pos=0.1] (v10) +(10,0);

    \draw<1->[thick] (v10) ++(0, 0.3) -- ++(0, -0.6) node[tag] {1.0};
    \draw<1->[thick] (v101) ++(0, 0.2) -- +(0, -0.4) node[tag] {1.0.1};
    \draw<1->[thick] (v102) ++(0, 0.2) -- +(0, -0.4) node[tag] {1.0.2};
  \end{tikzpicture}
\end{frame}



\begin{frame}{Branches in SVN}
  Subversion knows nothing about branches!
  \begin{itemize}
  \item but SVN has a cheap copy mechanism
  \item used for tags and branches
  \end{itemize}

  \begin{tikzpicture}
    \node<2->[working copy, below, text width=20mm, label=above:r10]
             (a) at (0, 0) {
      trunk/\\
      \quad hello.c\\
      \quad Makefile\\
      branches/\\
      tags/
    };
    \node<3->[working copy, below, text width=25mm, label=above:r11]
             (b) at (3.5, 0) {
      trunk/\\
      \quad hello.c\\
      \quad Makefile\\
      branches/\\
      \quad \alert<3>{goodbye/}\\
      \qquad \alert<3>{hello.c}\\
      \qquad \alert<3>{Makefile}\\
      tags/
    };
    \node<4->[working copy, below, text width=30mm, label=above:r12]
             (c) at (7.5, 0) {
      trunk/\\
      \quad hello.c\\
      \quad Makefile\\
      branches/\\
      \quad goodbye/\\
      \qquad hello.c\\
      \qquad \alert<4>{goodbye.c}\\
      \qquad Makefile\\
      tags/
    };

    \tikzstyle{s}=[yshift=-5mm]
    \tikzstyle{every pin edge}=[draw, red, <-]

    \draw<3->[->, short] ([s] a.north east) -- ([s] b.north west);
    \draw<4->[->, short] ([s] b.north east) -- ([s] c.north west);
  \end{tikzpicture}
\end{frame}

\begin{frame}{Merging Branches in SVN}
  Branches are only interesting if you can merge them:
  \begin{itemize}
  \item before SVN 1.5: no built-in support for merging(!)
  \item SVN 1.5 and later: tracks info needed for merging
  \end{itemize}

  \pause

  \begin{center}
  \begin{tikzpicture}
    \node[draw=structure, fill=structure!20!white, text justified,
      text width=0.9\textwidth, font=\small] {The bottom line is that
      Subversion's merge-tracking feature has an \alert{extremely
        complex} internal implementation, and the
      \texttt{svn:mergeinfo} property is the only window the user has
      into the machinery. Because the feature is \alert{relatively
        new}, a numbers of edge cases and possible unexpected
      behaviors may pop up. \hfill\itshape ---Version Control with
      Subversion};
  \end{tikzpicture}
  \end{center}

  (Mercurial has robust built-in support for merging branches.)
\end{frame}

%% \begin{frame}{Thinking Distributed}
%%   Natural solution to SVN branch situation:
%%   \begin{itemize}
%%   \item make merges explicit, which requires
%%   \item branches as first-class objects
%%   \end{itemize}
%%
%%   \pause
%%
%%   \begin{center}
%%     \begin{tikzpicture}
%%       \begin{pgfonlayer}{foreground}
%%         \begin{scope}[thick, node distance=4mm]
%%           \node[rev] (r1) {};
%%           \node[rev, right=of r1] (r2) {};
%%           \node[rev, right=of r2] (r3) {};
%%           \draw[->] (r1) -- (r2);
%%           \draw[->] (r2) -- (r3);
%%
%%           \node[rev, below=of r1] (r4) {};
%%           \node[rev, right=of r4] (r5) {};
%%           \node[rev, right=of r5] (r6) {};
%%           \draw[->] (r4) -- (r5);
%%           \draw[->] (r5) -- (r6);
%%         \end{scope}
%%       \end{pgfonlayer}
%%
%%       \node[draw, fill=blue!60, fit=(r1) (r2) (r3)] (trunk) {};
%%       \node[draw, fill=blue!30, fit=(r4) (r5) (r6)] (bob) {};
%%
%%       \begin{pgfonlayer}{background}
%%         \node[thick, repository, inner sep=10pt,
%%           label=above:Repository, fit=(trunk) (bob)] {};
%%       \end{pgfonlayer}
%%
%%       \node[working copy, label=below:Alice, left=of trunk] (a) {
%%         hello.c\\
%%         Makefile
%%       };
%%       \node[working copy, label=below:Bob, below=of bob] (b) {
%%         hello.c\\
%%         Makefile
%%       };
%%       \node[working copy, label=below:Carla, right=of trunk] (c) {
%%         hello.c\\
%%         Makefile
%%       };
%%
%%       \draw[<->] (a) -- (trunk);
%%       \draw[<->] (b) -- (bob);
%%       \draw[<->] (c) -- (trunk);
%%     \end{tikzpicture}
%%   \end{center}
%% \end{frame}

\begin{frame}{Centralized Revision Control}
  Subversion use a single server:
  \begin{center}
    \begin{tikzpicture}
      \tikzstyle{working copy}+=[below, text width=25mm]

      \node[repository, label=above:Repository] (repository) {};
      \node[rev] (r1) at (-7mm, 0) {};
      \node[rev] (r2) at (0, 0) {};
      \node[rev] (r3) at (7mm, 0) {};
      \draw[->] (r1) -- (r2);
      \draw[->] (r2) -- (r3);

      \node[working copy, label=below:Alice] (a) at (-3.5, -2.5) {
        trunk/\\
        \quad hello.c\\
        \quad Makefile
      };
      \node[working copy, label=below:Bob] (b) at (0, -2.5) {
        branches/\\
        \quad bob/\\
        \qquad hello.c\\
        \qquad Makefile
      };
      \node[working copy, label=below:Carla] (c) at (3.5, -2.5) {
        trunk/\\
        \quad hello.c\\
        \quad Makefile
      };

      \draw[<->, short] (a) -- (repository);
      \draw[<->, short] (b) -- (repository);
      \draw[<->, short] (c) -- (repository);
    \end{tikzpicture}
  \end{center}
\end{frame}

\begin{frame}{Distributed Revision Control}
  Mercurial duplicates the history on many servers:
  \begin{center}
    \begin{tikzpicture}[start chain, bend angle=10]
      \tikzstyle{every node}=[repository, minimum height=18mm, text width=15mm,]
      \tikzstyle{every path}=[<->, short]

      \node (a) at ( 90:3) {Alice};
      \node (b) at (210:3) {Bob};
      \node (c) at (-30:3) {Carla};
      \draw<1-2> (a) -- (b);
      \draw<1-2> (b) -- (c);
      \draw<1-2> (c) -- (a);

      \node<2->[overlay] (l) at ([xshift=3cm] a) {Alice's Laptop};
      \draw<2-> (a) -- (l);

      \node<3-> (r) at (0, 0) {Server};
      \draw<3-> (a) -- (r);
      \draw<3-> (b) to[bend left] (r);
      \draw<3-> (c) to[bend right] (r);

      \draw<4-> (b) to[bend right] (c);
    \end{tikzpicture}
  \end{center}
\end{frame}


\section{Using Mercurial}

\subsection{Getting Started}

\begin{frame}
  \begin{center}
    \vfill
    \huge\bfseries Live Demo!
    \vfill
    \hyperlink{after-basics}{\beamerskipbutton{continue}}
  \end{center}
\end{frame}

\begin{frame}[fragile]{Getting Started}
  We will create a \path{hello-world} project:
\begin{lstlisting}
% hg init hello-world
% cd hello-world
\end{lstlisting}

A new repository is of course empty:
\begin{lstlisting}
% hg log
\end{lstlisting}
and has a clean status:
\begin{lstlisting}
% hg status
\end{lstlisting}
\end{frame}

\begin{frame}[fragile]{Adding Files}
  We copy some ready-made files into the working copy:
\begin{lstlisting}
% cp ../hello-files/* .
% hg status
? Makefile
? hello.c
\end{lstlisting}

Put the new files under revision control:
\begin{lstlisting}
% hg add
adding Makefile
adding hello.c
% hg status
A Makefile
A hello.c
\end{lstlisting}
\end{frame}

\begin{frame}[fragile]{Making a Commit}
We can now commit the changes shown by \hgcmd{hg status}:
\begin{lstlisting}
% hg commit -m "Imported source code."
\end{lstlisting}

The changeset is shown in \hgcmd{hg log}:
\begin{lstlisting}
% hg log
changeset:   0:9cef08a0e941
tag:         tip
user:        Martin Geisler <mg@lazybytes.net>
date:        Sun Aug 16 00:22:11 2009 +0200
summary:     Imported source code.
\end{lstlisting}
\end{frame}

\begin{frame}[fragile]{Settings}
  You configure Mercurial using configuration files:
  \begin{itemize}
  \item \path{/etc/mercurial/hgrc} holds global settings
  \item \path{~/.hgrc} holds per-user settings
  \item \path{.hg/hgrc} holds per-repository settings
  \item username in previous commit came from \path{~/.hgrc}:
\begin{lstlisting}[language=ini]
[ui]
username = Martin Geisler <mg@lazybytes.net>
\end{lstlisting}
  \end{itemize}
\end{frame}


\begin{frame}[fragile]{Examining Differences}
Change the output from ``hello, world'' to ``Hello World!''.

Mercurial will list the file as changed:
\begin{lstlisting}
% hg status
M hello.c
\end{lstlisting}
and can list the change:
\begin{lstlisting}
% hg diff
diff -r 9cef08a0e941 hello.c
--- a/hello.c   Sun Aug 16 00:22:11 2009 +0200
+++ b/hello.c   Sun Aug 16 01:21:15 2009 +0200
@@ -1,5 +1,5 @@
 #include <stdio.h>
 
 int main(void) {
-    printf("hello, world\n");
+    printf("Hello World!\n");
 }
\end{lstlisting}

\end{frame}

\begin{frame}[fragile]{Working with History}
  Committing our change adds another changeset:
\begin{lstlisting}
% hg commit -m "Much better output."
% hg log
changeset:   1:759a3a26c7c5
tag:         tip
user:        Martin Geisler <mg@lazybytes.net>
date:        Sun Aug 16 15:28:50 2009 +0200
summary:     Much better output.

changeset:   0:9cef08a0e941
user:        Martin Geisler <mg@lazybytes.net>
date:        Sun Aug 16 00:22:11 2009 +0200
summary:     Imported source code.
\end{lstlisting}

% The new commit is the working copy parent:
% \begin{lstlisting}
% % hg parents
% changeset:   1:759a3a26c7c5
% tag:         tip
% user:        Martin Geisler <mg@lazybytes.net>
% date:        Sun Aug 16 15:28:50 2009 +0200
% summary:     Much better output.
% \end{lstlisting}

\end{frame}

\subsection{Working with Remote Repositories}

\begin{frame}{Pushing and Pulling}
\end{frame}

\begin{frame}{Merging}
\end{frame}

\begin{frame}{Searching History}
  Everything is local and fast:
  \begin{itemize}
  \item \hgcmd{hg log} can search in commit messages and usernames
  \item \hgcmd{hg grep} seaches in file content
  \item \hgcmd{hg bisect} makes a binary search on the revision graph
  \end{itemize}
\end{frame}

\begin{frame}{Revision Graph Bisection}
\end{frame}

\section{Cool Extensions}

\begin{frame}[label=after-basics]{Mercurial is Pluggable}
\end{frame}

\subsection{Changing History}

\begin{frame}{Moving Changesets Around}
  \tikzstyle{rev}+=[on chain, join, minimum size=5mm]
  \tikzset{node distance=4mm and 6mm}

  Tired of all those merges? Use the \hgext{rebase} extension!
  \begin{itemize}
  \item Revision graph:

    \begin{tikzpicture}[start chain]
      \node[rev] {$A$};
      \node[rev] {$B$};
      \node[rev] {$C$};
      \begin{scope}[start branch=pulled]
        \node<3->[rev,on chain=going below right] {$X$};
        \node<3->[rev] {$Y$};
        \node<3->[rev] {$Z$};
      \end{scope}
      \node<2->[rev] {$D$};
      \node<2->[rev] {$E$};
    \end{tikzpicture}

  \item<4-> Merge:

    \begin{tikzpicture}[start chain]
      \node[rev] {$A$};
      \node[rev] {$B$};
      \node[rev] {$C$};
      \begin{scope}[start branch=pulled]
        \node[rev,on chain=going below right] {$X$};
        \node[rev] {$Y$};
        \node[rev] {$Z$};
      \end{scope}
      \node[rev] {$D$};
      \node[rev] {$E$};
      \begin{scope}[continue branch=pulled]
        \node[rev,on chain=going above right,join=with chain-end] {$M$};
      \end{scope}
    \end{tikzpicture}

  \item<5-> Rebase:

    \begin{tikzpicture}[start chain]
      \node[rev] {$A$};
      \node[rev] {$B$};
      \node[rev] {$C$};
      \begin{scope}[start branch=pulled]
        \node[rev,on chain=going below right] {$X$};
        \node[rev] {$Y$};
        \node[rev] {$Z$};
        \node[rev] {$D'$};
        \node[rev] {$E'$};
      \end{scope}
      \node[rev,join=by {black!30!white},opacity=0.3] {$D$};
      \node[rev,join=by {black!30!white},opacity=0.3] {$E$};
    \end{tikzpicture}

  \item<6-> Beware: public changes should never be rebased.
  \end{itemize}
\end{frame}

\begin{frame}{Maintaining Patch Series}
  The \hgext{mq} extension makes it easy to maintain a patch series:

  \begin{center}
    \begin{tikzpicture}[start chain=stack going above, node distance=5mm]
      \tikzstyle{rev}+=[on chain,join]
      \tikzstyle{patch}=[rev, draw=green!50!black!50,
        top color=white, bottom color=green!50!black!20]
      \path[use as bounding box] (0,0) -- (0, 4.5);

      \node[on chain] {$\vdots$};
      \node[rev] {};
      \node<2->[patch] {code};
      \node<3->[patch] {test};
      \node<4->[patch] {doc};

      \draw<5->[->] ([xshift=-1cm] stack-3.center)
        -- node[left, anchor=mid east] {\hgcmd{qpush}}
                    ([xshift=-1cm] stack-5.center);
      \draw<5->[->] ([xshift=1cm] stack-5.center)
        -- node[right, anchor=mid west] {\hgcmd{qpop}}
                    ([xshift=1cm] stack-3.center);
    \end{tikzpicture}
  \end{center}

\end{frame}

\begin{frame}{Editing History}
  \tikzstyle{rev}+=[on chain, minimum size=7mm]
  \tikzstyle{squiggle}=[on chain, font=\large, red]
  \tikzset{node distance=5mm}

  Inspired by \hgcmd{git rebase -i}, \hgext{histedit} lets you
  \begin{itemize}[<+->]
  \item reorder changesets:

    \begin{tikzpicture}[start chain]
      \node[rev] {$A$};
      \node[rev,join] {$B$};
      \node[rev,join] {$C$};
      \node[squiggle] {$\rightsquigarrow$};
      \node[rev] {$A$};
      \node[rev,join] {$C'$};
      \node[rev,join] {$B'$};
    \end{tikzpicture}

  \item fold changesets:

    \begin{tikzpicture}[start chain]
      \node[rev] {$A$};
      \node[rev,join] {$B$};
      \node[rev,join] {$C$};
      \node[squiggle] {$\rightsquigarrow$};
      \node[rev] {$A$};
      \node[rev,join] {$BC$};
    \end{tikzpicture}

  \item drop changesets:

    \begin{tikzpicture}[start chain]
      \node[rev] {$A$};
      \node[rev,join] {$B$};
      \node[rev,join] {$C$};
      \node[squiggle] {$\rightsquigarrow$};
      \node[rev] {$A$};
      \node[rev,join] {$C'$};
    \end{tikzpicture}

  \item edit changesets:

    \begin{tikzpicture}[start chain]
      \node[rev] {$A$};
      \node[rev,join] {$B$};
      \node[rev,join] {$C$};
      \node[squiggle] {$\rightsquigarrow$};
      \node[rev] {$A$};
      \node[rev,join] {$X$};
      \node[rev,join] {$B'$};
      \node[rev,join] {$C'$};
    \end{tikzpicture}
  \end{itemize}
\end{frame}

\subsection{Migrating History}

\begin{frame}{Migrating History}
  The \hgext{convert} extension can import history:
  \begin{itemize}
    \item CVS, SVN, Git, Bazaar, Darcs, \dots
    \item incremental conversion
    \item many options for fiddling with branches, authors, \dots
  \end{itemize}
  \pause

  Interestingly, \hgext{convert} can import from Mercurial:
  \begin{itemize}
    % Break "--" to avoid them forming an en-dash...
  \item \hgcmd{-{}-filemap} lets you exclude and rename files
  \item \hgcmd{-{}-branchmap} lets you rename branches
  \end{itemize}
\end{frame}

\subsection{Bi-Directional Gateways}

\begin{frame}{Interfacing with Subversion}
  The \hgext{hgsubversion} extension let's you:
  \begin{itemize}
  \item use \hgcmd{hg clone} on a SVN URLs
  \item use \hgcmd{hg pull} to convert new SVN revisions
  \item use \hgcmd{hg push} to commit changesets to SVN server
  \end{itemize}

  The extension is being used, but please note:
  \begin{itemize}
  \item it is not yet feature complete
  \item requires standard \path{trunk/}, \path{branches/} and \path{tags/}
    layout
  \end{itemize}

  \begin{center}
    \includegraphics[height=8em]{hgsubversion}
  \end{center}

\end{frame}

\begin{frame}{Interfacing with Git}
  Need to work on a Git repository? Try \hgext{hg-git}!
  \begin{itemize}
  \item Mercurial extension: you get the nice \hgcmd{hg} command line
  \item round-tripping: changeset hashes are preserved
  \end{itemize}

  % TODO: add colors, improve boxes.
  \begin{center}
    \begin{tikzpicture}
      \node[draw] (server) {Git};
      \node[draw,below left=of server] (c1) {Hg};
      \node[draw,below=of server] (c2) {Hg};
      \node[draw,below right=of server] (c3) {Git};
      \draw[<->, short] (c1) to[bend left] (server);
      \draw[<->, short] (c2) -- (server);
      \draw[<->, short] (c3) to[bend right] (server);
    \end{tikzpicture}
  \end{center}
\end{frame}

\section{Conclusion}

\begin{frame}{Weak Points}
  Mercurial and distributed revision control has some weak points:
  \begin{itemize}
  \item tag conflicts
  \item filename encodings across different filesystems
  \item penalties for large binary files
  \item cannot retrieve a sub-tree (narrow clone)
  \item cannot retrieve only recent history (shallow clone)
  \end{itemize}
\end{frame}

\begin{frame}{Mercurial in a Nutshell}
\begin{itemize}
\item elegance
\end{itemize}
\end{frame}

\subsection{More Information}

\begin{frame}{More Information}
  \begin{itemize}
  \item Mercurial homepage: \url{http://mercurial.selenic.com/}
  \end{itemize}
\end{frame}


\end{document}

% LocalWords:  SVN Makefile RCS CVS changeset changesets Changeset Changesets