changeset 302:78a5a27609a5

Introduction, conclussion, more consistent
author Martin Geisler <mg@lazybytes.net>
date Wed, 08 Jun 2011 16:34:44 +0200
parents 027862d2fec9
children 87e3dd9b2002
files revset-talk.tex
diffstat 1 files changed, 267 insertions(+), 119 deletions(-) [+]
line wrap: on
line diff
--- a/revset-talk.tex
+++ b/revset-talk.tex
@@ -22,16 +22,68 @@
 
 \section{Introduction}
 
+\begin{frame}[fragile]{Confusing Histories}
+  Big projects can give rise to a branchy history:
+  \begin{itemize}
+  \item several concurrent branches
+  \item many developers pushing changes
+  \end{itemize}
+
+  \pause
+
+  Mercurial help you to cut away the unnecessary fluff:
+  \begin{itemize}
+  \item<2-> Revision sets selects revisions (Mercurial 1.6):
+\begin{lstlisting}
+$ hg log -r "branch('stable') and user('Martin')"
+\end{lstlisting}
+    Can be used in all places where Mercurial expects revisions
+
+  \item<3-> File sets selects files in revisions (Mercurial 1.9 or
+    2.0):
+\begin{lstlisting}
+$ hg revert "set:added() and size('>20MB')"
+\end{lstlisting}
+    Can be used in all places where Mercurial expects file names
+
+  \end{itemize}
+\end{frame}
+
+\begin{frame}[fragile]{Flexibility}
+  The query languages lets you solve hard problems:
+  \begin{itemize}[<+->]
+  \item Imagine you have a dirty working copy:
+\begin{lstlisting}
+$ hg status
+M index.html
+A logo.png
+\end{lstlisting}
+ But how can you see the diff of \path{index.html} only?
+
+\item Easy! You use your nifty Unix shell:
+\begin{lstlisting}
+$ hg diff $(hg status --no-status --modified)
+\end{lstlisting}
+
+\item With file sets you can do
+\begin{lstlisting}
+$ hg diff "set:modified()"
+\end{lstlisting}
+and it will work on all platforms
+
+  \end{itemize}
+\end{frame}
+
 \begin{frame}[fragile]{Quoting}
   How to handle special characters:
   \begin{itemize}[<+->]
-\item You will need to quote your revsets on the command line:
+\item You will need to quote your queries on the command line:
 \begin{lstlisting}
 $ hg log -r parents()
 zsh: parse error near `()'
 \end{lstlisting}
 
-\item Strings in revsets can be in single- or double-quotes:
+\item Strings in queries can be in single- or double-quotes:
 \begin{lstlisting}
 $ hg log -r "user('Martin')"
 \end{lstlisting}
@@ -56,57 +108,143 @@
 \begin{frame}[fragile]{Predicates}
   Predicates select changesets for inclusion in the resulting set:
   \begin{itemize}
-  \item Changeset metadata: \cmd{closed()}, \cmd{head()},
-    \cmd{merge()}, \cmd{author(string)}, \cmd{date(interval)},
+  \item \cmd{closed()}, \cmd{head()}, \cmd{merge()}: simple changeset properties
 
-Closed heads:
-\begin{lstlisting}
-$ hg log -r "head() and closed()"
-\end{lstlisting}
-
-Reopened branches:
-\begin{lstlisting}
-$ hg log -r "closed() and not head()"
-\end{lstlisting}
+  \item \cmd{author(string)}, \cmd{date(interval)}: search by user
+    name or by commit date
 
 \begin{lstlisting}
 $ hg log -r "author('Martin') and merge()"
 \end{lstlisting}
 
+  \item \cmd{grep(regex)}, \cmd{keyword(string)}: search in commit
+    message, user name, changed file names for a regular expression or
+    a substring
+
+  %\item \cmd{bisected(string)}: changesets marked good/bad/skip while
+  %  bisecting
+
+  \end{itemize}
+\end{frame}
+
+\begin{frame}[fragile]{Matching by Files in Changesets}
+  Matching by how a file changed:
+  \begin{itemize}
+  \item \cmd{adds(pattern)}: a file matching pattern was added
+  \item \cmd{modifies(pattern)}: a file matching pattern was modified
+  \item \cmd{removes(pattern)}: a file matching pattern was removed
+  \item<2-> \cmd{file(pattern)}: combination of all the above
+  \item<3-> \cmd{contains(pattern)}: a file matching pattern was present
+  \end{itemize}
+\end{frame}
+
+\subsection{Functions}
+
+\begin{frame}[fragile]{Following the Changeset Graph}
+  A common task is to follow the graph from a particular changeset:
+  \begin{itemize}
+  \item \cmd{::set} or \cmd{ancestors(set)}: ancestors of changesets in set
+  \item \cmd{set::} or \cmd{descendants(set)}: descendants of changesets in set
+  \item \cmd{X::Y}: a combination of the above, finding changesets between X and Y
   \end{itemize}
 
-  bisected(string)
-  grep(regex)
-  keyword(string)
+  \pause
 
-  \cmd{adds(pattern)}
-  \cmd{contains(pattern)}
-  \cmd{file(pattern)}
-  \cmd{filelog(pattern)}
-  \cmd{modifies(pattern)}
-  \cmd{removes(pattern)}
-
+  Changes that need to be merged into the default branch:
+\begin{lstlisting}
+$ hg log -r "ancestors(stable) - ancestors(default)"
+$ hg log -r "::stable - ::default"
+\end{lstlisting}
 
 \end{frame}
 
+\begin{frame}[fragile]{Family Relations}
+  
+  \begin{itemize}
+  \item \cmd{ancestor(single, single)}: greatest common ancestor of
+    the two changesets. Used to find out what needs to be merged in a
+    merge between X and Y:
+\begin{lstlisting}
+$ hg log -r "ancestor(X, Y)::Y"
+\end{lstlisting}
 
+  \item \cmd{children(set)}, \cmd{parents([set])}: set of all children/parents of set
+
+  \item \cmd{heads(set)}, \cmd{roots(set)}: changesets from set with
+    no children/parents in set
+
+\end{itemize}
+\end{frame}
 
-\begin{frame}{Functions}
-  ancestor(single, single)
-  ancestors(set)
-  children(set)
-  descendants(set)
-  follow([file])
+\begin{frame}[fragile]{Parents and Grand Parents}
+  Going from a changeset to the parent changeset is easy:
+  \begin{itemize}
+  \item \cmd{p1([set])}, \cmd{p2([set])}: the first/second parent of
+    changesets in set or of the working copy if no set is given
+
+  \item \cmd{x\textasciicircum}, \cmd{x\textasciicircum 2}: the
+    first/second parent of \cmd x
+
+  \item \cmd{x\textasciitilde n}: the $n$'th first ancestor of \cmd x,
+    \cmd{x\textasciitilde 0} is \cmd x, \cmd{x\textasciitilde 3} is
+    \cmd{x\textasciicircum\textasciicircum\textasciicircum}
+  \end{itemize}
+
+  To see both sides of a merge changeset M use
+\begin{lstlisting}
+$ hg diff -r "p1(M):M" && hg diff -r "p2(M):M"
+\end{lstlisting}
+  or the shorter
+\begin{lstlisting}
+$ hg diff -c M && hg diff -r "M^2:M"
+\end{lstlisting}
 
-  heads(set)
+  %\item \cmd{follow([file])}: follow working copy parents or follow a
+  %  file history across renames (like \cmd{hg log -f})
+\end{frame}
 
-  outgoing([path])
+\begin{frame}[fragile]{The Next Push}
+  The \cmd{hg outgoing} command tells what will be pushed, and so does
+  this function:
+  \begin{itemize}
+  \item \cmd{outgoing([path])}: changesets not in the destination
+    repository
+  \end{itemize}
+
+\pause
+
+  It is now easy to see what you will push as a single diff:
+\begin{lstlisting}
+$ hg diff -r "outgoing()"
+\end{lstlisting}
+% \cmd{hg diff} extracts the first/last revision using \cmd{min()} and
+% \cmd{max()}
+
+\pause
 
-  p1([set])
-  p2([set])
-  parents([set])
-  present(set)
-  roots(set)
+  It is also easy to reset a repository:
+\begin{lstlisting}
+$ hg strip "outgoing()"
+\end{lstlisting}
+  People familiar with Git will know this as
+\begin{lstlisting}
+$ git reset --hard origin/master
+\end{lstlisting}
+
+\end{frame}
+
+\begin{frame}[fragile]{Handling Missing Revisions}
+  If you don't know if a given revision is present, then use:
+  \begin{itemize}
+  \item \cmd{present(set)}: prevents lookup errors if a revision in
+    set is not found. Used like
+\begin{lstlisting}
+$ hg log -r "head() and (present('bad'):: - present('fix')::)"
+\end{lstlisting}
+    where bad is a known buggy changeset and fix is a bugfix. Without
+    the use of \cmd{present()}, an error would be raised if the bugfix
+    is not yet in the repository.
+  \end{itemize}
 \end{frame}
 
 \begin{frame}{Final Touches on Your Query}
@@ -114,8 +252,7 @@
   \begin{itemize}[<+->]
     \item \cmd{max(set)}, \cmd{min(set)}: the changeset with
       minimum/maximum revision number in the set
-    \item \cmd{reverse(set)}: the set is an ordered set; this reverses
-      it
+    \item \cmd{reverse(set)}: the set is ordered; this reverses it
     \item \cmd{limit(set, n)}, \cmd{last(set, n)}: the first/last
       $n$ changesets
     \item \cmd{sort(set[, [-]key...])}: sorting the set by revision
@@ -135,8 +272,10 @@
   \end{enumerate}
   First match wins.
 
+  \pause
+
   You can override this using predicates:
-  \begin{itemize}[<+->]
+  \begin{itemize}
   %\item \cmd{rev(number)}
   %\item \cmd{id(hash)}
   \item \cmd{bookmark([name])}, \cmd{tag([name])}: the changeset with
@@ -153,22 +292,39 @@
 \subsection{Operators}
 
 \begin{frame}{Operators}
+  You can combine two revision sets using:
+  \begin{itemize}
 
+  \item \cmd{x and y} or \cmd{x \& y}: changesets in both \cmd x and
+    \cmd y
+
+  \item \cmd{x or y} or \cmd{x | y} or \cmd{x + y}: changesets in
+    either \cmd x or \cmd y
+
+  \item \cmd{x - y}: changesets in \cmd x but not in \cmd y
+
+  \end{itemize}
 \end{frame}
 
 \begin{frame}[fragile]{Examples}
   \begin{itemize}
-  \item Changes that need to be merged into the default branch:
-\begin{lstlisting}
-$ hg log -r "ancestors(stable) - ancestors(default)"
-$ hg log -r "::stable - ::default"
-\end{lstlisting}
+
 
 \item Heads on the current branch:
 \begin{lstlisting}
 $ hg log -r "head() and branch(.)"
 \end{lstlisting}
 
+    Closed heads:
+\begin{lstlisting}
+$ hg log -r "head() and closed()"
+\end{lstlisting}
+
+    Reopened branches:
+\begin{lstlisting}
+$ hg log -r "closed() and not head()"
+\end{lstlisting}
+
 \item Open heads on the current branch:
 \begin{lstlisting}
 $ hg log -r "head() and branch(.) and not closed()"
@@ -187,61 +343,35 @@
 \section{File Sets}
 
 \begin{frame}{Selecting Files}
+  File sets let you:
   \begin{itemize}
   \item select files from working copy
   \item select files from old revisions
-  \item might be part of Mercurial 1.9 (July) or 2.0 (November)
   \end{itemize}
-\end{frame}
-
-\begin{frame}
-  File sets give an amazing flexibility.
-\end{frame}
-
-\begin{frame}[fragile]{Working Copy Status}
-  The \cmd{hg status} command lets you select files:
-\begin{lstlisting}
-$ hg status
-M index.html
-A logo.png
-$ hg status --added
-A logo.png
-\end{lstlisting}
-
-How do you see the change to \path{index.html} without seeing the diff
-of the added \path{logo.png} file? You do:
-\begin{lstlisting}
-$ hg diff $(hg status --no-status --modified)
-\end{lstlisting}
-
-With file sets you can do
-\begin{lstlisting}
-$ hg diff "set:modified()"
-\end{lstlisting}
-and it will work on all platforms.
-
+  Hopefully part of Mercurial 1.9 (July) or 2.0 (November)
 \end{frame}
 
 \begin{frame}[fragile]{Working Copy Status}
 The proposed predicates are:
 \begin{itemize}[<+->]
 
-\item status flags: \cmd{modified()}, \cmd{added()}, \cmd{removed()},
-  \cmd{deleted()}, \cmd{unknown()}, \cmd{ignored()}, \cmd{clean()}
+\item \cmd{modified()}, \cmd{added()}, \cmd{removed()},
+  \cmd{deleted()}, \cmd{unknown()}, \cmd{ignored()}, \cmd{clean()}:
+  status flags
 
-\item copied files: \cmd{copied()}
+\item \cmd{copied()}: copied files, quite hard to extract today
 
-\item tracked files that \emph{would} be ignored: \cmd{ignorable()}
+\item \cmd{ignorable()}: tracked files that \emph{would} be ignored
 
-\item all tracked files:
-  \cmd{tracked()}
+\item \cmd{tracked()}: all tracked files
 
-\item after a merge: \cmd{conflicted()} and \cmd{not conflicted()}
+\item \cmd{conflicted()}: like \cmd{hg resolve --list} after a merge
 
 \end{itemize}
+
 \end{frame}
 
-\begin{frame}[fragile]
+\begin{frame}[fragile]{Searching by Path}
   We can replace the \cmd{find} Unix command:
   \begin{itemize}
   \item \cmd{glob(P)} instead of \cmd{find -path P}
@@ -256,49 +386,40 @@
 This shows that \path{foo.h} is a new header file in version 2.0.
 \end{frame}
 
-\begin{frame}
+\begin{frame}{File Type Predicates}
   Other \cmd{find}-like predicates will be:
   \begin{itemize}
-    \item file type: \cmd{executable()}, \cmd{symlink()},
-    \item permissions: \cmd{perm()}, \cmd{owner()}
-    \item other: \cmd{date()}, \cmd{size()}
-  \end{itemize}
-\end{frame}
-
-\begin{frame}
-  Matching files by content:
-  \begin{itemize}
-  \item \cmd{grep()}: like the Unix \cmd{grep} we all love
-  \item \cmd{contains()}: simple sub-string matching
-  \item \cmd{binary()}, \cmd{text()}
-  \item \cmd{decodes()}: check if file can be decoded with the given
-    character set, such as UTF-8, UTF-16, \dots
-  \item \cmd{eol()}: line-ending type, Unix (\cmd{LF}) or DOS (\cmd{CRLF})
+    \item \cmd{executable()}, \cmd{symlink()}: file type
+    \item \cmd{perm()}, \cmd{owner()}: file permissions
+    \item \cmd{date()}, \cmd{size()}: other file meta data
   \end{itemize}
 \end{frame}
 
-
-
-\begin{frame}[fragile]{Working Copy Predicates}
+\begin{frame}[fragile]{Looking Into Files}
+  Matching files by content:
+  \begin{itemize}[<+->]
+  \item \cmd{grep()}: like the Unix \cmd{grep} we all love
+  \item \cmd{contains()}: simple sub-string matching
+  \item \cmd{binary()}, \cmd{text()}: does file contain a NUL byte?
 \begin{lstlisting}
-$ hg status
-? logo.png
-? index.html
-$ hg status "set:unknown() and not binary()"
-? index.html
+$ hg add "set:unknown() and not binary()"
 \end{lstlisting}
+
+  \item \cmd{decodes()}: check if file can be decoded with the given
+    character set, such as UTF-8, UTF-16, \dots
+
+    Lets you find mistakes:
+\begin{lstlisting}
+$ hg status --all "set:glob('**.py') and not decodes('UTF-8')"
+C src/foo.py
+\end{lstlisting}
+
+  \item \cmd{eol()}: line-ending type, Unix (LF) or DOS (CRLF)
+  \end{itemize}
 \end{frame}
 
-
-\begin{frame}[fragile]{Working Copy Predicates}
-\begin{lstlisting}
-$ hg status -c 100 "set:decodes('UTF-8')"
-M plan.txt
-\end{lstlisting}
-\end{frame}
-
-\begin{frame}
-  Future extensions:
+\begin{frame}{Adding New Predicates}
+  The feature will be extensible, some possible future extensions:
   \begin{itemize}
   \item \cmd{magic()}: recognize files based on file content, like the
     \cmd{file} program in Unix
@@ -324,12 +445,39 @@
   \end{description}
 \end{frame}
 
+\section{Conclusion}
 
-\appendix
-\newcounter{finalframe}
-\setcounter{finalframe}{\value{framenumber}}
+\begin{frame}{Conclusion}
+  In short:
+  \begin{itemize}
+  \item revision sets lets you zoom in on the right part of the history
+  \item file sets will let you pick out the relevant files
+  \item both mechanisms are completely general
+  \end{itemize}
+
+  \pause
+
+  Please get in touch if you have more questions:
+  \begin{itemize}
+  \item Email: \curl{mg@aragost.com}
+  \item IRC: \curl{mg} in \curl{\#mercurial} on \curl{irc.freenode.net}
+  \end{itemize}
 
-\setcounter{framenumber}{\value{finalframe}}
+  \pause
+
+  \begin{center}
+    \begin{tikzpicture}
+      \tikzstyle{every node}=[font=\Huge\bfseries]
+      \node[black, shift={(0.8pt, -0.8pt)}] {Thank you!};
+      \node[orange!50!red] {Thank you!};
+    \end{tikzpicture}
+  \end{center}
+\end{frame}
+
+%\appendix
+%\newcounter{finalframe}
+%\setcounter{finalframe}{\value{framenumber}}
+%\setcounter{framenumber}{\value{finalframe}}
 
 \end{document}