UW AMath High Performance Scientific Computing
 
AMath 483/583 Class Notes
 
Spring Quarter, 2011

Table Of Contents

Previous topic

Bitbucket repositories: viewing changesets, issue tracking

Next topic

Sphinx documentation

This Page

Mercurial examples

For some simple examples elsewhere, see:

Examples for Lecture 3

This example shows how one might create and use a stand-alone repository for one project, showing how you might use Mercurial for a single directory with no cloning, no bitbucket repository, etc.

At the end we’ll also look at how it can be cloned.

We’ll go through this example with more detail in Lecture 3.

Make a new directory:

$ cd
$ mkdir myproject

Confirm it’s empty:

$ cd myproject
/Users/rjl/myproject
$ ls -a
./  ../

Copy some files here so we’ll have something to start with:

$ cp $CLASSHG/codes/python/myfcns*.py .
$ ls
myfcns.py   myfcns2.py

We’re not yet using hg:

$ hg status
abort: There is no Mercurial repository here (.hg not found)!

hg init

Let’s create a repository for this directory:

$ hg init
$ ls -a
./      ../     .hg/        myfcns.py   myfcns2.py

No files have been committed yet:

$ hg status
? myfcns.py
? myfcns2.py

Let’s add everything in this directory (and recursively in any subdirectories, if there were any):

$ hg add
adding myfcns.py
adding myfcns2.py

$ hg status
A myfcns.py
A myfcns2.py

Now commit them:

$ hg commit -m "Initial commit of files copied from $CLASSHG"
myfcns.py
myfcns2.py
committed changeset 0:2a3c30a21b10

$ hg status

The last command prints nothing since the directory is “clean”

To force printing status of each file (C = clean):

$ hg status -A
C myfcns.py
C myfcns2.py

Now edit myfcns.py so the function f2 is x**4 instead of the exponential... [not shown here]

Now:

$ hg diff
diff -r 2a3c30a21b10 myfcns.py
--- a/myfcns.py Thu Apr 01 18:45:59 2010 -0700
+++ b/myfcns.py Thu Apr 01 18:56:44 2010 -0700
@@ -12,8 +12,9 @@

 def f2(x):
     """
-    An exponential function.
+    A power function.
     """
     from numpy import exp
-    y = exp(4.*x)
+    y = x**4
     return y
+

Commit this change:

$ hg status
M myfcns.py

$ hg commit -m "Changed f2 to be a power function"
myfcns.py
committed changeset 1:77711e71d739

Now let’s change the power from 4 to 5 [editing not shown]:

$ hg diff
diff -r 77711e71d739 myfcns.py
--- a/myfcns.py Thu Apr 01 18:58:00 2010 -0700
+++ b/myfcns.py Thu Apr 01 18:59:21 2010 -0700
@@ -15,6 +15,6 @@
     A power function.
     """
     from numpy import exp
-    y = x**4
+    y = x**5
     return y

The file is modified in the working copy, but not yet in the repository since we haven’t committed.

hg revert

Suppose after testing we decide this was a bad idea and want to revert back to what we had before changing the working copy:

$ hg status
M myfcns.py

$ hg revert myfcns.py
saving current version of myfcns.py as myfcns.py.orig
reverting myfcns.py

Now myfcns.py is back to the power function with exponent 4. Note that hg has also saved a copy of the working file before the revert as myfcns.py.orig, just in case you regret the revert. This file is not under version control:

$ hg status
? myfcns.py.orig

We could add it, but probably we don’t want to, not with this name anyway. Instead we’ll probably eventually delete it.

hgignore

You can tell hg to ignore certain files when it’s reporting on the status of the repository. This is useful for files of the form *.orig, for example, and also for files that are produced as the result of compiling or running a code, that you generally don’t want to place under version control. For example, we’ll see later that a python file like myfcns.py can lead to a file myfcns.pyc (compiled version) in some cases, so we might want hg to ignore all files of the form *.pyc. Also, compiling a fortran program in fname.f90 produces an object code file fname.o that we also won’t want to keep under version control.

You can print the status ignoring certain files with the -X flag:

$ hg status -X *.orig

But for file types you always want to ignore, it’s easier to create a file .hgignore to do this once and for all. This file should be in the same directory as .hg and contain, for example:

syntax: glob
*.orig
*.pyc
*.o

to ignore the types of files just described. glob refers to pattern matching.

See also:

Now hg status will ignore the *.orig file, but note that we’ve created a new file that we probably do want to put under version control (so if we ever clone this repository it will go along with it):

$ hg status
? .hgignore

$ hg add .hgignore
adding .hgignore

$ hg commit -m "added .hgignore file to ignore some files"
.hgignore
committed changeset 2:0367a3426fc9

hg diff

You can use hg diff to print the diffs between a file in your working directory and the one at the tip of the repository, or using the -r flag between two different revisions, as in the example on the Lecture 2 slides. You can also use xxdiff as done there.

hg serve

If you want a web-page view similar to what bitbucket provides, you can even run your own web server specific to this repository. In a different window (since this will print out stuff to the window and make it hard to work in it), do:

$ hg serve

and then point your web browser to http://localhost:8000/. You should see a log of this directory. Try clicking on one of the commit messages to see the changeset.

To kill the server, type <ctrl>-c in the window where you started it.

If port 8000 is already in use (e.g. you want to serve multiple repositories at once), you can also specify a different port, e.g.

$ hg serve -p 8001

Cloning this repository

Suppose you want to try out a new idea that will require many changes and you don’t want to disturb this directory, which you’re still using for other purposes. (For our simple example, maybe we want to replace the power function with the sine function.)

Then you could make a clone:

$ cd ..
$ hg clone myproject myproject-branch-for-sine
updating to branch default
resolving manifests
getting .hgignore
getting myfcns.py
getting myfcns2.py
3 files updated, 0 files merged, 0 files removed, 0 files unresolved

Now we can go into this version and make the desired change. The new clone is an independent repository that might go off in a different direction, or it might eventually be merged back into the original one.

Removing .hg

Suppose you decide you no longer want a directory to be under version control. For example, you are done debugging and know you will never again want to refer to the past history. Then you could do:

$ rm -r .hg

The -r flag means recursively, so the directory .hg will be removed along with all files in it (and all subdirectories, and files in them, etc.). If rm is set to ask you for confirmation before removing each file, you can force it to remove everything without asking by:

$ rm -rf .hg

Warning

If this is your only copy of the repository (i.e. there are no clones) and you do this, all your revision history is gone forever! Make very sure you are in the right directory first!

This is all you need to do to remove version control, you’re left with an ordinary directory.

Making a copy of a directory

Perhaps you want to keep using version control in myproject, but you want to make a copy of the directory that does not have the .hg subdirectory, for example to turn into a tar file [wikipedia-tar] that you can send to others or post on a website. To do this, simply clone the repository and then go into the clone and remove the .hg directory, leaving a clean copy:

$ cd
$ clone myproject myproject-copy
$ cd myproject-copy
$ rm -rf .hg

Note: Cloning the repository only copies the files committed, not all the files in the working directory that have not been added, or any local modifications not committed.

If you want a copy of all files in the working directory, in their current state, you could instead do:

$ cd
$ cp -r myproject myproject-copy
$ cd myproject-copy
$ rm -rf .hg

Warning

Think twice before any rm -rf operation!