mirror of
https://github.com/xen-project/xen.git
synced 2026-10-28 02:01:24 +01:00
Add the Mercurial for Xen cheatsheet into the repo.
Signed-off-by: ian@xensource.com
This commit is contained in:
1 parent
a640c9b437
commit
dbf7e82d46
1 file changed
+422
@@ -0,0 +1,422 @@
|
||||
|
||||
Mercurial(hg) Cheatsheet for Xen
|
||||
================================
|
||||
|
||||
Written by Andrew Warfield, extended by Michael Fetterman and Ian Pratt
|
||||
June 29, 2005
|
||||
|
||||
Overview
|
||||
--------
|
||||
The Xen project has moved from BitKeeper to Mercurial for source
|
||||
control. This note aims to provide a quick guide to getting up and
|
||||
running with the new tools as quickly as possible, and is written from
|
||||
the perspective of someone who has been using BK.
|
||||
|
||||
For a more detailed exposition, see the mecurial tutorial:
|
||||
http://www.serpentine.com/mercurial/index.cgi?Tutorial
|
||||
|
||||
The Hg manpage is available at:
|
||||
http://www.selenic.com/mercurial/hg.1.html
|
||||
|
||||
There's also a very useful FAQ that explains the terminology:
|
||||
http://www.selenic.com/mercurial/FAQ.html
|
||||
|
||||
There's also a good README:
|
||||
http://www.selenic.com/mercurial/README
|
||||
|
||||
Necessary software
|
||||
------------------
|
||||
Mercurial is available at:
|
||||
http://www.selenic.com/mercurial/
|
||||
|
||||
You will also need a Python version >= 2.3
|
||||
|
||||
How Mercurial is different from BK
|
||||
----------------------------------
|
||||
There are several pertinent differences between hg and bk. This
|
||||
section aims to give an overview of the conceptual differences between
|
||||
the two SCMs -- if you just want examples to get going, skip ahead to
|
||||
"Getting Xen". The key differences are:
|
||||
|
||||
- No explicit per-file locking. You do not need to explicitly
|
||||
check a file out before editing it.
|
||||
- No notion (currently) of file renames.
|
||||
- A repository can have multiple active heads.
|
||||
- Automatic merge support is currently inferior to BK's.
|
||||
- No graphical tools.
|
||||
- No per-file revision history, only per-changeset (we never really used this anyhow)
|
||||
- Hg repositories tend to be rather bigger than Bk ones, but Hg does seem faster.
|
||||
|
||||
Mercurial is based on the notion of changesets as complete, immutable,
|
||||
versions of the repository. You make changes to a working version of
|
||||
the repository that is based on a particular changeset. When you
|
||||
commit, you will generate a new child changeset with whatever changes
|
||||
you choose to apply.
|
||||
|
||||
A major difference between Hg and BK is that you aren't forced to
|
||||
resolve conflicts immediately: BK forced you to resolve conflicts
|
||||
immediately on any merge, and it then immediately created a changeset
|
||||
with those conflicts' resolutions. Frequently, you then had to add
|
||||
yet another changeset to fixup the things for which the automatic
|
||||
merge yielded bad results. Hg puts the results of the merge into your
|
||||
work directory, and remembers what you merged with (so that it can
|
||||
later record both of the merge parents, if you decide to make a
|
||||
changeset), but it doesn't immediately create a changeset.
|
||||
|
||||
A further feature of Hg is that it allows a repository to have
|
||||
multiple heads. This means that you can have changesets with no common
|
||||
descendent in one repository -- something BK won't allow. This is
|
||||
actually pretty neat. For example, it would in principle enable you to
|
||||
have both the 2.0-testing and unstable trees in a single
|
||||
repository. We shyed away from doing this as we thought the risk of
|
||||
commiting to the wrong head was too great.
|
||||
|
||||
One slightly confusing aspect of Hg is that many of the commands have
|
||||
aliases, and hence when looking things up in the man page its not
|
||||
always obvious what the underlying command is. For example 'co' is
|
||||
actually an alias for the 'update' command, but 'co' seems to make
|
||||
more sense, at least to RCS refugees like me.
|
||||
|
||||
|
||||
Getting Xen
|
||||
-----------
|
||||
|
||||
The URL for the mainline Xen mercurial respository is:
|
||||
|
||||
http://xenbits.xensource.com/xen-unstable.hg
|
||||
(similarly for xen-2.0 and xen-2.0-testing)
|
||||
|
||||
You can point a browser and this and use Hg's web interface to view
|
||||
revision history, or use it as the nominated source when issuing
|
||||
"hg init" or "hg pull" commands.
|
||||
|
||||
However, to avoid taxing the Mercurial server with a complete pull of
|
||||
the Xen repository, it is best to download a tarball of a seed
|
||||
repository from:
|
||||
|
||||
http://www.cl.cam.ac.uk/Research/SRG/netos/xen/downloads/xen-unstable.hg.tar.gz
|
||||
|
||||
Untar the repository on your disk, cd into it, and then pull the most
|
||||
recent changes:
|
||||
|
||||
hg pull -u
|
||||
|
||||
By default hg does not automatically checkout ('update') files from
|
||||
the repository as used to happen with bk. The above is equivalent to
|
||||
"hg pull; hg co"
|
||||
|
||||
The repository parent is stored in a repository configuration file,
|
||||
.hg/hgrc, from the repository root. If you look at this file, you
|
||||
will see:
|
||||
|
||||
| [paths]
|
||||
| default = http://xenbits.xensource.com/xen-unstable.hg
|
||||
|
||||
"default" specifies the appropriate parent repository for hg to pull
|
||||
from. Hg allows you to pull additional repositories, for instance if
|
||||
you want to work between unstable and testing concurrently.
|
||||
|
||||
The command "hg pull" simply adds changesets to your repository,
|
||||
without any merging of any kind. "hg pull -u" implies merging with
|
||||
the current state of your working directory. If you weren't already
|
||||
"updated" to your local repository's tip, you might be surprised to
|
||||
find yourself merging the results of the pull with a non-tip node in
|
||||
your local repository.
|
||||
|
||||
|
||||
Revision History
|
||||
----------------
|
||||
|
||||
You can view the repository revision history with:
|
||||
|
||||
hg history
|
||||
|
||||
In practice, you'll probably want to use pipe the output through
|
||||
'head' or 'more' as it prints the entire history.
|
||||
|
||||
Looking at the first few lines of output, you can see the changeset at
|
||||
the head of the current branch, known as the 'tip' (the tip is
|
||||
automatically given a special tag to make it easy to refer to):
|
||||
|
||||
| changeset: 5599:6cbf9ec05cd9e05c0c46a85df7fc00262633cd3d
|
||||
| tag: tip
|
||||
| user: kaf24@firebug.cl.cam.ac.uk
|
||||
| date: Tue Jun 28 18:47:14 2005
|
||||
| summary: bitkeeper revision 1.1768 (42c18d2259NPELcGV7ohyZNh72ufSw)
|
||||
|
||||
By default, Hg just shows the first line of the changset comments. You
|
||||
can find further information with "hg -v history".
|
||||
|
||||
The changeset identifier has two parts, a _local_ monotonically
|
||||
increasing changeset id, 4792 above, and a _global_ hash, which
|
||||
follows the colon on the changeset line. The hash uniquely identifies
|
||||
the changeset and its lineage back to the root of the changeset tree
|
||||
-- it is useful for distributed management and so on. However, as it
|
||||
is a bit unruly, the local id will allow you to work easily with the
|
||||
local repo. Hg commands will take either identifier. Additionally, a
|
||||
tags mechanism lets you give common names to specific changesets.
|
||||
|
||||
You should always use the global hash when referring to versions of
|
||||
the mainline Xen respoitory. With Bk you could often get away with
|
||||
using the shortform version, but with Hg the local ids are pretty much
|
||||
guaranteed to be different.
|
||||
|
||||
|
||||
Creating a child repository from an existing repository
|
||||
-------------------------------------------------------
|
||||
If you wanted to create additional local child repositories,
|
||||
|
||||
hg init [path or url]
|
||||
|
||||
is effectively equivalent to bk clone. The major difference is that
|
||||
it should be run from the root of your new repository. So:
|
||||
|
||||
bk clone /foo/bar
|
||||
|
||||
would be replaced with:
|
||||
|
||||
mkdir bar
|
||||
cd bar
|
||||
hg init /foo/bar
|
||||
|
||||
NB: newer version of Hg support a 'clone' command that works in the
|
||||
same manner as bk.
|
||||
|
||||
Editing files
|
||||
-------------
|
||||
|
||||
Normal edits may be made in place. File creation needs explicit
|
||||
marking, though deletes should be picked up automatically
|
||||
|
||||
creation:
|
||||
|
||||
touch a (or otherwise created a file)
|
||||
hg add a
|
||||
|
||||
You can see what has changed using:
|
||||
|
||||
hg status
|
||||
|
||||
| C foo/foo.c
|
||||
| R foo/bar.c
|
||||
| ? a.txt
|
||||
|
||||
This shows that in the current repo, foo.c has been changed, bar.c has
|
||||
been deleted, and a.txt is new, but has not been added. '?' changes
|
||||
to 'A' after "hg add a.txt". There is a .hgignore file which contains
|
||||
regexps of files that should be ignored when scanning for new
|
||||
files. We try to ensure that all the generated files in a build are
|
||||
covered by the regexps.
|
||||
|
||||
You can add all the new files in a repository with "hg addremove". If
|
||||
you discover that you've added a file you didn't want, you can remove
|
||||
it from the list of files to be included in the next commit using
|
||||
"hg forget".
|
||||
|
||||
Committing changes
|
||||
-----------------
|
||||
|
||||
After you've checked that hg knows about any new files you've created,
|
||||
you probably want to see a diff of what you're about to commit. You
|
||||
can do this with:
|
||||
|
||||
hg diff
|
||||
|
||||
Once you're happy with what you have, invoke:
|
||||
|
||||
hg commit
|
||||
|
||||
This will pop up an editor with a list of files to be committed to the
|
||||
repository. It will look vaguely like this:
|
||||
|
||||
|
|
||||
| HG: manifest hash 6397b04bd5c2a992482d973b685a7e5e498788e7
|
||||
| HG: changed doc/thesis/new.tex
|
||||
| HG: removed doc/2005-hotdep-protection/paper.tex
|
||||
|
||||
Your comments can go anywhere in this file. The first line is the
|
||||
most important, as it will show as the changeset description in
|
||||
non-verbose-mode history listings.
|
||||
|
||||
You can do commits without the editor and of partial sets of files
|
||||
using command-line switches. See:
|
||||
|
||||
hg help commit
|
||||
|
||||
You can use the -A (--addremove) flag to commit e.g. "hg -A commit" to
|
||||
ask mercurial to scan the tree looking for newly created files to add
|
||||
in to the changeset. This avoids having to explicitly use "hg add",
|
||||
but you probably want to be careful of adding any new generated files
|
||||
too.
|
||||
|
||||
|
||||
Generating a patch
|
||||
------------------
|
||||
Generating a patch is easy,
|
||||
|
||||
hg export [changeset]
|
||||
|
||||
will generate a patch describing the diff between that changeset and
|
||||
its parent.
|
||||
|
||||
Pushing changesets to a parent repository
|
||||
-----------------------------------------
|
||||
|
||||
hg push
|
||||
|
||||
Pushes changes up to a parent. You can't push if you pulled the
|
||||
repository off the web interface. In fact, you can currently only push
|
||||
to an ssh target -- filesystem drectory targets don't work, but this
|
||||
will be fixed soon.
|
||||
|
||||
|
||||
Repository history
|
||||
------------------
|
||||
|
||||
Here are a collection of common commands to get you started:
|
||||
|
||||
hg history | less
|
||||
|
||||
shows the history of changesets, starting from the most recent. You
|
||||
want to pipe it to some sort of pager. For more complete details,
|
||||
|
||||
hg -v history | less
|
||||
|
||||
will include files modified and full (not just first-line) comments.
|
||||
|
||||
Additionally, you can see just the tip (head of the current
|
||||
branch) of the repository by typing:
|
||||
|
||||
hg [-v] tip
|
||||
|
||||
|
||||
Moving to a specific changeset
|
||||
------------------------------
|
||||
|
||||
The co command lets you change the working version of the repository
|
||||
to a different changeset.
|
||||
|
||||
hg co [changeset]
|
||||
|
||||
NB: 'co' is an alias for 'update'
|
||||
|
||||
This command enables you to rewind the working repository to previous
|
||||
changesets, for example to isolate the changeset in which a bug is
|
||||
introduced.
|
||||
|
||||
If you try and do a 'co' but have modified files in your repository Hg
|
||||
won't let you unless you ask it explicitly to merge the checked out
|
||||
version into the current tree using the "-m" option. The "-C"
|
||||
(--clean) option will force overwrite any locally modified files.
|
||||
|
||||
Any commits that are made to non-head changesets will obviously fork
|
||||
the tree, creating a new head. You can see all the heads in a tree with
|
||||
"hg heads".
|
||||
|
||||
In general, "hg co" does the right thing, although it doesn't
|
||||
currently seem to clean up unused directories that have been created
|
||||
by other checked-out versions. This can confuse the Xen build
|
||||
system. Hg will probably get fixed soon, but in the meantime you can
|
||||
cleanup with "find -depth -type d -print | xargs -r rmdir".
|
||||
|
||||
You can return to the tip by ommiting an explicit changeset id.
|
||||
|
||||
The manifest command lets you see the contents of the repository for
|
||||
the current changeset.
|
||||
|
||||
hg manifest
|
||||
|
||||
This will print a bunch of records of the form:
|
||||
|
||||
| 98856c45c35a504bc6da06a62b7787ddfdfd1c8b 644 COPYING
|
||||
| f28971eedc5b54e7a9b26dd18d52992955354981 644 Config.mk
|
||||
| a3575cc4db59e50bbac8a039a0c74f081a8dfc4f 644 Makefile
|
||||
| 7fc869aae2945a9f4626fad96552db3103e61cb9 644 README
|
||||
| ...
|
||||
|
||||
This lists the hash of each file, its 1-bit 'executable' atribute
|
||||
(either file permission mode 644 or 755), and the file name. So, to
|
||||
determine the files that change across two changesets, you would dump
|
||||
the respective manifests to files, and use diff.
|
||||
|
||||
|
||||
Managing changeset tags
|
||||
-----------------------
|
||||
To create a tag to the current changeset:
|
||||
|
||||
hg tag tagname
|
||||
|
||||
This will _immediately_ generate a changeset with a change to the file
|
||||
.hgtags in the repository root. The new tag in this file will look
|
||||
something like:
|
||||
|
||||
| 35159ed4b30538e7a52c60ad0a63f7e9af156e4c tagname
|
||||
|
||||
and may be used to identify that changeset throughout the repo.
|
||||
Storing tags in this file and generating changesets immediately
|
||||
forces people to merge and keep tags up to date across the repository.
|
||||
|
||||
Note that tags are resolved by searching .hgtags in each of the
|
||||
repository heads, sequentially, and using the first match. "hg heads"
|
||||
lists the current heads.
|
||||
|
||||
The "hg tags" command, will lists all the currently valid tags.
|
||||
|
||||
|
||||
Hg server and source browser
|
||||
----------------------------
|
||||
|
||||
hg serve -p port
|
||||
|
||||
Launches a web server on the specified port, serving a source browser
|
||||
for the repository. This browser may be used to examine the
|
||||
changeset history, view annotated source files, generate diffs.
|
||||
Additionally "hg pull" may be run against it.
|
||||
|
||||
Additional useful commands
|
||||
(that probably only need one-line descriptions)
|
||||
-----------------------------------------------
|
||||
|
||||
(Slightly) more detail on all of these is available with
|
||||
|
||||
hg help [command]
|
||||
|
||||
Shows the differences between whatever changeset you most recently
|
||||
checked out, and your current working directory:
|
||||
|
||||
hg diff
|
||||
|
||||
View an annotated version of a source file:
|
||||
|
||||
hg annotate
|
||||
|
||||
Get a historical version of a file:
|
||||
|
||||
hg cat
|
||||
|
||||
NB: Most commands accepting a version number want the changeset's
|
||||
version number. "hg cat" is different in that it wants the
|
||||
*file*'s version number.
|
||||
|
||||
Unadd a file to the current commit:
|
||||
|
||||
hg forget
|
||||
|
||||
List all heads in the current repository:
|
||||
|
||||
hg heads
|
||||
|
||||
Undo exactly one (and ONLY one) changeset:
|
||||
|
||||
hg undo
|
||||
|
||||
Show the parents of a changeset:
|
||||
|
||||
hg parents
|
||||
|
||||
NB: Changesets have either one or two parent changesets. If your
|
||||
working directory contains the uncommitted results of a merge, then
|
||||
you have two parents. Otherwise, the single parent is the changeset
|
||||
which you most recently checked out.
|
||||
|
||||
|
||||