Copyright © Cay S. Horstmann 2010, 2012
This work is licensed under a Creative Commons
Attribution-Noncommercial-Share Alike 3.0 United States License.
hg
init
).hgignore
, hg add
, hg remove
)hg commit -m
"..."
)hg serve
, point
browser to http://localhost:8000
)hg clone
, hg
push
, hg pull
)hg update
, hg merge
) and
resolve conflictsEstimated time: Two lab sessions
Using your own Linux? Open a terminal window and run
sudo apt-get install openssh-client mercurial
(or the equivalent for your distro)
Then open a terminal window and run
sudo port install mercurial
This will take a long time.
Or, if you don't want to install XCode and MacPorts, just use the Linux virtual machine.
Run the Cygwin setup program (download it again if you didn't save it when you installed Cygwin). Click Next until you get to the Select Packages screen. In the Search dialog, type mercurial.
Select it for installation by clicking on the circle next to Skip. A version number will appear.
Don't click Next yet. Locate openssh and select it for installation in the same way.
Click Next and wait for the installation to complete.
To test that your installation was successful, open a terminal window and type
hg --version
If you get a version number and copyright notice, the installation was successful.
~/.hgrc
(that is a file with the five-character
name .hgrc
in the home directory ~
). Be sure to
remember the dot at the start of the file name.
Windows users: Remember that ~ is
c:\cygwin\home\yourname
in the Windows file system.
Windows users: Don't type ~
in EmacsW32. It
interprets it as the Emacs home directory.
Add these lines:
[ui] username=Your name <username@mailserver.com> merge=internal:merge
(of course, replacing Your name
with your name and
username@mailserver.com
with your email address).
ls ~/.ssh
If you get a directory listing showing (among others) a file
id_rsa.pub
, then skip to step 5.
Otherwise run
ssh-keygen -t rsa -C "Your name <username@mailserver.com>"
(of course, replacing Your name
with your name and
username@mailserver.com
with your email address). When
prompted for a passphrase, you can enter a passphrase, which is more
secure, but you have to enter it whenever you use the key. Or just hit
Enter to skip this.
Do not change the name of the key that is being generated. It
should be id_rsa
.
cat ~/.ssh/id_rsa.pub
Copy the text (starting with ssh-rsa
and ending with
Your name <username@mailserver.com>
and paste it into an
email message to your instructor. This key is needed to allow you access to
the Mercurial server (in Step E).
A version control system remembers the changes that you made to the files in a project. This is useful (even essential) for two reasons:
The database that contains the changes to a project is called a repository. When you interact with a version control system, you contribute your changes to a repository, fetch the latest changes that are contributed by others, or occasionally undo some changes.
Many version control systems are in common use. In this lab, you will learn about a modern version control system called Mercurial. Mercurial is particularly well suited for learning about version control systems. It is so easy to use that it is painless to set up a local repository on your hard disk, but it scales to extremely large projects. For example, the source code for the Java development kit is contained in a very large Mercurial repository.
Open a terminal window and use the cd
command to change to
the directory containing the project. (That is, the directory containing
the src
and nbproject
subdirectories.)
Using a text editor (not Notepad!), create a file .hgignore
in that directory with the following contents.
syntax: glob build dist nbproject build.xml manifest.mf
Now run
hg init hg status
What output do you get?
Windows users: If you get errors about unavailable resources, try the "rebaseall" procedure described in this thread. Or switch to using the Linux virtual machine and repeat the steps starting from part A.
hg
command interacts with a Mercurial repository. (Hg is
the chemical symbol for the element
Mercury.)
The hg init
command initializes a repository. You
issue it once when you start a project, or when you decide to add version
control to an existing project.
The hg status
command shows the current status of the files
in your project. At the beginning, you get a listing such as
? .hgignore ? src/AddressBook.java ? src/AddressBookDemo.java ? src/ArrayListAddressBook.java ? src/ConsoleInOut.java ? src/InOut.java ? src/Item.java ? src/WindowInOut.java
The ?
indicates that these files are unmanaged.
Tell Mercurial that you want to add them:
hg add
This command adds all files in all subdirectories that are not excluded
in the .hgignore
file.
Now run hg status
again. What output do
you get?
Occasionally, you need to remove files and tell Mercurial
that you don't want them to be a part of your project anymore. Then you use
the hg remove
command. The moral is: Mercurial doesn't
automatically manage every file in your project directory. You tell it
which ones you want to save.
A
next to each file means that these files will be added
when you make the next “commit” to the repository. Do it now:
hg commit -m "initial checkin"
The -m
option is required. Put a brief message describing
the reason for the commit. (You usually commit after adding a feature or
fixing a bug.)
Some people like to put longer commit comments, describing the commited change in detail. That is best done from an IDE—see Part C.
Now run hg status
again. What output do
you get?
hg status
has nothing to report, then all files are
up-to-date.
Edit the file src/AddressBook.java
in NetBeans. Make some
change; for example, remove the first javadoc comment. Save the file.
Now run hg status
again. What output do
you get?
M
indicates that the file has been changed and is
different from the version in the repository.
Run hg commit
again. Now the repository contains both the
original version and your latest changes.
To see the difference between them, run
hg serve
and point your web browser to http://localhost:8000.
What happens?
Windows users: If you don't see the repo, your firewall probably blocks port 8000. If you don't know how to control your Windows firewall, switch to using the Linux virtual machine and repeat the steps starting from part A.
src/AddressBook.java
file.
How can you get it without the line numbers?
If you ever need the old file back, you can copy/paste it
from the browser, or you can use the Mercurial revert
command.
That is more convenient inside NetBeans—see section C.
You have just seen one reason to use a version control system: To get an old version of a file back. It's as if your file system had an undo button!
(But remember, you must enable the undo by periodically running hg
commit
. You can only revert to committed versions.)
Hit Ctrl + C to stop the hg serve
process.
find
You will see the src
subdirectory containing your files,
and next to it, a .hg
directory containing the repository
data.
Windows users need to install a separate Mercurial implementation from http://bitbucket.org/tortoisehg/thg-winbuild/downloads/ before this part of the lab. Just download and run the installer. (Unfortunately, NetBeans does not work with the Mercurial program in Cygwin.)
If not, try these things:
hg
executable, c:\Program Files\Mercurial
on Windows or
/opt/local/bin
on the MacIf all else fails, ask your lab assistant or instructor for help.
@author
). Save your file and look at the Projects tab.
What do you notice about the file name?
It lists the file(s) that have changed and you can type a commit message that is as detailed as you like.
Type an appropriate message and click Commit.
When you add files, they show up in green. NetBeans
automatically issues an hg add
before committing them.
Once in a while, you may want to know how one of your local files differs from the repository.
Make a change to InOut.java, such as adding a comment explaining the purpose of the interface. Then right-click on the file in the Projects tab and select Mercurial -> Diff. You will see a graphical display of the differences.
How do you get back an older version?
(Try it out. First commit the current version, just in case you mess up, then try reverting to an older one.)
As a rule of thumb, it is a good idea to use the command
line for “big ticket” commands, such as hg init
and hg clone
. (Lots of things can go wrong with these, and the
IDE often hides the error messages, making it hard to diagnose what is
going on.) Common commands such as hg commit
and hg
revert
are most convenient in the IDE.
If you use the Linux virtual machine, you need to click on the USB icon at the bottom of the VirtualBox page and select your USB device.
Type
hg clone . /path/to/USBStick/lab6
(assuming you are still in the lab6
project directory;
otherwise type hg clone /path/to/courseDirectory/lab6
/path/to/USBStick/lab6
).
The path to the USB stick depends on your operating system.
/media/someName
or /media/sdf1
or
something similar (try ls /media
to see your choices)/Volumes/someName
or /Volumes/NO\ NAME
(try ls /Volumes
to see your choices)/cygdrive/someLetter
such as
/cygdrive/e
(try ls /cygdrive
to see your
choices)Then verify that a lab6
directory has been created on the
USB stick.
This directory is now a “clone” of your project.
First, your fellow developers need a copy of the master.
Inserts the USB stick into your buddy's laptop.
Clone the repository onto that laptop:
hg clone /path/toUSBStickOnBuddyLaptop/lab6 /path/to/buddysCourseDirectory/lab6
Your buddy starts NetBeans and makes a Java project with the files in
/path/to/buddysCourseDirectory/lab6
.
@author Your Name
.@author Your Buddy's Name
.cd /path/to/buddysLabDirectory/lab6 hg push /path/toUSBStickOnBuddyLaptop/lab6
Now your buddy's changes are on the USB stick.
Windows users: If you get errors about ”waiting for lock”, try removing a lock file, as described in this thread. Or switch to using the Linux virtual machine and repeat the steps starting from part A.
hg pull /path/to/USBStick/lab6
What happens?
But the second set isn't yet applied to your files. Type
hg update
to update your files.
Now run hg status
again. What output do
you get?
hg update
command modified a file, but that change isn't
yet permanent.
What command do you use to tell the repository that you accept the change?
hg push /path/to/USBStick/lab6
Now your changes are on the USB stick.
How does your buddy get your changes?
This scenario illustrates an important rule: Always pull before you push. If you push your changes without first pulling other changes, the shared repository (and not just yours) will contain multiple change sets (or multiple “heads” in Mercurial speak). Multiple heads aren't good, and it is harder to fix them on the shared repository than yours.
Whatever you do, do not use
the -f
or --force
option. Then you are guaranteed
to create multiple heads, and everyone will hate you. Here's what Joel Spolsky has to say about
that:
AddressBook.java
and adds a line
@author
Your Buddy's name
, followed by
hg commit "Added @author tag" hg pull /path/toUSBStickOnBuddyLaptop/lab6 hg update hg push /path/toUSBStickOnBuddyLaptop/lab6
You take the stick back, edit AddressBook.java
and add a
line @author
Your name
, followed by
hg commit "Added @author tag" hg pull /path/toUSBStick/lab6
What happens?
hg update
. Instead, a human needs need to make a decision how
the change sets should be merged. Run
hg merge
Then look inside AddressBook.java
.
What happens?
<<< === >>>
symbols are
“conflict markers” that point you to the part of the code that
you need to fix.
Edit the file so that it becomes
@author Your name, your buddy's name
What do you do to save your changes to the shared repository?
Conflict markers sound scary, but experience has shown that they are quite rare in practice. Most of the time, team members don't edit the same part of a file, and merging works without generating conflicts. And when conflicts occur, they are usually easy to resolve.
In this part, you will retrieve a repository from a server, make some changes, and save your changes on the server.
You can only do this part if you have sent your public key to your instructor and it has been installed in the server.
Issue this command to get the repository:
cd /path/to/courseDirectory/lab6 hg clone ssh://hg@cs13.cs.sjsu.edu:62222/sandbox
Where is the repository clone located?
You should not get a password prompt. If you do, that means that the SSH authentication has failed. Here are debugging tips. (Skip them if you were able to clone the repo.) First be sure that your lab instructor has placed your public SSH key on the server. Then run
ls -al ~/.ssh
The .ssh
directory should have permission
drwx------
and the file id_rsa
should have
permission -rw-------
.
Run
cat ~/.ssh/id_rsa.pub
and have the lab instructor check that this file is present on the server.
Run
ssh -v -p 62222 hg@cs13.cs.sjsu.edu
and have the lab instructor check for any anomalies in the debug messages.
sandbox/yourname.txt
(using your name, of course, not yourname
, unless you have the
misfortune of having the name “Yourname”). Put in some text
about yourself, something like
Hi, my name is Yourname Jones--which isn't a fun name to have. That's why friends call me Why Jay. I live in Drawbridge and am a computer science student at SJSU.
Don't copy this—put some information about yourself.
Save the file.
Now
ssh://hg@cs13.cs.sjsu.edu:62222/sandbox
What commands did you use?
It is quite likely that you need to pull
and
update
before you can push
.
ssh://hg@cs13.cs.sjsu.edu:62222/sandbox
.
What other files did you get?
You now know enough about Mercurial to manage your personal projects and small team projects. Once you are more comfortable with the basics, check out the tutorial at http://hginit.com/ that gives a very nice background explanation in the inner workings of Mercurial.