Written by Suman Chakravartula, CS107 TA
You will use Mercurial to manage the projects for your CS107 labs and assignments. Mercurial is a revision control system, which is a tool used by developers to manage the source code in a project. A revision control system does two critical things:
CS107 is not a team project course, so for us, it's about the benefits of #1. Revision control allows you to explore changes while maintaining the option to undo them if they don't work. Saved versions (along with regular testing) makes it easy to pinpoint what code changes are responsible for a new bug so you can focus your attention on fixing the right code. And if you accidentally delete a critical file or munge an important code passage, Mercurial can save the day and retrieve the old version. Without Mercurial, you could attempt to manually track your project history by saving copies of files along the way but this is tedious and error-prone. Instead you'll use Mercurial's handy commands to save/view/retrieve versions. There are many popular revision control systems available (cvs, svn, git, etc.); we chose Mercurial because it has simple commands and is easy to configure, in addition to having a great design that scales to large projects. (read Joel on Software on the beauty of Mercurial)
This quick guide walks you through the essential commands needed for CS107. If you want to go further , there is an entertaining and picture-enhanced tutorial at http://hginit.com/01.html and the official long, super-thorough tutorial at http://www.selenic.com/mercurial/wiki/index.cgi/Tutorial.
Mercurial is installed on the myth
machines, so you need to be working on (or ssh'ed into) one of these machines for the Mercurial commands to be recognized. As a test, try the command
hg --version
Mercurial should respond with "Mercurial Distributed SCM" and a copyright notice.
Before using Mercurial, you must create your personal configuration file. Using any text editor, create a text file named .hgrc
in your home directory (the leading dot in the filename is important!). Add the lines below, substituting your own real name, your sunet, and your preferred text editor (emacs, vim, nano, etc.)
[ui]
editor = emacs
username = Your Real Name <yoursunet@stanford.edu>
After you saved the file, verify the result by asking Mercurial to display your configuration with the command:
hg showconfig ui
The expected response should be:
ui.editor=emacs
ui.username=My Real Name <mysunet@stanford.edu>
Now, you're good to go!
The project and its change history is called a repository. We will set up the initial repositories for your CS107 projects.
Use hg clone
to make a new project from the starter. The first step is to establish your working directory for a project. This step is called cloning--- the starter code is copied or cloned from a central location to create your local working version. The clone command takes two arguments: the path to the repository to clone from and the path of the destination to hold the newly cloned files. The cs107 repository paths are of the form /afs/ir/class/cs107/repos/assignN/sunet
. The following command clones the assign1
project for zelenski
into the new local directory assign1
:
hg clone /afs/ir/class/cs107/repos/assign1/zelenski assign1
The response to this command should look something like this:
updating working directory
2 files updated, 0 files merged, 0 files removed, 0 files unresolved
This created a new directory called assign1
containing the starter files for the project. Within this directory is a hidden directory named .hg
of important Mercurial housekeeping files that you should not delete.
Edit the project files, hg commit
when ready. cd into your new project directory and edit the files normally. When it's a good time (added a feature, fixed a bug, or ready to take a break), commit your changes to save the current revision before moving on. The following command commits changes to the file program.c
(you substitute the name of the file you are committing changes for):
hg commit program.c
If you don't specify a file, all changed files are committed. When committing, you supply a message summarizing the changes and state of the code at this point. Mercurial will automatically open a text editor for you to enter this message when you commit. When you close the editor, your message is stored with the changes being committed. The editor setting in your .hgrc file determines which editor Mercurial opens. By the way, if you exit the editor without entering a message (or only enter lines that start with HG:) Mercurial assumes you changed your mind and cancels the commit (it will warn you the commit didn't go through with a message about abort/rollback). You can also use the optional -m flag to specify the message directly in the commit command and skip using the text editor, like this
hg commit -m "Fixed off-by-one bug" program.c
Use hg status
to list changed files and hg diff
to review changes. At any point, you can compare the files in your working directory with the most recently committed version to review modifications you have made since your last commit. The hg status
command lists the files in your working directory that have as-yet-uncommitted changes.
hg status
The status response is empty if all files are up-to-date; otherwise it lists the files that have been modified (M), added (A), or removed (R).
M Makefile
M program.c
It may useful to review the edits to modified files to ensure the changes are what you intend. The command hg diff program.c
shows the specific changes made to the file program.c. The command hg diff
with no arguments shows changes for all files in the project.
hg diff program.c
In the diff output, a line prefixed with - is one that has been removed, a + is one that has been added. The example diff below shows a one-line change in a printf call.
diff -r d35e4f44da17 program.c
--- a/program.c Mon Apr 06 20:42:53 2009 -0700
+++ b/program.c Mon Apr 06 21:02:03 2009 -0700
@@ -5,7 +5,7 @@
int main (int argc, const char * argv[])
{
- printf("hello world\n");
+ printf("hello cs107\n");
return 0;
}
You can add the optional -r arguments to diff to specify which revisions to compare. By default, diff compares the files in the working directory with the last committed revision.
Use hg log
to review commits. To see the history of changes made to the file program.c
over several commits, type the following command:
hg log program.c
Mercurial responds with information about each previous commit, called a revision or changeset. For each revision, it gives the number, date, and summary message you entered when committing. Consider the following example:
hg log hello.c
changeset: 1:aeb35c8f94f9
tag: tip
user: sumanc@myth34.stanford.edu
date: Mon Apr 06 00:06:47 2009 -0700
summary: Added code to print Hello world
changeset: 0:16fac3b14693
user: sumanc@pod8.stanford.edu
date: Fri Apr 03 18:13:02 2009 -0700
summary: initial commit
Information about more recent revisions is printed before that of older revisions. Above there are two revisions: revision 0 is the initial state when the starter code was cloned, revision 1 has a small update as described in the summary line. The most recent commit has the highest number and is referred to as the tip.
If you need to do more serious trolling through your history, try the command hg view
, which brings up a graphical display of all your commits and allows you to easily browse those revisions and follow the history of changes.
Use hg update
to restore to a previous commit. Mercurial can restore your code to the state at the time of a previously committed revision. A typical scenario is when your latest changes have broken something or your recent work has led you to a dead end, and you wish to backup to a known good state. The following command shows how to restore your project directory to the code committed for revision 3:
hg update -c 3
The lowercase -c flag adds a safety check for uncommitted modifications. If any are found, the update is canceled. You must either commit those changes or discard them. Use hg diff
to view the changes before deciding how to proceed. If you want to preserve those changes in your history, commit so they are recorded. If not worth saving, you can discard by re-invoking update with the lowercase -c
argument changed to uppercase -C
which will throw away all uncommitted changes and overwrite your current files with the specified revision. Uncommitted changes that are discarded are gone forever -- be careful!
The log command provides a list of available revision numbers. Revision numbers start at 0. So if you wanted to start again from the very beginning, the command would be hg update -c 0
. Note that the more regular you are about making commits, the more options you will have if you need to return to a previous revision.
Use hg add
to include additional files. The starter repos we provide will be configured with the appropriate files already tracked, so you will rarely, if ever, need to add new files to the repo. However, if you do you create additional source files, you can use the hg add
command to bring them under revision control. For example, the following commands adds the file myfile.c
to the repository:
hg add myfile.c
A file must already exist before you can add it. Adding only marks the file for inclusion; you must hg commit
to followup and commit the file into the repo. Note that it is not necessary nor recommended to add build products (such as .o or executable files) to the repo. If you accidentally add the wrong file, use hg remove filename
followed by hg commit
to take it out.
Usehg help
to learn more. The commands listed here are likely to be all you need. However, Mercurial has many other features. hg help
will list all available commands and hg help command-name
will provide a description of a particular command. Mercurial is a power tool and using its commands inappropriately can make a mess of your repo, so if you're drawn to experiment with fancy features, we suggest working on test repo or making a backup copy first.
Remmber that submitting a finished project for grading is a separate step. Committing records changes in your local repository, but when finished, you must submit to your class repo for grading!
The CS107 projects are distributed as pre-made Mercurial repositories, but should you ever need to create a repo on your own, it's simple! Simple cd
in the directory where you want to create the repo and use hg init
and hg add
:
hg init
hg add file1.c file2.c Makefile
A repository can end up stuck in a locked state if you previously bailed out midway through a commit. Any attempt to act on a locked repo will fail with an error message like this:
waiting for lock on working directory of assign1 held by 'myth8:17680'
Make a copy of your project directory (as a precaution) and then use the command /afs/ir/class/cs107/tools/unlockrepo
. This script steps you through forcibly breaking the repo lock which should enable you to commit again.
This means the commit was canceled. During a commit, Mercurial brings up an editor for you to enter a commit message. If you exit the editor without entering a message, Mercurial takes the empty message as a sign that you changed your mind and cancels the commit. Also if you prefix your message with HG: (like the lines that are present when the editor is opened), Mercurial will cancel your commit because it ignores the lines beginning with HG: and treats them as empty.