.. _hgex: ============================================================= Mercurial examples ============================================================= For some simple examples elsewhere, see: * ``_ * Other references at :ref:`biblio_hg` 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 -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!