view mercurial.tex @ 31:841a65486521

Described hgsubversion.
author Martin Geisler <mg@lazybytes.net>
date Tue, 18 Aug 2009 21:30:14 +0200
parents 317450a7eb96
children 44c11490eab5
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.8pt,
  rulecolor=\color{white!50!black},
  %backgroundcolor=\color{white},
}

\usepackage{tikz}
\usetikzlibrary{chains,positioning,shapes}
\tikzstyle{every picture}=[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{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}

\begin{frame}{Branches}
  A central 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);

    \tikzstyle{branch}=[blue!60, ->, >=latex, line join=round]
    \tikzstyle{tag}=[draw=yellow!50!orange, fill=yellow!50]

    \draw<2->[->] (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-> (v10) ++(0, 0.3) -- ++(0, -0.6) node[below, tag] {1.0};
    \draw<5-> (v101) ++(0, 0.2) -- +(0, -0.4) node[below, tag] {1.0.1};
    \draw<6-> (v102) ++(0, 0.2) -- +(0, -0.4) node[below, 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);

    \tikzstyle{branch}=[blue!60, ->, >=latex, line join=round]
    \tikzstyle{tag}=[draw=yellow!50!orange, fill=yellow!50]

    \draw[->] (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-> (v10) ++(0, 0.3) -- ++(0, -0.6) node[below, tag] {1.0};
    \draw<1-> (v101) ++(0, 0.2) -- +(0, -0.4) node[below, tag] {1.0.1};
    \draw<1-> (v102) ++(0, 0.2) -- +(0, -0.4) node[below, tag] {1.0.2};
  \end{tikzpicture}
\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>[->] (Alice) -- node[above] {commit} (repository);
    \draw<4>[->] (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
  \end{itemize}
\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->[->] ([s] a.north east) -- ([s] b.north west);
    \draw<4->[->] ([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}{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[<->] (a) -- (repository);
      \draw[<->] (b) -- (repository);
      \draw[<->] (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}=[<->]

      \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}

\begin{frame}[label=after-basics]{Consistency and Subversion}
\end{frame}

\section{Cool Extensions}

\begin{frame}{Mercurial is Pluggable}
\end{frame}

\subsection{Changing History}

\begin{frame}{Moving Changesets Around}
  The \hgext{rebase} extension
\end{frame}

\begin{frame}{Maintaining Patch Series}
  The \hgext{mq} extension
\end{frame}

\begin{frame}{Editing History}
  The \hgext{histedit} extension
\end{frame}

\subsection{Migrating History}

\begin{frame}{Migrating History}
  The \hgext{convert} extension can import history:
  \begin{itemize}
    \item CVS, SVN, Git, \dots
    \item incremental conversion
  \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=10em]{hgsubversion}
  \end{center}

\end{frame}

\begin{frame}{Interfacing with Git}
\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