Using git for Gecko development

The canonical source code repositories at Mozilla use Mercurial, but it is possible to use git to interact with them directly.

With git-cinnabar contributors who prefer git gets the same experience and seamlessness as hg users with the Mozilla toolchain. git-cinnabar is a git extension for interacting with Mercurial remote repositories. Unlike other git-to-hg tools, it does not rely on a local Mercurial clone under the hood.

In practice it no longer matters what version control system one uses for Mozilla work as git-cinnabar supports pushing directly to Mercurial remotes such as the inbound integration tree, as well as making productivity tools like code review and try available to non-hg users.

I decided to write this tutorial to collect and synthesise how to get started with Mozilla development on git as the current available information is spread out in a few different places. You can read A git workflow for Gecko development by Mike Hommey, who is the author of git-cinnabar, for a more detailed technical walk-through. This is largely a reiteration of that, but adds a few hints on how to set up default origin branches and interacting with code review tools that could be useful to git novices and as a tutorial to get people ready to contribute patches to Gecko.

To use git with a remote hg repository you need git version 2.2.2 or newer and the Mercurial Python library installed. git-cinnabar provides a git-remote-hg binary that extends git to be able to talk directly to hg remotes. You install it by cloning it to somewhere of your liking, but ensure you put the directory in your environment PATH variable:

% git clone

To clone and set up your new Gecko repository:

  1. Create a git repository:

    % git init gecko
    % cd gecko
  2. Set a few options for git-cinnabar to be happier:

    % git config fetch.prune true
    % git config push.default upstream
  3. Add remotes for the Mercurial repositories you want:

    % git remote add central hg:: -t branches/default/tip
    % git remote add inbound hg:: -t branches/default/tip
    % git remote set-url --push inbound hg::ssh://
  4. Finally fetch all the changesets:
    % git remote update

The next step is optional, but useful if you want central and inbound to track the remote branches. It lets you check out central as if you would check out the master branch in a regular git repository and pull changes directly from the remote into it.

% git checkout --track -b central central/branches/default/tip
% git checkout --track -b inbound inbound/branches/default/tip
% git config branch.central.rebase true
% git config branch.inbound.rebase true

With this setup you can start new work in a branch branched off from one of the tracking branches for the remotes we just set up:

% git checkout central
% git pull
% git checkout -b 1123506

Working with the branch is just as you would expect:

% $EDITOR testing/marionette/evaluate.js
… hackety hack …
% git commit -am 'Bug 1123506 - Evaluate scripts in content; r?automatedtester'
% git push inbound

If you’ve previously used the gecko-dev mirror on Github, it is possible to reuse it with git-cinnabar, but my recommendation is to start with a fresh checkout unless you are bandwidth constricted. One major caveat to note with repurposing gecko-dev is that commits pulled from Mercurial will not have the same SHA-1s as those already in the repo.

Code review

When you are done writing your patch it must be reviewed before it can be integrated into Gecko. Mozilla uses a customised Review Board instance that it is possible to create review requests in by pushing branches to.

To use it you will at minimum need a Bugzilla account and an API key. If you’re a regular committer you get elevated privileges to trigger try runs, ability to land commits on our integration branch inbound, and permission to carry forward Ship It’s when you fix up already accepted changes.

To push from git to create a review request you need Mozilla VCS tools, which if you’ve run ./mach mercurial-setup before is checked out in ~/.mozbuild/version-control-tools. However, it is easy enough to install manually:

% git clone hg::

Inside the checkout there is a subdirectory git/commands that you must expose in your PATH environment variable.

In your checkout of Gecko, you now identify yourself with your Bugzilla login and a generated API key:

% git config bz.username
% git config bz.apikey as3r123hj325hjld3
% git config mozreview.nickname ato

Now configure your checkout to be able to use MozReview:

% git mozreview configure

When committing to your work branch, make sure you follow Mozilla’s commit message policy. If you do, MozReview will be able to automatically associate new review requests with bugs and assign reviewers:

% git commit -am 'Bug 1123506 - Evaluate scripts in content; r?automatedtester'
% git mozreview push

When you push you will be asked if you want to publish your review right away. You can hit Enter to confirm. If you have entered the reviewer correctly by his or her nickname, they will be notified that a new review is awaiting their attention.

When the reviewer grants you an r+, indicating the patch is allowed to land in the integration branch, you may land the commits using Autoland by selecting AutomationLand Commits, and confirming with the Land button. This presupposes that you have commit access level 3.


With the advent of modern code review at Mozilla, the need to push to try manually is greatly diminished. It is now possible to trigger tests on try through Autoland and MozReview.

An advantage of pushing to try from MozReview is that try runs become automatically associated with the review. This saves you from having to paste a link to the try run in the bug, and the reviewer from having to context switch to Bugzilla to tell if the commits passed integration checks.

To trigger a try run from MozReview: AutomationTrigger a Try Build, then enter a try syntax and hit Submit.

If you prefer the ways of the stone age and still want to push to try yourself, you can by adding it as a remote:

% git remote add try hg::
% git config remote.try.skipDefaultUpdate true
% git remote set-url --push try hg::ssh://
% git config remote.try.push +HEAD:refs/heads/branches/default/tip
% git remote update

This disables fetching from the try remote since it’s only composed of throwaway changesets.

The test jobs to run are defined using try syntax, and the server picks up these options from the most recent commit starting with try: …. The most common thing to do is to add a new, empty commit to the HEAD of your branch:

% git commit --allow-empty -m 'try: -b do -p all -u all -t none'
% git push try

I welcome feedback on this tutorial at

Andreas Tolfsen works for Mozilla on engineering productivity. He is the author of several WebDriver implementations, including Marionette and OperaDriver. Previously he led the core infrastructure team at Opera. He also holds a BA in Musicology from the University of Oslo.