Mercurial > hg > mercurial-talk
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