Gerrit/Tutorial



This tutorial helps you with:
 * step-by-step instructions and screenshots for getting Gerrit access
 * setting up Git on your machine
 * configuring Git
 * installing git-review
 * submitting a patch
 * understanding the MediaWiki code review process

For the quick version, see Gerrit/Getting started. Gerrit/Advanced usage has additional documentation for power users. For more information check Gerrit.

What is Git?
Git is a distributed version control system (dvcs) written in C originally developed by Linus Torvalds and others to manage the Linux kernel. In the past couple of years, it has taken off as a very robust and well-supported code repository. “Distributed” means that there is no central copy of the repository. With Subversion, Wikimedia’s servers host the repository and users commit their changes to it. In contrast, with Git, once you’ve cloned the repository, you have a fully functioning copy of the source code, with all the branches and tagged releases at your disposal.

Git is a free and open source distributed version control system designed to handle everything from small to very large projects with speed and efficiency. Git is easy to learn and has a tiny footprint with lightning fast performance. It outclasses SCM tools like Subversion, CVS, Perforce, and ClearCase with features like cheap local branching, convenient staging areas, and multiple workflows.

What is Gerrit?
Gerrit is a free, web-based collaborative code review tool that integrates with Git. It has been developed at Google by Shawn Pearce (co-author of Git, founder of JGit) for the development of the Android project.

Starting from a set of patches for Rietveld, it became a fork and evolved into a full blown project when ACL patches wouldn't be merged into Rietveld by its author, Guido van Rossum.

Originally written in Python like Rietveld, it is now written in Java (Java EE Java Servlet) with SQL since version 2.

Why did Wikimedia engineering move from Subversion to Git
Three major reasons:
 * 1) To encourage participation: Since Git is distributed, it allows people to contribute with a much lower barrier to entry. Anyone will be able to clone the repository and make their own changes to keep track of them. And if you’ve got an account in our code review tool (Gerrit), you’ll be able to push changes for the wider community to review.
 * 2) To fix our technical process: Subversion has technical flaws that make life difficult for developers. Notably, the implementation of branching is not very easy to use, and makes it hard to use “feature branches”. Our community is very distributed, with many parallel efforts and needs to integrate many different feature efforts, so we’d like to use feature branches more. Git branches are very easy to work with and merge between, which should make things easier for our development community.  (Several other large projects, such as Drupal and PostgreSQL, have made the same switch for similar reasons, and we’ve done our best to learn from their experiences.)
 * 3) To get improvements to users faster: With better branching and a more granular code review workflow that suits our needs better, plus our ongoing improvements to our automated testing infrastructure, we won’t have to wait months before deploying already-written features and bugfixes to Wikimedia sites.

Setting up Git
These instructions explain how to install Git as a command-line tool. If you also want a GUI client check the list maintained by the Git project. For alternate instructions look here, or here.

Mac OS X
Install one of the following:
 * Homebrew package manager:  – Recommended, simple updating and easy installing of other packages
 * Standalone: Git for Mac

Windows
Install Git + MSys (Minimal Bash for Windows) from [//msysgit.github.io/ msysgit.github.io]. This gives you Git, plus a shell that allows most of the command lines in these instructions to work on Windows. See also Gerrit/TortoiseGit tutorial.

Linux & UNIX
For other Linux distributions please check your vendor documentation.
 * Debian/Ubuntu:
 * Fedora:
 * archlinux:
 * openSUSE:
 * Gentoo:
 * FreeBSD:
 * NetBSD:
 * OpenBSD:
 * Solaris 11 Express:
 * Mageia:

Now that you have Git installed, it’s time to configure your personal info.

Configure Git
Now that you have Git on your system, you’ll want to do a few things to customize your Git environment. You should have to do these things only once; they’ll stick around between upgrades. You can also change them at any time by running through the commands again.

Git comes with a tool called  that lets you get and set configuration variables that control all aspects of how Git looks and operates. To see your current configuration use the "list" (-l) option: git config -l

Set your username and email
Git tracks who makes each commit by checking the user’s name and email. In addition, we use this info to associate your commits with your Gerrit account. To set these, enter the code below, replacing the name and email with your own. (To keep your email private you can use " @gerrit.wikimedia.org", substituting your Gerrit username.) git config --global user.email "example@wikimedia.org" git config --global user.name "example"

Set Up SSH Keys in Gerrit
We use SSH keys to establish a secure connection between your computer and Gerrit. Setting them up is fairly easy, but does involve a number of steps. Run the following commands in a terminal. For alternate instructions look here, and then here.

To make sure whether you need to generate a brand new key, you need to check if one already exists. List the files in your .ssh directory (if you have one): $ cd .ssh $ ls If you see a file called  here, you may skip right to.

Generate a new SSH key
To generate a new SSH key, enter the code below. We want the default settings so when asked to enter a file in which to save the key, just press enter. $ ssh-keygen -t rsa -C "your_email@youremail.com"

Assign a memorable passphrase and press [enter] (press the [enter] key twice if you don't want a passphrase*).


 * * Why do passphrases matter?
 * Passwords aren’t very secure, you already know this. If you use one that’s easy to remember, it’s easier to guess or brute-force (try many options until one works). If you use one that’s random it’s hard to remember, and thus you’re more inclined to write the password down. Both of these are Very Bad Things™. This is why you’re using ssh keys.


 * But using a key without a passphrase is basically the same as writing down that random password in a file on your computer. Anyone who gains access to your drive has gained access to every system you use that key with. This is also a Very Bad Thing™. The solution is obvious: add a passphrase.


 * But I don’t want to enter a long passphrase every time I use the key!


 * Neither do we! Thankfully, there’s a nifty little tool called  that can save your passphrase securely so you don’t have to re-enter it. If you’re on OSX Leopard or later your keys can be saved in the system’s keychain to make your life even easier.

Which should give you something like this:

It will create 2 files in ~/.ssh directory as follows:

~/.ssh/id_rsa : identification (private) key ~/.ssh/id_rsa.pub : public key

Add your SSH key
Open your public key file, (e.g. id_rsa.pub) with a text editor (Notepad, TextEdit, or gedit will do just fine). You may need to turn on “view hidden files” to find it because the .ssh directory is hidden. It’s important you copy your SSH key exactly as it is written without adding any newlines or whitespace. Copy the full text, including the "ssh-rsa" lead and email address tail.

On a linux system you can use the following: cat /home//.ssh/id_rsa.pub Which for local-user preilly, gives this:

Can’t view hidden files? Other ways to copy:
OSX $ pbcopy < ~/.ssh/id_rsa.pub # Copies the contents of the id_rsa.pub file to your clipboard

Windows You can open Git GUI, go to Help > Show Key, and then press Copy To Clipboard to copy your public key to your clipboard.

Linux $ sudo apt-get install xclip # Downloads and installs xclip $ xclip -sel clip < ~/.ssh/id_rsa.pub

Add ssh key to your Gerrit account
Create an account at wikitech.wikimedia.org if you do not yet have one.

Log into the web interface for Gerrit. Click on your username in the top right corner, then choose "Settings". On the left you will see SSH PUBLIC KEYS. Paste your SSH Public Key into the corresponding field. Alternately, once logged in, use these direct links to add your public key to Gerrit and wikitech.

Add SSH key to use with Git
Start Git Bash.
 * Get ssh-agent running using
 * $ eval `ssh-agent`
 * Be sure to use the accent " ` " located under the tilde " ~ ", not the single quote " ' ".


 * Add your private key to the agent (use path to your private key file)
 * $ ssh-add .ssh/id_rsa
 * if the key is in the default location, use
 * Key should be in OpenSSH format (.ppk keys can be exported to this format in PuTTyGen).


 * Run ssh. (Do be paranoid and check for the matching SSH fingerprint for gerrit.wikimedia.org:29418 when logging in for the first time.)
 * $ ssh -p 29418 @gerrit.wikimedia.org
 * It should give a Gerrit welcome message and then abort. If it doesn't, add the  (verbose) option to the command to help debug.

Download the Examples extension using Git
You can download MediaWiki core using Git, as well as the source code of any project repository hosted at gerrit.wikimedia.org (the Wikimedia Foundation server cluster).

Let's practice downloading the Examples extension. Simply run the following on the git bash command line: $ git clone ssh://@gerrit.wikimedia.org:29418/mediawiki/extensions/examples

This will copy the entire history of the "Examples" extension repository. You will have a working directory of the extension's main branch, so you can look at the code and start editing it. If you change into the new directory, you can see the .git subdirectory. That is where all the project data is.

By default, Git will create a directory that has the same name as the project in the URL you give it - basically whatever is after the last slash of the URL. If you want something different, you can just put it at the end of the command, after the URL. So, in this example you will have a "examples" directory.

Prepare to work with Gerrit
Your commit message needs a "change ID" in order to work with Gerrit. You can see these in the git log for a project and if you browse changes on Gerrit, they look like  starting with an I (capital i)). Each time you amend a commit in response to Gerrit feedback git gives it a new commit ID, but because this change ID stays the same Gerrit will keep track of it as a new "patch set" addressing the same change.

There's a git add-on called git-review that adds a Change-ID line to your commits and manages other aspects of using Gerrit.

Installing git-review
For more details, please see Gerrit/git-review

First, install the release version of.

In Windows, please see Gerrit/git-review.

If you're running recent Debian/Ubuntu,  has been packaged, so you can simply run If that worked, skip past the next section.

Install using pip Python package installer
Generally, the easiest way to get the latest version of git-review is to install it using the python package installer :

If that worked, skip to the next section. If you need to install pip, then:

In Debian/Ubuntu, to install

On OpenSuse, install via YaST, then run



On FreeBSD, you directly have a kept up to date devel/git-review port:

Note: if you don't have  but have   installed, you can use this:

Or, if you already have git-review installed, you can upgrade it using

Configuring git-review
Git is a distributed version control system; it's possible to fetch code from one host, push your changes to another, and submit them to a third for Gerrit code review. It's a lot simpler to work with one "remote" for all three. Since Git's default remote name is "origin" and most guides on the web use that name, let's tell git-review to use this as well. In your home directory, create .config/git-review/git-review.conf (in Windows, the file is %USERPROFILE%\.config\git-review\git-review.conf) and add these two lines:

Setting up git-review
After cloning a repository, you need to set it up for git-review. This will automatically happen the first time you try to submit a commit, but it's generally better to do it right after cloning. In your project's directory ("examples"), enter

which should give you this:

''If you see "the authenticity of host gerrit.wikimedia.org can't be established..." Don’t worry, this is supposed to happen the first time. Type "yes".''

This may ask you for your git username, if it's different from the shell username you're using.

How to submit a patch
For a brief overview see Gerrit/Getting started.

The main avenue for submitting changes to MediaWiki code is to first join the MediaWiki development community so you can submit changes to Gerrit, our code review tool. Getting developer access is relatively easy.

Clone the "mediawiki core" repository or the project repository which you are interested in. Open git bash and enter one of the following lines: $ git clone ssh://USERNAME@gerrit.wikimedia.org:29418/mediawiki/core.git $ git clone ssh://USERNAME@gerrit.wikimedia.org:29418/mediawiki/extensions/EXTENSION.git Substitute your gerrit username and the extension or project name. You can copy this git command from the top of the project's home page in gerrit.

Update master
Make sure that your master branch (the branch created when you initially cloned the repository) is up to date: git pull origin master



However, note that a few repositories use different terms (for example operations/puppet has a "production" instead of a "master" branch).

Create a branch
First, create a local branch for your new change. Give the branch a short but reasonably descriptive name (e.g.,  ,  ,  , ..). git checkout -b BRANCHNAME origin/master This will create a new branch (BRANCHNAME) from the latest 'master' and check it out for you. This is equivalent to doing git branch BRANCHNAME --track origin/master git checkout BRANCHNAME

Usual way
Modify your local code in some fashion. Using your preferred editor, modify the file Example/Example.body.php

Then check the changes you've made, within the file(s) and within the directory: git diff

Without any extra arguments, a simple  will display in unified diff format (a patch) what code or content you've changed in your project since the last commit that are not yet staged for the next commit snapshot.

Then check the changes you've made, within the file(s) and within the directory: git status

You run git status to see if anything has been modified and/or staged since your last commit so you can decide if you want to commit a new snapshot and what will be recorded in it.

This will show all modified files. To prepare submitting a file, you should add your changes to the index (the staging area between your working copy and your local repository), which is done by using the  command. git add Example/Example.body.php

You pass a file to  when you want the changes you made to it to be included in your next commit.

Any files you've changed that are not staged by you doing  will be left alone - this means you can craft your commits with a bit more precision.

At any time you can always review the changes already added to the staging area by running, and look at the diff with  :



The  command will show you what contents have been staged. That is, this will show you the changes that will currently go into the next commit snapshot.

Once you are happy with the change list, you can add them to your local repository by using git commit

You will then be prompted in your favorite editor to add a descriptive message for this commit. This is what other people will see when you will later push that commit to another repository. If you do not manually add a Change-ID line to your commit message, it will be automatically generated and added for you.



You can repeat this step over and over until you have a set of changes that you want to have pushed to the master branch. One of the cool things about git is that when you, you are committing to your local copy. This means you can commit as often as you like without potentially screwing things up for another developer on the project, unlike in SVN where you would want to be very careful that the changes you commit would not cause things to break.

Hence the workflow is something like:

Prepare to push your change set to Gerrit
Before your changes can be merged into master, they must undergo review in Gerrit.

But first, it's a good idea to synchronize your change set with any changes that may have occurred in master while you've been working. From within the branch you've been working on, execute the following command: git pull --rebase origin master

This command will fetch new commits from the remote and then rebase your local commits on top of them. It will temporarily set aside the changes you've made in your branch, apply all of the changes that have happend in master to your working branch, then merge (recommit) all of the changes you've made back into the branch. Doing this will help avoid future merge conflicts. Plus, it gives you an opportunity to test your changes against the latest code in master.

Once you are satisfied with your change set and you've rebased against master, you are ready to push your code to Gerrit for review.

Squash into single commit
If you make several related commits to your local repository prior to wanting to submit for review, you should squash those commits into a single commit. If you've followed everything above, you can perform this action by doing:

git rebase -i origin/master

This will bring up your text editor with text like:

pick 749a62a Added a file pick ec9295b Changed some code pick be33007 Fixed my bug in that file

Change all but the first "pick" to "squash":

pick 749a62a Added a file squash ec9295b Changed some code squash be33007 Fixed my bug in that file

Save the file. Another file will open in your text editor which will allow you to edit the combined commit message. Be careful to only keep one of the  lines and have it be at bottom of the message after one empty line.

Push your change set to Gerrit
If you installed  and you ran   to set it up for this repository, the command to push changes to Gerrit is very simple: git review -R The  option does not automatically perform a rebase before submitting the change to Gerrit.



Upon success, you'll get a confirmation and a link to the changeset in Gerrit.

(If you forgot to run, "remote" will complain about "missing Change-id in commit message". But it will also suggest a commit message with a Change-Id: INNNXXXNNN... line. Copy that line starting with "Change-Id", run  , and paste the Change-Id line under your commit message in the text editor that opens up. Then repeat   and it should complete.)

You can view this change in the Gerrit Web UI:



If you want to see your changed files in their context then click on the  links and the   link (you then will see).

If your commit addresses a ticket in Phabricator, please comment on that ticket to note that the commit is in the merge queue, and link to its changeset in Gerrit.

Push to a branch
As you can see in the screenshot above, the commit was pushed to master. The branch name only appeared as the topic of the commit. If you really want to push to a branch, you have to push via.

Amending a change
BEWARE:  performs a hard reset that destroys all local changes. Stash or commit changes you wish to preserve first.

Sometimes, you might need to amend a submitted change. You can amend your own changes as well as changes submitted by someone else, as long as the change hasn't been merged yet.

Rebase to bring your local branch up to date with the remote. It's best to make rebase updates a separate patch, so that your code reviewers have an easy time seeing what changes you've made. Assuming you are using Gerrit, you can do this by clicking the "Rebase Change" button when viewing your patch in Gerrit's web interface.

If you have git-review, hard reset and checkout the change with this command: git review -d

Note, if you already have the change in a branch on your local repository, you can just check it out instead: git checkout

For example: git review -d 9332

Or, if you already have the branch, git checkout review/preilly/2012/bug12345 Should accomplish the same thing.

Next, make some changes. vim Example/Example.body.php

the files as needed, then commit the change (ensuring you are amending the commit): git add Example/Example.body.php git commit --amend



NOTE: DO NOT use the  flag to specify a commit summary: that will override the previous summary and regenerate the Change-Id. Instead, use your text editor to change the commit summary if needed, and keep the Change-Id line intact.

Push the change git review -R
 * The -R is important here. It tells git-review to not rebase your change against master, which clutters diffs between patch set 1 and 2.





git-review complains about multiple commits
If  asks you if you really want to submit multiple commits, and lists a bunch of unrelated commits from different branches, try either of these: git fetch --all git remote update

Both commands do exactly the same thing, they fetch objects from all remote repositories set. So just pick the command you remember easily and forget about the other one.



git complains "you are in the middle of a merge -- cannot amend"
When after rebasing and merging your git commit --amend

results in message: fatal: You are in the middle of a merge -- cannot amend.

apply these steps and reapply your changes git stash git reset --hard git checkout master git review -d git stash pop git commit -a --amend If, after  jenkins-bot emails 'This change was unable to be automatically merged with the current state of the repository. Please rebase your change and upload a new patchset. 'This might mean that server master branch now has merge conflicts with your patch. Check advanced Gerrit usage to see how to fix them.

Push using HTTPS
This method is helpful for submitting to changes to Gerrit when SSH is not functional.

For this the user needs the HTTP Password which can be generated in the Account Settings of Gerrit under the tab of HTTP Password. After generating the password the developer should commit all the changes for one patch under one single commit and use git push https://gerrit.wikimedia.org/r/p/mediawiki/core HEAD:refs/for/master The authentication credentials need to be entered to successfully submit the changes. The syntax given above is for Mediawiki core and will vary for extensions accordingly. For example if one is pushing to Extention:LiquidThreads then git push https://gerrit.wikimedia.org/r/p/mediawiki/extensions/LiquidThreads HEAD:refs/for/master

Commit Hook and Change-ID
A major problem that arises when using HTTPS for submitting changes is that commit hook is not automatically attached. A hack for this approach is to make one fail attempt to push. On doing so, the error message will automatically highlight the Change-Id, see below example: Username for 'https://gerrit.wikimedia.org': xxxxxx Password for 'https://xxxxxx@gerrit.wikimedia.org': Counting objects: 25, done. Delta compression using up to 2 threads. Compressing objects: 100% (4/4), done. Writing objects: 100% (4/4), 448 bytes | 0 bytes/s, done. Total 4 (delta 3), reused 0 (delta 0) remote: Resolving deltas: 100% (3/3) remote: Processing changes: refs: 1, done remote: ERROR: missing Change-Id in commit message footer remote: Suggestion for commit message: remote: Commit message appears here remote: remote: Change-Id: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx remote: remote: Hint: To automatically insert Change-Id, install the hook: remote:  gitdir=$(git rev-parse --git-dir); scp -p -P 29418 xxxxxx@gerrit.wikimedia.org:hooks/commit-msg ${gitdir}/hooks/ remote: remote: To https://gerrit.wikimedia.org/r/p/mediawiki/extensions/Test ! [remote rejected] HEAD -> refs/for/master (missing Change-Id in commit message footer) error: failed to push some refs to Now copy the change ID and amend your commit. Always add Change-ID as the last line of your commit message. git commit --amend This will open an editor to change the commit message. Paste the Change-Id as the last line of the message and save it. See example: Your commit summary Your commit message Bug: Txxxxx Change-Id: xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx Now you can successfully push to Gerrit.

Automatically adding commit Hook
To obtain the commit-msg script: scp -p -P 29418 USERNAME@gerrit.wikimedia.org:hooks/commit-msg /.git/hooks/ See https://gerrit.wikimedia.org/r/Documentation/cmd-hook-commit-msg.html for details.

Proxy servers
If you are behind a proxy server, you also need to clone over HTTPS. Make sure the environment variable  is set correctly. To debug issues, try running with, e.g.

In case of issues, try providing  directly, e.g.

or use git's options directly:

This last option should also work for SOCKS proxy servers, using

Diff algorithm
Gerrit uses jGit's diff, which uses a slightly different diff algorithm from git's default diff algorithm.

To see roughly what a patch will look like in Gerrit, run.

If jgit isnt available in your packaging system, download jgit.sh from https://eclipse.org/jgit/download/ and use jgit.sh instead of jgit.

How we review code
Code review is an essential part of our contribution workflow. The principle is basic: any patch must be reviewed by others before being merged.

This means that your code will need reviewers. Check our advice for getting reviews.

Review before merge
It's important to us to have a review-before-merge workflow for MediaWiki core and also for any extension we deploy. We will also offer that option to any extension author who wants it for their extension. The one exception is localisation and internationalisation commits, which will be able to be pushed without review.

Who can review? Gerrit project owners
Who has the ability to do code review?

We use gerrit.wikimedia.org to manage code review. Anyone can ask for a Gerrit account – get one!. Within Gerrit, anyone can comment on commits and signal their criticisms and approvals. Anyone can give a nonbinding "+1" to any commit. However, for any given repository ("Gerrit project"), only a small group of people will have the ability to approve code within Gerrit and merge it into the repository. This superapproval is a "+2" even though that's a misleading name, because two +1 approvals DO NOT add up to a +2. These people are "Gerrit project owners". Learn about becoming a Gerrit project owner.

Even within a Gerrit project, we can also specify particular branches that only specific people can pull into.

How to comment on, review, and merge code in Gerrit
Anyone can comment on code in Gerrit.

Viewing and commenting on code

 * Make sure you have a https://gerrit.wikimedia.org login (Get an account!). If you don't know, try logging in at https://wikitech.wikimedia.org; the username and password should be the same.  If you can't, ask in  for someone to help.
 * Log in to Gerrit. If you know the changeset you want to look at (URL will look like https://gerrit.wikimedia.org/r/#change,8939 ), go to that. Otherwise, use the search box and try searching.  There is no fulltext search in Gerrit, but you can search by author ("Owner"), Gerrit project, branch, changesets you've starred, etc. The Gerrit search documentation covers all of the different search operators you can use.
 * The changeset has a few important fields, links and buttons:
 * Reviewers. 'jenkins-bot' is the autoreviewer that auto-verifies anything that passes the Jenkins tests. It will report a red or green mark depending on whether the build passes.
 * Add reviewer. Manually pings someone to request their review. It'll show up in their Gerrit dashboard.
 * Side-by-side diff. Opens the diff. You can double-click on a line and comment on that line, then save a draft comment! Then, click "Up to change" to go back to the changeset, proceed to.
 * Review ("Add comment"). Publish your thoughts on the commit, including an overall comment and/or inline comments you added (see above).
 * If, upon code review, you approve, use "+1" under Code Review; otherwise, use "-1" to disapprove. These numbers are nonbinding, won't cause merges or rejections, and have no formal effect on the code review.
 * Abandon change (you'll see this if you wrote this diff). This action removes the diff from the merge queue, but leaves it in Gerrit for archival purposes.

Comparing patch sets
Every time you amend your commit and submit it for review, a new patch set is created. You can compare the different patch sets like this:
 * Select the older patch set in the "Old Version History" list.
 * Expand the newer patch set details by clicking the arrow near it.
 * Click Side-by-Side. Note that in Gerrit 2.3 this only works if you open the diff in the same tab, so don't open it in a new tab.

Formally reviewing and merging or rejecting code
If you are one of the Gerrit project owners, you'll also see:
 * Abandon Change button
 * on the Review page, additional Code Review options to +2 (approve) or -2 (veto) a diff, and a Publish And Submit button (publish your comment and merge diff into the branch, in 1 step)
 * Submit Patch Set 1 button (merge -- only useful if you or someone else has already given a +2 approval to the diff, but not merged it)

And once you've merged something into the example Gerrit project you'll see it in https://gerrit.wikimedia.org/r/gitweb?p=test/mediawiki/extensions/examples.git;a=summary.

If you merge a commit that references a ticket in Phabricator, please go to that ticket and mark it RESOLVED and reference the merge ID.

Troubleshooting
Problems encountered installing commit-msg hook

If you encounter this error when trying to push changes using git-review, you are not working with a repository that was cloned via ssh. You must clone repositories using ssh, not http or https, to succesfully push changes using git-review.