Mercurial is a Version Control System that stores all the versions locally while many VCSs rely on the internet to store older versions of the files. It allows users to revert to previous versions of files if necessary as well as collaborate asynchronously on projects and merge their results.
I recommend the Lynda.com videos on the fundamentals of version control if you need help understanding where version control fits in the grand scheme of things. The Institute pays for a subscription to this amazing resource (Lynda.com) and makes it available for anyone in the MIT community. For those who don't have access to that resource, this series on youtube also offers a good introduction
Open a terminal window (/Applications/Utilities/Terminal) and type:
If it returns something similar to:
Mercurial Distributed SCM
It means you have Mercurial already installed. If not, follow the instructions below to install Mercurial:
First, check which operating system version you are using by navigating to the top left corner of your screen and click on:
> About This Mac > Version 10.X
Now, get the version of python that you're using by typing the following in a terminal window:
With this information, go to http://mercurial.selenic.com/downloads and select a version that matches both your Mac OS and Python versions. Pay particular attention to the filename linked to by the different download links as they contain the python version in them but are not otherwise written explicitly on the website. An example of a filename is:
Indicating that this installation package of Mercurial is expecting python 2.7 and OS X 10.8
SSH is a secure communication mechanism that relies on asymetric encryption (also called public-key cryptography). The authentication mechanism uses a public key to decrypt the server's messages and a private key to prove to the server that we are allowed to communicate. This means that we must ensure that the private key file stored on your computer is adequately protected from unauthorised users. This is done through changing the key file's permissions (see Terminal commands section below).
The first thing we need to do is to obtain the keys for the archive you want to use, which in this case are distributed by Neil via email to the accepted students. This will contain two files: classes and classes.pub. The former being the private key and the latter being the public one. We now need to place them in a logical directory located in ~/.ssh/keys. Let's first check that the directory exists:
If the directory doesn't exist, you can create it by using the following command:
Now that we have the folder created, copy the archive keys you're going to use into the folder. You can do this in many different ways. The simplest is probably to open a finder window and drag and drop the key files into the folder. Because folders that start with a . are hidden folders on UNIX operating systems, you can use the command line to open the finder to the correct location:
Alternatively, you can use the copy command to copy the correct files. Remember you can use wildcards like * to copy multiple files at once
As discussed in the SSH overview above, we need to make sure the keys have the correct permissions set, otherwise it represents a risk and SSH won't let you connect to the archive. Let's check the permissions of the files in the Keys folder:
ls -la ~/.ssh/keys
Permissions for the .pub key(s) should be:
and permissions for the private key file(s) should be:
This is unlikely to be the case right out of the box. So type the following commands to respectively change the public files in the folder:
chmod u+rwx *.pub
chmod go+rx *.pub
chmod go-w *.pub
and the private file of interest, in this case classes:
chmod u+rw classes
chmod go-rwx classes
In order to create a script that will automate the process outlined above, we will need to create a program in the correct folder. In this example, I will use the /usr/bin folder to store our script. Please read the note about this folder on the side if you want to use a less essential folder. Because of the folder's importance for the system, we need to use super-user privileges to be able to write our script to the folder:
sudo nano /usr/bin/hgclone
An interface appears in your terminal. Copy and Paste the following script:
#!/bin/bash # if [ $# -ne 6 ]; then echo "$(tput bold)$(tput setaf 9)Incorrect use of the HgClone script. Please use it thusly: $(tput sgr 0)" echo "$(tput bold)hgclone $(tput setaf 10)archive_name $(tput setaf 11)archive_key $(tput setaf 12)archive_server $(tput setaf 13)server_port $(tput setaf 14)\"user name\" $(tput setaf 15)user@email_address$(tput sgr 0)" echo "" else echo "$(tput bold)$(tput setaf 14)HgClone Custom Script v2$(tput sgr 0)" echo "$(tput bold)$(tput setaf 10)Running clone command$(tput sgr 0)" cmd="hg clone -v -e 'ssh -p $4 -i ~/.ssh/keys/$2' ssh://hg@$3/$1 $1" eval $cmd echo "$(tput bold)$(tput setaf 2)Modifying mercurial local configuration file$(tput sgr 0)" cmd="echo -e '\n[ui]\nssh = ssh -p $4 -i ~/.ssh/keys/$2\nusername = $5 <$6>' >> $1/.hg/hgrc" eval $cmd echo "$(tput bold)$(tput setaf 2)Done$(tput sgr 0)" echo "" fi
To save the script and exit the nano text editor, press Ctrl-X, confirm (using the Y key and Enter). You should now be back to the terminal. Try executing the script you just saved by doing:
It should complain that you didn't run the script with the correct arguments. Now, all that should be left for us to do is run the script.
If you have other issues running the script, check that you have execute (u+x) permissions on the hgclone file (/usr/bin/hgclone) using the
ls -la command.
An example of the hgclone command would be:
hgclone 863.13 classes fab.cba.mit.edu 846 "Charles Fracchia" email@example.com
Alternatively, you can download the script and move it to the correct folder using:
sudo mv ~/Downloads/hgclone /usr/bin/hgclone
You will still need to ensure that the permissions include the ability to execute. You can add the execution permission using:
sudo chmod +x /usr/bin/hgclone
Now that we have the SSH keys configured correctly, we need to clone the archive to our local computer. Because the command is a little long, some people prefer to automate the process by creating a custom script. Please see that section if you want to go that route. Otherwise, use the command below and replace with your relevant settings.
hg clone -v -e 'ssh -p port_number -i ~/.ssh/keys/private_key_file' ssh://hg@server_location/archive_name local_folder_path
An example of this command being used to clone the How to Make (Almost) Anything Class archive for 2013 (xxx.13):
hg clone -v -e 'ssh -p 846 -i ~/.ssh/keys/classes' ssh://firstname.lastname@example.org/863.13 HTMaA
Now that we've cloned the archive, we need to configure the archive's specific settings
The archive settings are store in a hidden directory (starts with a .) within the repository
Using your favorite editor, edit (you may need to create it if it doesn't exist) the following file within your repository:
and make sure the content is:
[paths] default = ssh://email@example.com/863.13 [ui] ssh = ssh -p 846 -i ~/.ssh/keys/classes username = Firstname Lastname < firstname.lastname@example.org> editor = mate [extensions] convert = fetch = [hooks] changegroup = hg update >&2
Make sure on the SSH line, you have the correct path to the private key that was distributed by email.
This one is easy. The command is below.
Don't forget to incorporate the pulled changes into your local directory:
Occasionally when your version clashes with the one you are trying to update, you might get an error telling you there are outstanding changes or that you need to merge. See the merging section below on how to do that.
The first thing you need to do when adding changes to the archive is to check the status of the archive using the following command:
This should return a list of the files like the one below:
M people/charles.fracchia/vcs.html ? people/charles.fracchia/about.html
The M flag represents a file that is tracked by mercurial but has been modified since the last commit. The ? flag means that the file is not being tracked by the version control system.
In this case, I recently created this about.html page, and want to include it in the next commit. To do that, I use the command below:
hg add people/charles.fracchia/about.html
Re-running the status command should now show that the file will be added to the next commit:
M people/charles.fracchia/vcs.html A people/charles.fracchia/about.html
If afterall you change your mind and don't want to include the file to the next commit use the forget command:
hg forget people/charles.fracchia/about.html
Committing in mercurial is akin to creating a snapshot in time of your archive. You could refer to this as a version of your archive. Once you have selected the files that should go into your commit (see Adding and Forgetting section), you can commit your version by using the following command:
hg commit -m "Your commit message"
Try to be descriptive in your commit message, it will be extremely helpful when you have to look back and understand what was done.
Merging occurs when you have two parrallel branches of development that need to be unified. This often happens when you have been offline (aka haven't pulled and updated your archive) in a while and changes have been made in parallel. Sometimes, these changes will conflict with eachother and you will need to actively choose which changes to keep and which you throw. I will not be explaining how to do this, there is a good guid on this here.
In order to merge your changes into the current head commit type:
As mercurial suggests after the merge command, don't forget to commit that merge into a version. I often use an explicit comment to show this specific merge:
hg commit -m "Merging"
Pushing to the archive uploads your commit history to the server. This means that you can make intermediary versions (and encouraged) as you go along, even if you can't reach the server. Once you restore your ability to connect to the mercurial repository server, you can upload your changes using:
|pwd||Give the path of your current directory||pwd
|open dir||Open the directory dir in Finder. ".." goes one level up in the folder structure. "." means the current folder.||open .|
|cd dir||Change the current directory to dir||cd ..|
|ls options||List the contents of the current directory. If you put a path in the options, it will list the contents of that path. Adding "-la" will list the hidden folders||ls -la
-rw-------@ 1 username staff 1675 Sep 12 23:57 classes
|chmod User Group Other+/-Read Write eXecute file_path||Change the permissions on the file||chmod go-rx file
Would remove read and execute rights from group and other on file
|cp original_file target_file_location||Copy original_file to target_file||cp ~/Desktop/classes.pub ~/.ssh/keys/classes.pub
Would copy the classes.pub file from the desktop to the ssh keys folder
|sudo command||Execute command with superuser privileges||sudo chmod ugo+rw protected_file
Would change the permissions of the protected file to be readable by all (user, group and other)