More Fun with Mercurial
More Fun with Mercurial
It doesn't have to be named "myrepo"!
I used a directory named "myrepo" for a demonstration, but you can
use Mercurial in any directory. You can even cd into an
existing directory full of files and start version-controlling it with
Mercurial; just do hg init .. (Remember that in Unix,
. refers to the current directory). All this does is create the
hidden .hg directory where Mercurial tracks the history
of your files, it doesn't change your files in any other way. You'll
still have to hg add each file you want tracked.
You can mix tracked and untracked files in the same directory;
just hg add some and put the names of others in
your .hgignore file, so they don't always show up
in hg status.
Directories, sub-directories, and sub-sub-directories...
If you hg init a directory and turn it into a
Mercurial repo, you can then version-track any files inside that
directory, and inside any sub-directories, on down the chain.
An example
mypages/
- things_to_remember.txt
- mysite/
- index.html
- css/
- style.css
- print.css
- img/
- grimacing_soccer_player.jpg
- anothersite/
- ...
If you cd mypages/ and then hg init
mysite, it will create mypages/mysite/.hg/ (it
would also create the mysite directory if it didn't
already exist).
An example, continued
mypages/
- things_to_remember.txt
- mysite/
- index.html
- css/
- style.css
- print.css
- img/
- grimacing_soccer_player.jpg
- anothersite/
- ...
Then you can hg add index.html, or hg add
img/grimacing_soccer_player.jpg, or cd css
and hg add style.css print.css (or just hg add
*). But you can't add things_to_remember.txt
or anything in the anothersite directory.
Bring out your repos
If you wanted to version control everything, you could of
course hg init the mypages directory
instead, and keep everything in one big repo. But
if mysite and anothersite are
separate sites that you maintain independently from each other, you'd
probably want to manage them as two separate repos with separate
version histories instead.
You can even nest one Mercurial repo inside another; the inner one will manage only the files inside it, of course, and the outer one will completely ignore all the files inside the inner one).
Repos vs working directories
Technically, the repository is just the .hg directory where Mercurial stores all its version-history metadata, and the directory containing it (where your files live) is the working directory. The working directory represents a snapshot of your files at some point in the version history.
- mysite/ <---- working directory
- .hg/ <---- repository
- index.html
- css/
- style.css
- print.css
Time travel, continued
So far, we've always kept our working directory at
the most recent version, or tip. But we can revert to
any previous state with the hg update command.
cd into the working directory where you did last
week's homework. First do an hg status to see if there
are any uncommitted modifications; if there are, do hg
diff to see the changes and then either hg commit -m
'some message' to commit them, or hg revert
filename.py to abandon them. (If you only ever committed a
single change, make some change and commit it so hg log
shows you at least two revisions.)
Time travel
Run hg log, and pick some previous revision. I'll pick 0:
carljm@kale:~/testproj$ hg log changeset: 1:c38c63ca48cc tag: tip user: Carl Meyerdate: Thu Sep 17 16:10:27 2009 -0400 summary: changes changeset: 0:db16fd315f06 user: carljm@dj.goshen.edu date: Thu Sep 17 14:16:09 2009 -0400 summary: first commit
More time travel
Run hg parents to see what revision the working
directory is currently based on; should be the tip (latest)
revision. Then:
carljm@kale:~/testproj$ hg update 0 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
Mercurial tells that one file was changed between the revision I
was at and the one I just updated to. Now hg parents will
tell me that my working directory is based on revision 0; and if I
look at my files, I will see that they are indeed the versions I had
right after my first commit (revision 0). my recent changes aren't
lost, of course; hg log still shows the full history,
and hg update 1 (or hg update tip, or
just hg update) will return me to my most recent
version.
Clean your house before time travelling
If you have uncommitted changes in the files in your working
directory, hg update will try to "carry them along" in
your time travelling, by applying the "same" changes to the older
versions of your file(s). This can be very handy but most of the time
you don't need it: just commit first, or abandon your changes by
providing the -C flag: hg update -C.
Using dj.goshen.edu
$ ssh dj.goshen.edu
It's a (virtual) Linux server dedicated to this class; but it gives
you a Unix-style bash shell, just like on your Macs (or even more like
www.goshen.edu). You have a home directory
in /home/yourname (in place
of /Users/yourname on a Mac), and that's where you are
placed initially when you ssh in (pwd to verify). You can
also ssh into it from off-campus, which will help some of you out.
A new place for homework
First off, mkdir homework to create a directory where
you'll put your homework assignments from here on out. Within it,
create numbered directories for each week's homework (just to help me
find things more easily).
Transferring files using scp
If you need to transfer files to/from dj.goshen.edu:
carljm@kale:~$ scp my_file.txt carljm@dj.goshen.edu:~/some_dir/ my_file.txt 100% 5 0.0KB/s 00:00
Or to pull a file down:
carljm@kale:~$ scp carljm@dj.goshen.edu:~/some_dir/my_file.txt . my_file.txt 100% 5 0.0KB/s 00:00
In both cases, I can leave out the carljm@ if my local username is the same. On a campus machine, it will be, since both are my GC username.
You can also transfer files using any GUI FTP client that supports the SFTP protocol.
But we'd rather use Mercurial!
Rather than copying individual files, you'll often have a Mercurial
repo that you want to keep in sync between two different machines. Or
you keep the primary copy on dj.goshen.edu, but you want to work on it
on a lab Mac, so you don't have to deal with network latency for your
editing. This is where hg clone, hg pull,
and hg push come into play.
hg clone creates a new copy of an existing repo.
hg pull pulls changesets from some other repo into
your current one.
hg push pushes changesets from your current repo into
some other one.
Cloning, pulling, and pushing
Say I've got a local repository on my computer, and I want to create a clone of it on dj.goshen.edu:
carljm@kale:~/testproj$ hg clone . ssh://dj.goshen.edu/newtest searching for changes remote: adding changesets remote: adding manifests remote: adding file changes remote: added 2 changesets with 2 changes to 1 files
. refers to my current directory, which is a Mercurial working directory. The second argument _could_ just be a path to some other (not-yet-existing) directory on my own computer, but in this case I give it an ssh://dj.goshen.edu URL. The path is relative to my home directory, so this will create a copy of my local testproj in a directory named newtest on dj.goshen.edu.
Need to update after clone/push/pull
If I now ssh into dj.goshen.edu and ls
the newrepo directory, it won't have anything in it
except the .hg repo dir. This is because neither hg clone
nor hg push nor hg pull will modify the
working directory; they just copy changesets in the version
history.
In the case of a brand-new clone, this means it has no working
directory contents at all yet, even though all your version history is
there inside the .hg directory. All you need to do
is cd newrepo and then hg update to give
yourself an up-to-date working directory.
hg pull provides a shortcut, hg pull -u
which just performs an automatic hg update after
pulling. It's the only one with this shortcut because it's the only
one that brings new changesets into your current (local) repo.
Make changes locally and push them
In your local repository, make some changes and make a new commit. Then run:
carljm@kale:~/testproj$ hg push ssh://dj.goshen.edu/newtest pushing to ssh://dj.goshen.edu/newtest searching for changes remote: adding changesets remote: adding manifests remote: adding file changes remote: added 1 changesets with 1 changes to 1 files
Again, need to update the remote repo
carljm@dj:~/newtest$ hg log changeset: 2:4970659539b4 tag: tip user: Carl Meyerdate: Thu Sep 17 18:04:14 2009 -0400 summary: more changes changeset: 1:c38c63ca48cc user: Carl Meyer date: Thu Sep 17 16:10:27 2009 -0400 summary: changes changeset: 0:db16fd315f06 user: carljm@dj.goshen.edu date: Thu Sep 17 14:16:09 2009 -0400 summary: first commit
...
carljm@dj:~/newtest$ hg parents changeset: 1:c38c63ca48cc user: Carl Meyerdate: Thu Sep 17 16:10:27 2009 -0400 summary: changes carljm@dj:~/newtest\$ hg update 1 files updated, 0 files merged, 0 files removed, 0 files unresolved carljm@dj:~/newtest\$ hg parents changeset: 2:4970659539b4 tag: tip user: Carl Meyer date: Thu Sep 17 18:04:14 2009 -0400 summary: more changes
And now make changes remotely and pull them
carljm@dj:~/newtest$ emacs file.txt carljm@dj:~/newtest$ hg commit -m 'yet another change' carljm@kale:~/testproj$ hg pull ssh://dj.goshen.edu/newtest pulling from ssh://dj.goshen.edu/newtest searching for changes adding changesets adding manifests adding file changes added 1 changesets with 1 changes to 1 files (run 'hg update' to get a working copy) carljm@kale:~/testproj$ hg update 1 files updated, 0 files merged, 0 files removed, 0 files unresolved
Homework
- Read chapter 3 (and chapters 1 and 2 if you haven't already) of The Definitive Guide to Mercurial, and work through the examples as you go.
- I'll check your homework directory (inside the "week3" subdirectory) in your homedir on dj.goshen.edu and look for the tutorial repositories that show you working through the examples. If you work through the examples on your own computer or a lab Mac instead, just push the sample repositories you created (hello, hello-push, etc) onto dj.goshen.edu using ssh:// URLs as I demonstrated above. Contact me if you have any trouble.