Producing a Changeset

version 0.02

This section is confined to the actual Mercurial mechanics required to produce a changeset:

Setting a JDK User Name

Ensure that ui.username has a value in the ~/.hgrc file as described in Verifying the Configuration.


The timing for creating a changeset is important. Creating the changeset long before it gets pushed into the parent repository may require complex merges. If a changeset is created before sufficient review or testing, a rollback may be required and a new changeset may be required to correct previous mistakes. The mq extension is recommended for managing changes before they become committed to a changeset.

In the examples below, the script common/bin/ can be used to apply the Mercurial command to all the repositories in the forest. So when you see hg, if you are dealing with one repository, just use "hg", if it's a forest, use "sh common/bin/".

Each repository in the forest is managed independently. After editing files in the individual cloned repositories of the forest, the hg status command may be used to see the changes in a single repository.

$ hg root
$ hg status
? duke/images/DukeTubbingSmall.png
$ hg add duke/images/DukeTubbingSmall.png
$ hg status
A duke/images/DukeTubbingSmall.png

To see changes made to the repositories use hg status:

$ hg status
A duke/images/DukeTubbingSmall.png

In this example, the repository was previously cloned as described in Cloning a Sandbox Repository. A new file DukeTubbingSmall.png was added to a new subdirectory.

Formatting a Changeset Comment

A single change is described by a block of text of the following form:

<bugid>: <synopsis-of-symptom>
Summary: <summary-of-code-change>
Reviewed-by: <reviewer>+
Contributed-by: <contributor-email>

There may be more than one bugid line, but there must be at least one.

The summary line is optional, but authors are strongly encouraged to include one if the nature of the change is not obvious from the synopsis. It's just one line, meant to give the reader a clue as to how the code changed. A more complete description of the change belongs in the bug report.

A reviewed-by line is required. Reviewers must have the ability to deal with any adverse consequences of the change, and so must themselves be authors. They are therefore identified by their OpenJDK usernames rather than full e-mail addresses.

The contributed-by line is optional. If present, it is a list of comma-separated email addresses. It should be included only when the author or authors of the change do not have commit rights to the target repository and thus would not otherwise receive acknowledgment.

There will be exceptions for merge changesets, tag changesets, etc.


1234567: NPE thrown on FileInputStream("")
Summary: Rewrite precondition-checking code in io.c
Reviewed-by: mr
Contributed-by: Ben Bitdiddle <ben at>

If a changeset contains multiple unrelated changes (this is frowned upon, but may happen from time to time) then its comment will contain multiple blocks of the above form, separated by blank lines.

The required format of the comments will be enforced whenever the changeset is pushed into the JDK master or team repository forests. Other Projects may copy these conventions, adopt some other conventions, or have no conventions, depending upon their goals.

Committing a Changeset

The following commands commit all of the changes in a repository to a changeset.

$ cat ../message
1111111: Missing Duke gif
Summary:  Add missing file
Reviewed-by: iag
$ hg commit -l ../message
$ hg toutgoing
comparing with
searching for changes
changeset:   23:fb12953f3a35
tag:         tip
user:        iris
date:        Wed Dec 12 21:05:59 2007 -0800
summary:     1111111: Missing Duke gif


It is often necessary to merge local changes with those made in the parent repositories. The first step in a merge process is to retrieve (or pull) the collection of changesets which have been pushed since the last merge or initial clone. If there if there are merge conflicts, then they must be resolved. Chapter 3 of the Mercurial book contains detailed information on the merging process.

There are two basic ways to update the working set files in the repositories:

Option 1: hg pull
One way to merge the parent repository with the working set of files is to use hg pull all by itself. This option allows merging off-line or at a later time.
$ hg pull
pulling from
searching for changes
no changes found

In Mercurial, pulling changesets will not update or merge into the working set of files. To update the clone, run hg update. If the update reports conflicts, run hg merge to resolve them.

Option 2: hg fetch
Alternatively, use hg fetch to pull the changes, update the working set files, and create simple merge changesets as necessary. The fetch extension is distributed with Mercurial but needs to be enabled. Edit the .hgrc to include the following entries:

Once the fetch extension has been enabled, hg fetch may be invoked as follows:

$ hg fetch
pulling from
searching for changes
no changes found

Actual file merging will be done with the selected Mercurial merging tool see MergeProgram for the details on how to define the selected merge tool in ~/.hgrc.


In order to push changesets into the parent repository, some additional configuration is required. The following sections describe the operations that will be performed by users with push access.

Generating an SSH Key

All pushes require an ssh key which must be installed on the Mercurial server. The ssh-keygen command generates an ssh key. The -b option overrides the default number of bits for the key. Allow a few minutes to generate a 4096 bit key; a key of at least 2048 bits is recommended. While it is possible to use ssh without a passphrase, this is strongly discouraged. Empty or insecure passphrases may be reset using ssh-keygen -p; this does not change the keys.

$ ssh-keygen -t rsa -b 4096
Enter file in which to save the key(/u/iris/.ssh/id_rsa):
Generating public/private rsa key pair.
Enter passphrase(empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /u/iris/.ssh/id_rsa.
Your public key has been saved in /u/iris/.ssh/
The key fingerprint is:
md5 4096 c2:b7:00:e6:4b:da:ea:ec:32:30:f5:bd:12:26:04:83 iris@duke
The key's randomart image is:
+--[ RSA 4096]----+
|    E.=          |
|     . *         |
|      o .   .    |
|         + o     |
|        S + .    |
|       .   + .   |
|        + + +..  |
|       * . oo+.  |
|      o . .o..   |

The ~/.ssh/ is a text file containing the public ssh key. This file should be mailed as an attachment along with the JDK username to keys(at) An administrator will install your key on the server and notify you on completion. This process may take a couple of days.

Users behind a SOCKS firewall can add a directive to the ~/.ssh/config file to connect to the OpenJDK Mercurial server:

Host *
ProxyCommand /usr/lib/ssh/ssh-socks5-proxy-connect -h [socks_proxy_address] %h %p

See the ssh-socks5-proxy-connect man page and ssh-config man page for more information. Other systems may require proxy access via other programs. Some Linux distributions provide the corkscrew package which provides ssh access through HTTP proxies.

It is recommended that all users check with their network administrators before installing any kind of TCP forwarding tool on their network. Many corporations and institutions have strict security policies in this area.

SSH Shortcuts

The following section provides some tips for improving the usability of ssh-related operations.

Setting the default-push Path to the Server Repositories

This is the typical development model:

Diagram of server repos and user's clone

Changesets need to be pushed via ssh to the read/write repository which resides on the OpenJDK Mercurial server. The easiest way to do this is to have each repository define the "default-push" path in every repository's .hg/hgrc file. The .hg/hgrc file in is not a managed file-- it is private to the repository. The following example defines the "default" and "default-push" paths for clones of the jdk9/dev team repository.

default =
default-push = ssh://<JDK_username>

Given a JDK_username this simple script will attempt to do this for all the repositories:

hgdirs="`find . -type d -name .hg`"
for i in ${hgdirs}; do
  d="`dirname ${i}`"
  defpush="`(cd ${d} && hg paths default-push 2> /dev/null)`"
  if [ "${defpush}" = "" ] ; then
    defpath="`(cd ${d} && hg paths default 2> /dev/null)`"
    if [ "${defpath}" != "" ] ; then
      defpush="`echo ${defpath} | sed -e 's@http://\([^/]*/[^/]*/[^/]*\)/\(.*\)@ssh://$username\@\1/\2@'`"
      cp ${i}/hgrc ${i}/hgrc.orig
      echo "default-push = ${defpush}" >> ${i}/hgrc
      echo "Added default-push: ${defpush}"
for i in ${hgdirs}; do
  d="`dirname ${i}`"
  echo "(cd ${d} && hg paths)"
  (cd ${d} && hg paths)
exit 0

Pushing a Changeset

Committers can use the hg push command to propagate changesets into the repositories.

Most developers will only find a need to create changesets in one or two repositories. However, it is important that before any changesets are pushed, the corresponding forest pull and merge with the destination forest be performed; otherwise there is a risk of breaking the build.

$ hg push

After the push has been accepted, an automatic e-mail notification will be sent to the mailing list associated with the repository. In most cases notifications are sent to the Project's -dev mailing list. Some Projects with high traffic -dev mailing lists use a dedicated -changes list for notifications.

Who has push access?

All of a Project's Committers can push to all of the the Project's repositories.

Some Projects may chose to restrict the set of Committers with push to key repositories. For instance, JDK Release Projects restrict push access to MASTER repositories to Committers who are either integrators or members of the Release Engineering Team.

Refer to the Nominating a Contributor or Author to be a Committer section of the Project page for information about becoming a Project Committer.

version 0.02