Note: I've just migrated to a different physical server to run Spivey's Corner,
with a new architecture, a new operating system, a new version of PHP, and an updated version of MediaWiki.
Please let me know if anything needs adjustment! – Mike

Mercurial cheat sheet (Object-Oriented Programming)

Copyright © 2024 J. M. Spivey
Jump to navigation Jump to search

This page contains everything you need to know to use the Mercurial version control system for the labs in the Object-oriented programming course. Material for the labs is provided in a public, read-only Mercurial repository.

  • You will begin by cloning the repository into your home directory.
  • Then you can work on the labs by editing the files locally.
  • As you work, you may like to check in your changes to your local repository in order to keep track of what you've done.
  • At any point, you can check the status of files you have changed, view a log of what you have checked in, and compare the state of your work with the checked-in version or with original code provided for the lab.
  • If there are bug fixes or additions to the lab materials during the course, you can get them by pulling and merging changes from the public repository.

One element of a typical workflow is missing in the lab setup: because each person is doing the exercises independently, we omit the step where you push your changes back to the public repository.

The minimum you will need to do is clone the public repository to begin the labs, and produce some diff listings as a major part of the project report. Anything more is entirely optional.

The instructions here assume you are using the command-line interface to Mercurial, and you can cut and paste the commands given here to carry out various tasks. In the labs, we also have the Eclipse plugin for Mercurial installed; you can do the same tasks there by pointing and clicking within Eclipse. It's also useful to know about the TortoiseHG program that you can activate by typing thg& at the shell prompt; this provides an appealing GUI for exploring your repository and carrying out version control tasks. My own preference is usually to have thg open so I can see what's happening, but to make changes to the repository by typing at the command line.

Cloning

The lab materials are provided in a Mercurial repository on my college computer, the same machine that hosts Spivey's Corner. To begin the labs, you should issue the command,

$ hg clone http://spivey.oriel.ox.ac.uk/hg/oop

This will create a directory named oop with subdirectories corresponding to the three lab exercises. Like all commands that interact with Mercurial, this one begins with hg – the chemical symbol for Mercury – and then the name of the specific operation that is needed, in this case clone.

The directory oop created by the clone command contains the subdirectories you can see, plus one hidden subdirectory oop/.hg; it is in this subdirectory that Mercurial keeps a complete copy of the repository that you cloned, together with any changes or additions you make.

Showing status

After you have done some editing, the command

$ hg st .

lists the files under your current directory (".") that do not agree with the latest state of the repository. The output might look like this:

M src/text/Text.scala
? src/text/Hello.scala
? src/text/Text.scala~

This means that the file Text.java has been modifed since the last check-in, and there are files Hello.java and Text.java~ that Mercurial knows nothing about. You can add the new source file to version control by giving the command hg add Hello.scala, and afterwards hg st will show an A in place of the question mark. It's not appropriate to add the backup file Text.scala~, because it is not part of the source code for your program.

If there are no changed since the most recent check-in, then hg st produces no output.

Checking in

If hg st . shows modified or added files in the current directory, then the command

$ hg ci . -m "log message"

will record these changes in the repository. Here log message represents a brief comment you should write, describing the changes you are checking in. Larger projects typically have conventions that demand longer and more explicit comments with every check-in; then it is more convenient to omit the comment from the command line, and have Mercurial start an editor for you to type as long a comment as is needed. But, for us, a few words on the command line are sufficient. (And in any case, a few well-chosen words are infinitely better than no comment at all.)

XKCD #1296

It's a good idea to check in the main part of each lab exercise before starting on the next one, and to check in again when you have finished everything for an exercise. At that point, you can pull and merge any updates that have been made to the lab materials (see below).

Mercurial records your name next to each change you check in, and that means the hg ci command needs to know it. You need to create a file in your home directory called .hgrc and in it put the following text:

[ui]
username = Fred Bloggs <fred@bloggs.com>

(substituting, of course, your real name and e-mail address for the strings Fred Bloggs and fred@bloggs.com). After you've created this file, the unix command ls will not show it, because of the long-standing unix convention that files with names starting with a dot are not listed. But the file does exist, and you can see it listed, together with no doubt 1001 other such hidden files, by giving the command ls -a.

Viewing logs

The command

$ hg log

will show a list of checked-in revisions, starting with the lab materials as you inherited them and showing also any revisions you have checked in. Each revision has a serial number and a hash, displayed in the form 30:21778adbcc91. The serial number, 30, is specific to this copy of the repository, whereas the hash, 21778adbcc91, is globally unique, even if changes are copied with hg pull and hg push between one repository and another; either can be used to refer to the revision in commands like hg diff (see below).

Diff listings

The hg diff command can be used to compare any two revisions of your project or some of its files. The simplest uses are the simple command

$ hg diff .

This compares the current directory in the working copy with the latest check-in. Example output:

diff --git a/EdBuffer.scala b/EdBuffer.scala
--- a/EdBuffer.scala
+++ b/EdBuffer.scala
 −225,9 +225,9 
     }
 
     /** Change that records a deletion */
-    class Deletion(pos: Int, deleted: Char) extends Change {
+    class Deletion(pos: Int, deleted: Text.Immutable) extends Change {
         def undo() { insert(pos, deleted) }
-        def redo() { deleteChar(pos) }
+        def redo() { deleteRange(pos, deleted.length) }
     }
 
     def wrapChange(before: Memento, change: Change, after: Memento) = {

(The lines marked - has been removed and replaced by the ones marked +).

Also useful in the labs is the command

$ hg diff -r basis .

This compares the working copy with the original source code, bookmarked as basis, showing exactly the changes you have made. The bookmark basis is always updated to point to the unmodified source without your changes, even if you have merged in changes to the lab materials after starting work on a lab.

You can show the changes made between two specific revisions by first finding out their serial numbers with hg log (say 21 and 23), then using the command

$ hg diff -r 21 -r 23 .

This is useful for making listings that show just the code needed to do certain parts of the lab exercises, such as in preparing your report on the assessed practical.

Pulling and merging changes

If we need to fix bugs in the lab materials during term, or to add more example programs, then the changes will be added to the public repository for you to pull in and merge with your own changes. If the need arises, we'll help you with the process; but very briefly, the procedure is as follows. First, pull the changes from the public repository into your own. This will not change any of the revisions you've checked in, nor your working copy, but it will make the bugfixes available locally.

$ hg pull

Next, you should check in the work you've done so far, so as to give you a safe place to return to if anything goes wrong.

$ hg ci -m "Checkpoint before merging"

This will probably create a fork in your repository, where one revision (typically the one present when you cloned initially) now has two children, one containing your own work, and the other containing the fixed public materials. You now need to merge these together into a single revision. Mercurial will work out what to do:

$ hg merge

The merged revision is now present in your working copy, and you should check it in.

$ hg ci -m "Merged bugfixes from public repository"

Now you can resume your work with the bugs fixed.