Version 1.0.1 of Mercurial has been released. Use this version if available for your platform. Version 1.0 is OK, 0.9.5 mostly OK but has some serious known bugs, 0.9.4 not OK at all.
Please use Python version at least 2.4.4; version 2.5.x is recommended
Binary packages should be the right choice for most users. See Mercurial installation tutorial for more information if the binary packages are not enough for you.
Be sure to select the correct installer, depending on whether you use Mac OS X 10.4 or 10.5.
Sun internal users can use /pkg/local/bin/hg
Solaris packages are at Opensolaris.org site
Another option for Solaris users is to use a Blastwave Mercurial package.
However, on Solaris, the binary packages don't always work, so if they don't, follow these steps (SPARC or x86):
1.0.1 is not available for older Fedora's (as in selenic's download site or Fedora RPMs). For newer Fedoras use "yum install mercurial" and for older ones build Mercurial from sources.
Ubuntu provides Mercurial packages. They are generally too old. Do not use them. Build Mercurial from sources instead (it is very easy).
If you are using Windows, you probably want to convert newlines to CRLF in your checkout. Mercurial does not do this by default, but you can edit Mercurial.ini in your installation and make sure it includes
[extensions] win32text = [decode] ** = cleverdecode: [encode] ** = cleverencode:
Even if you are not working on Windows, you may sometimes have files which may have CRLF in them. If you commit those files and then try to push them, your push command will fail due to the forbidcrlf hook on our servers. If you had made more commits after the one that commited the file with CRLF then it is harder to get rid of that problematic commit. So the best way is to prevent that situation in the first place. If you have Mercurial 1.0 or later this is easy. Just add the following hook to your Mercurial.ini on Windows, ~/.hgrc on Unix, or .hg/hgrc inside a repo.
[hooks] pretxncommit.crlf = python:hgext.win32text.forbidcrlf
Be sure to configure your "user name" in the configuration file. (Mercurial.ini on Windows, ~/.hgrc on Unix, or .hg/hgrc inside a repo.) It should be your netbeans.org email address (based on your login ID). Example:
[ui] username = jhacker@netbeans.org
You may also include a display name using the usual email syntax. This is useful since people may not recognize you by your login ID alone:
[ui] username = John Q. Hacker <jhacker@netbeans.org>
Mercurial uses default HTTP ports (80 and 443), so if you use firewall, make sure that firewall permits connection to http://hg.netbeans.org/main for hg on these ports. If you have to use a proxy for HTTPS, try adding to your global config file e.g.
[http_proxy] host = webcache.uk.sun.com:8080
Mercurial takes heed of the environment variable "http_proxy". Make sure to set it properly.
If one uses KDiff3 as a merge program, it is useful to use hgmerge.py script in order to avoid possible incorrect merges. More information about merge programs for mercurial can be found here. Example:
[ui] merge = /path/to/hgmerge.py [hgmerge] interactive = kdiff3 noninteractive = diff3
When you first run a build, a special Ant task downloads binaries (JAR libraries etc.) on demand. More information is available in ExternalBinaries.
The NetBeans CVS repository was split into several repositories:
See HgMigration for background.
There will likely be additional repositories that are special clones of the above, especially main. These function somewhat like branches in CVS:
To start working with the main NetBeans Mercurial repository you need to create a clone of it.
$ hg clone http://hg.netbeans.org/main/ requesting all changes adding changesets adding manifests adding file changes added 5 changesets with 5 changes to 10 files
(The actual numbers will be much bigger, say 60-70k.)
Note that the initial clone may sometimes take a significant amount of time. Some users reported it took up to two hours for them.
If you have write access and are intending to push changes back, add a push path to your .hg/hgrc:
[paths] default = http://hg.netbeans.org/main/ # Add this: default-push = https://jhacker:secretpass@hg.netbeans.org/main/
(Replace jhacker with your netbeans.org username. Replace secretpass with your password, which during the dry-run period will simply be hguser. After the switch to a real repository you should get a real password in the mail.)
Every Mercurial repository is complete, self-contained, and independent. It contains its own private copy of a project’s files and history. A cloned repository remembers the location of the repository it was cloned from, but it does not communicate with that repository, or any other, unless you tell it to.
hg clone http://hg.netbeans.org/main/ will create a main directory under your current directory. (If you pass another argument, it will be used as an alternate directory name to create.) The main directory then contains a full copy of the http://hg.netbeans.org/main/ repository with checked out sources. The main/.hg directory contains all the Mercurial control files.
Most other directories under main are NetBeans modules imported from the CVS repository using this simple template: java/j2seproject -> java.j2seproject, core/progress -> api.progress, openide/loaders -> openide.loaders, etc.; the new directory name is predictably derived from the module's code name base, just removing some common prefixes and introducing some simple abbreviations. You can see the complete mapping in the new file nbbuild/translations.
The basic build infrastructure remains in main/nbbuild.
Building NetBeans is the same as it was under CVS. (There is also a top-level build.xml which delegates to nbbuild/build.xml for convenience.) You need JDK 5.0u14 and Ant 1.7.0.
$ cd main $ ant
Note: you need to be connected to the network for the first build, because it will fetch external binaries (JARs and ZIPs) from a server. You will also need to be online when doing the first build after some update to external binaries.
Note2: do not forget to have proper ANT_OPTS set - ie ANT_OPTS=-Xmx384m
Mercurial's commit operation will change only your local copy of the NetBeans repository. Example:
$ cd main $ # edit some files... $ hg ci
and enter a log message when prompted. (Note: you should make the first line of the log a complete sentence as a summary. Any additional lines can supply details.)
If you only want to check in some files or directory, just specify them:
$ hg ci java.j2seproject
After creating new files you just need to run
$ cd main $ hg add form/src/org/netbeans/modules/form/SpiffyBuilder.java form/test/data/
Like cvs add, this addition will only take effect when you next commit.
More info about operations on files could be found in the Mercurial book.
First check what changes will be propagated to the server:
$ cd main $ hg out
Then if you are ready to really push your changes, run:
$ cd main $ hg push
(If you checked out just http://hg.netbeans.org/main/, and did not configure an HTTPS URL for the default-push path as suggested above, you will need to specify this full URL as a command argument.)
If someone else has pushed changes in the meantime (since you last pulled), you need to pull their changes first and merge; see the next section.
Note: the server checks some basic conditions about your push before accepting it. In particular, if you tried to commit carriage returns (CRLF) in a text file, this will be rejected. You need to enable CRLF translation in your Hg settings.
Tip: if you are using Windows and you get a weird error message about SSL, check if your Internet Explorer settings say to use a proxy.
To update your sources, you can use:
$ cd main $ hg pull -u
This will pull other people's changes from the server into your repository. It will also update your working copy to the latest version.
If you have made your own changes in this repository (even in a completely unrelated directory), you will need to merge your changes with other people's changes. This requires running hg merge.
A convenient way to pull and merge at the same time is to use the Fetch extension. Enable it:
[extensions] fetch =
and run
$ cd main $ hg fetch
Be warned that there are two bugs associated with this extension:
If you want to retrieve all the repositories at once, install and enable the Forest extension. Then run:
$ hg fclone http://hg.netbeans.org/main/ nb_all
You should get nb_all for main sources, nb_all/contrib for extra modules, and nb_all/misc for additional files.
You can open and build experimental modules normally, e.g.
ant -f contrib/quickfilechooser/build.xml nbm
In most cases, if you make a mistake and want to fix it, you should just edit sources to fix it and commit a new revision. This preserves history of the mistake and its correction and is suitable for routine programming errors.
If a whole big commit was wrong (e.g. someone else broke the build), it is too much work to revert it manually. For this case you can use hg backout to revert its effects. (If the bad commit was not the last, you will need to merge since the subsequent commits should still be in effect.)
If you commit something that you really cannot tolerate being in history (e.g. legally forbidden files, passwords, ...) it is possible to discard the commit only if you have not yet pushed it. (Once it is on the server, it is permanent.)
If you have just committed the change and nothing else, just run hg rollback. Your working copy will still be modified; you can hg revert if you need to.
Sometimes hg rollback cannot be used, but it is still possible to kill off bad changesets. The simplest way of doing this is to use the hg strip command, added by the MQ extension:
[extensions] mq =
If you strip out a changeset from your local repository, it will be removed along with all descendant changesets. Be careful. (The command ought to save a backup somewhere just in case.)
You can also make a version of the repository that does not include the latest changes. Use hg clone -r and pass in the "last known good" changeset ID.
hg.netbeans.org has a number of server hooks in place to prevent common accidents from being committed permanently into the repository. The hooks are checking your changesets one by one.
Typical workflow for release clones is to do all the fixes on main and merge after QE verification. This involves the question how the fixes/changes/changesets could be easily moved from one to repository to another.
The easiest way is to use the Transplant extension. First you need to enable it in your ${HOME}/.hgrc:
[extensions] transplant= [defaults] transplant = --logIf you have your changeset already reviewed then its import to release-clone repository would be as simple as running:
hg -R release-clone transplant -s main REV1:REV2It takes all the changes between revisions REV1 and REV2 (you can specify only one revision if you like) and puts them to the release-clone repository. The new changesets are created in release-clone repository. They will have the same date and username as the original; the log message will additionally mention the original changeset. Note that transplanting a changeset involves a merge operation (the branch might be missing some context that was in the trunk) so you may on occasion be asked to resolve conflicts (see hg help transplant for more).
The second more CVS-like method is to create a patch first and then apply it to the release-clone. So the sequence of the commands would be following:
hg -R main export --git REV1:REV2 > myfix.patch hg -R release-clone import myfix.patchIt should basically do the same job as using transplant extension. (The transplant command adds some invisible metadata to the new changeset saying that it is a transplant, so that is preferable to doing a manual diff import.) This method has the advantage that you could edit the patch a bit before applying it to the branch, if some pieces are only applicable to trunk, but be very careful about applying a patch that QE has not tested.
Don't forget to push your changes when done.
The CVS server will still be available at least for read access after the switch. Say you had an old branch over the xml and websvc modules, named new_gui, with a base tag of new_gui_base.
cvs rdiff -r new_gui_base -r new_gui xml websvc > /tmp/mybranch-cvs.diff ruby nbbuild/translate-patch < /tmp/mybranch-cvs.diff > /tmp/mybranch-hg.diff hg import -p0 -m 'imported new_gui branch' /tmp/mybranch-hg.diff
(The translate-patch script should fix up filenames to match the new source layout. If your patch added completely new modules, you will need to translate these by hand, e.g. xml/newspi -> xml.newspi.)
(Note: if you get bizarre errors from the CVS server, make sure your CVSROOT ends in /shared/data/ccvs/repository rather than simply /cvs and try again.)
Not ready to merge your branch to main yet? Just make a local clone for your branch, import changes there, and continue development. Use hg merge to pull in changes from main so you do not fall out of synch.
Rather complex but seems to work. To move mod from repo1 to repo2 you need something like this:
(Note: if you're on Windows, the /dev/stdin might not work for you in the first step. Save the include mode statement in a file; then have --filemap point to the file)
plus a lot of careful sanity checking to make sure you are doing what you think you are doing.
If you want the module to live under a different relative path in the new repo, you should use
(echo include mod; echo rename mod newmod) | ....
to move it during the conversion. Otherwise you could use regular hg -R repo2 ren mod newmod at the end, but this will consume additional disk space (Hg bug #883).
The command 'hg export' generates a patch in Unix encoding (LF) independently on hgext.win32text setup. So before applying a patch run some unix2dos utility.
For routine development you will simply make some changes, test, and commit. However in special circumstances you may prefer to polish a patch for review by others. In particular, API changes normally go through a prereview process. This is different from normal development because:
For this style of development, MQ (Mercurial Queues) is ideal. This is a powerful tool bundled with Mercurial for managing patches. To get started, enable the MQ extension:
[extensions] mq =
You must be sure to not pull (or fetch) with patches applied. If you are a Unix user you can just
[hooks] prechangegroup.mq-no-pull = ! hg qtop > /dev/null 2>&1
You will probably also want to use Git-format diffs. This enhanced diff format captures file renames, among other things. You can either turn this on for all Mercurial commands:
[diff] git = 1
or just for MQ:
[defaults] qdiff = --git qnew = --git qrefresh = --git
In your NetBeans source repository, set up a patch queue:
hg qinit
(Use -c if you also want to version it as a separate Hg repo.)
Now let's say you are working on fixing bug #123456 when you realize that it requires an API change. Just make the API change as a local modification and try to use it - verify that it helps. Do not commit anything. Feel free to add, delete, or rename files as well as editing them (using hg add, rm, ren as usual).
Now you can initialize a patch for this change. Since you already have local modifications, use -f; add -e to give an initial log message:
hg qnew -e -f 123456.diff
Note: be sure that your log message does not start with # as this character is special in patches (marks a header) or a number. So do not use
#123456: a problem.
but rather
Issue #123456: a problem.
or similar.
Now hg stat and hg di will show nothing - because you have no modifications beyond what is saved in the patch. hg tip will list a special temporary changeset for your working patch, because your patch is applied, as you can see with hg qapp.
When you have submitted the issue for review (keywords API API_REVIEW_FAST, assigned to apireviews), attach the patch directly from .hg/patches/123456.diff, or you can run hg qdi to produce a patch that also shows the base revision. Add a reminder to your calendar to commit the patch in a week if there are no objections.
hg qpop -a to go back to unpatched sources and go about your normal work. (Do not pull or push while you have patches applied!)
If reviewers request some changes in the following days, hg qgo 123456 to reapply patch; make whatever changes you want. hg di will show changes from the last saved patch. To update the saved patch, use hg qref, at which point you can sanity-check it using hg qdi. Then just attach the new version as before so reviewers can see the revised patch.
If you'd rather not attach every revision, you can also mail the patch easily: hg email qtip will send it out to interested parties. (Use -n to preview what would be mailed before you really do it!) You need a little configuration, for example:
[smtp] host = mail-amer.sun.com username = jh102201 tls = true [email] from = John Q. Hacker <jhacker@netbeans.org> to = apireviews@netbeans.org cc = ,
If some changes are made to the repository which causes your patch to not apply cleanly after you last worked on it, hg qpush or hg qgo will show some warnings and leave behind *.rej files containing "hunks" of the patch which did not apply. You need to look at these and figure out how to apply the equivalent to the new code. (It is possible but quite tricky to run a standard 3-way merge tool to resolve conflicts; a future version of MQ may make this more friendly.) hg qref when you have everything the way you want it again.
If your review is accepted, you can easily commit the patch as a permanent change (and remove it from the queue):
hg qpop -a hg import .hg/patches/123456.diff hg qdel 123456.diff
and you can then push as usual.
If you have multiple active patches, bear in mind that in MQ patches are applied in series. This means that if hg qser prints
123321.diff 123456.diff
and the two patches touch related files, then 123456.diff may depend on 123321.diff and build on top of it. If you want to ensure the patches are independent, just hg qpop -a, edit .hg/patches/series to reorder your patches, and run hg qgo 123456.diff to make sure it applies on its own.
Want to know more about MQ? Try chapters 12 and 13 of the Mercurial book.
Before using Mercurial on production sources you should make sure you understand not only what merging does, but also that your merge tool is correctly set up in the unusual case of a line-by-line merge conflict. Let's make some dummy repositories to test a merge conflict.
We will use hg clone -r REV to simulate another person cloning a repository before some further changes were made. You could equivalently switch back and forth between the repositories, but clone -r will be helpful in retrying the merge.
$ hg init hgtest-how-to-merge $ cd hgtest-how-to-merge $ echo one > f $ hg ci -A -m one adding f $ echo two > f $ hg ci -m two $ hg log changeset: 1:de9c1703a8d3 tag: tip user: .... date: .... summary: two changeset: 0:58d574e6ba6e user: .... date: .... summary: one $ hg clone -r 0 . dupe requesting all changes adding changesets adding manifests adding file changes added 1 changesets with 1 changes to 1 files 1 files updated, 0 files merged, 0 files removed, 0 files unresolved $ cd dupe $ echo three > f $ hg ci -m three $ hg log changeset: 1:04d4360ce505 tag: tip user: .... date: .... summary: three changeset: 0:58d574e6ba6e user: .... date: .... summary: one
Now the second user, in the dupe repository clone, has committed changes against revision 58d574e6ba6e, effectively creating a new branch. In this case we have intentionally committed conflicting changes to the same file. When the second user tries to merge in changes from the first, Mercurial will look for a graphical merge tool and try to launch it. If your Hg installation is configured correctly, this tool will be found, and you will be able to resolve the merge and save:
$ hg fetch .. pulling from .. searching for changes adding changesets adding manifests adding file changes added 1 changesets with 1 changes to 1 files (+1 heads) merging with new head 2:de9c1703a8d3 merging f 0 files updated, 1 files merged, 0 files removed, 0 files unresolved new changeset 3:2ac5c85658f0 merges remote changes with local $ cat f two and a half
Here the merge tool has shown us that two parties changed one to both two and three and we have resolved this by saying it should really be two and a half.
You can use hg glog to see the result graphically. Note that while changeset IDs (the long hex hashes) stay the same, sequence numbers are different from the original repository: 1 was pulled to this clone as 2 though it is still identified as de9c1703a8d3.
$ hg glog @ changeset: 3:2ac5c85658f0 |\ tag: tip | | parent: 1:04d4360ce505 | | parent: 2:de9c1703a8d3 | | user: .... | | date: .... | | summary: Automated merge with file:/tmp/hgtest-how-to-merge | | | o changeset: 2:de9c1703a8d3 | | parent: 0:58d574e6ba6e | | user: .... | | date: .... | | summary: two | | o | changeset: 1:04d4360ce505 |/ user: .... | date: .... | summary: three | o changeset: 0:58d574e6ba6e user: .... date: .... summary: one
If you found any problems with your merge tool configuration, try to fix it now according to Mercurial documentation. Then you can easily rerun the test:
$ cd .. $ hg clone -r 0 . dupe2 requesting all changes adding changesets adding manifests adding file changes added 1 changesets with 1 changes to 1 files 1 files updated, 0 files merged, 0 files removed, 0 files unresolved $ cd dupe2 $ echo three > f $ hg ci -m three
and try the merge again.
Unix users who prefer not to use graphical merge tools at all can choose to just get CVS-style conflict markers. In this case you will need to edit the conflicted files, manually resolve the conflicts, and commit the merge when done. You will need the command merge in your path (many systems put this in a package called rcs). And in your ~/.profile or similar, add export HGMERGE=merge to use this simple tool. Here is an example of the result:
$ HGMERGE=merge hg fetch .. pulling from .. searching for changes adding changesets adding manifests adding file changes added 1 changesets with 1 changes to 1 files (+1 heads) merging with new head 2:de9c1703a8d3 merging f merge: warning: conflicts during merge merging f failed! 0 files updated, 0 files merged, 0 files removed, 1 files unresolved There are unresolved merges, you can redo the full merge using: hg update -C 1 hg merge 2 $ cat f <<<<<<< /tmp/hgtest-how-to-merge/dupe2/f three ======= two >>>>>>> /tmp/f~other.6OGVvm $ echo 'two and a half' > f $ hg di diff --git a/f b/f --- a/f +++ b/f @@ -1,1 +1,1 @@ three -three +two and a half $ hg ci -m merged $ hg glog @ changeset: 3:081a22ed714b |\ tag: tip | | parent: 1:6b06aa95da85 | | parent: 2:de9c1703a8d3 | | user: .... | | date: .... | | summary: merged | | | o changeset: 2:de9c1703a8d3 | | parent: 0:58d574e6ba6e | | user: .... | | date: .... | | summary: two | | o | changeset: 1:6b06aa95da85 |/ user: .... | date: .... | summary: three | o changeset: 0:58d574e6ba6e user: .... date: .... summary: one
You may also want to check out the Mercurial tutorial on merge conflicts.
Mercurial has no direct equivalent to the CVS checkout command; you always have the entire repository with history on your computer.
$ hg clone http://hg.netbeans.org/main/ nb_all
The Mercurial command checkout is simply an alias for the update command. This does no network operations but might be used to switch your working directory to an older revision.
hg pull -u (possibly followed by hg merge and hg ci), or hg fetch, is the closest equivalent to cvs up.
hg ci followed by hg push together act similarly to cvs ci.
You can use the -p (patch) option to either incoming or outgoing. This provides something similar to cvs -n up or cvs -n ci to preview what will be pulled or pushed. Example:
cd /path/to/repo1 hg in -p http://hg.netbeans.org/repo2/
CVS has a .cvsignore file in each directory which can match files or subdirectories directly in that directory using a simple glob syntax.
Hg uses a single .hgignore file at top level which lists ignored files or subdirectories in the whole repository using a choice of syntax, by default regular expression.
The initially created NB repositories will have .hgignore files created by inspecting the old .cvsignore files (which are not copied over). Some general patterns cover a lot of cases, e.g. /nbproject/private$ ignores any such dir generically. If you need to add new special-case ignore patterns, just edit and commit this file.
http://www.selenic.com/mercurial/wiki/index.cgi/TipsAndTricks
File a bug about the NetBeans Hg repositories and their usage.