Gerrit/Advanced usage

This is an extensive explanation of the workflow a patch follows from creation to review and merge.

For a simple description of how to submit a patch, see Git/Getting started.

Setup
To start contributing code you need:


 * Git installed and configured.
 * git-review installed and configured.
 * A Gerrit account.
 * A SSH key connected to your Gerrit account.
 * A repository clone of the project you want to contribute to.

How to submit a patch

 * 1) Update master.
 * 2) Create a branch.
 * 3) Make and commit your change.
 * 4) Prepare to push your change set to Gerrit.
 * 5) Push your change set to Gerrit
 * 6) Amending a change

Howto - Merging your amend back into your branch
''This section is optional. It's offered as a convenience way to offer your a solution to a common problem. At this stage, your new changeset is already in Gerrit.''

After you have amended your change, you may want to merge it back into your local branch.

You can do this by going to the Gerrit change in question.

Here is an example:

https://gerrit.wikimedia.org/r/#/c/7669/4

Go to the Download section and copy cherry pick.

We will select patch set 4.

Switch back to your branch. You will be in your review branch where you just made your change.

Note: use the branch relevant to your change number.

Paste in the cherry pick and merge any conflicts.

Perform a git add on the modified files.

Do not forget to check your status and run a diff.

You should see there are no differences:

Then commit the changes:

Submitting a change to a branch for review
In this example, we'll merge from   to.

Before you start, look up the git commit hash of the commit that was merged into master. This can be found on the Gerrit change page. Scroll down to the last Patch Set, and to the left of "(gitweb)" is the git commit hash (not to be confused with the Gerrit Change id). Make sure that the commit was indeed merged into the master branch. If it wasn't then wait with submitting the change to a branch until it has been reviewed and merged in master - until then the commit may still be amended (and we wouldn't want to merge the wrong version).

Here it goes, using :

As a result:
 * https://gerrit.wikimedia.org/r/25756 is created for review.
 * shows both the original and the merge changes

Acting on remote branches
By default, your local clone will only have a local master branch set up to track the remote master branch. Tracking means that whenever you fetch objects from the remote repository, git status or git branch will be able to tell you how up-to-date is your local branch, which is very useful. So, whenever you want to regularly act on a remote branch (lets says REMOTE_BRANCH, you want to setup a one locally (REMOTE_BRANCH too to easily remember about it) that track it (with -t).

will give the full details:

Pushing having used automatic setup
From : git-review accepts, as an optional argument, the branch name to interact with. When that argument is not specified, it falls back to look for the defaultbranch parameter in a .gitreview file at the root of the repository.

Every branch should have a .gitreview having a correct defaultbranch value. For mediawiki/core.git, else people will have to use something like:.

Pushing having used manual (Windows) setup
To change where you push to for review having performed a manual setup, run git config alias.push-for-review "push gerrit HEAD:refs/for/BRANCH_NAME" to override the local alias, then use git push-for-review as per usual.

Committing to non master
To make a change to the 1.17 branch, create a branch and tag, and push both:

Partial revert of previous commit
Can be find in gerrit patch view in small letters next to text Patch Set N. Then push for review normally.

SSH and "permission denied (publickey)"
If you get the error Then you're not logged in to your ssh key right now. Solution: do  to make it prompt you for the passphrase for your key and add it to the active keychain. Then you can check what's in your keychain with. Then try pushing for review again.

The fingerprint of the Gerrit server is

dc:e9:68:7b:99:1b:27:d0:f9:fd:ce:6a:2e:bf:92:e1

so you can say yes when it asks you to add that fingerprint to the known hosts file.

Keep in mind that gerrit listens on port 29418 and if for some reason you forgot to specify port number, you might be hitting "normal" SSH daemon listening on port 22 (this one has RSA key fingerprint b5:e9:dc:b2:dd:6e:70:f7:18:8a:dc:a3:5d:ab:99:4d).

To check whether SSH connectivity and public key authentication work you can use:

"[remote rejected] master -> master" and "failed to push some refs"
If you forget to add HEAD:refs/for/master as an alias, you will receive something along the lines of:

This means you tried to commit to branch "master" instead of submitting your changes for review.

Email doesn't match
remote: ERROR: committer email address (email) remote: ERROR: does not match your user account.

There are two possible problems that could cause this error. If the email address that git pops back _is_ the email address you intend to use with Gerrit, then you should add that email address in Gerrit, and make sure you click the confirmation link in the email Gerrit sends you. Then try pushing again.

If, however, git sends back some nonsense email (like one you don't use anymore, or a local mail address like root@localhost), you should do the following:

To do it locally for just that repo, instead do:

Then, try pushing again.

Build failed due to merge conflict
After `git review` 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.


 * Make sure your master branch hard-reset to the gerrit's master
 * Checkout for review, rebase, recommit

Working tree is dirty
Note: if upon doing 'git review' you receive a message "Working tree is dirty" try doing 'git add' for the file(s) changed (or created), then 'git commit', and then 'git review'. This was seen on OSX with an older git client.

missing Change-Id in commit message
Note: if upon doing 'git review' you receive a message about 'missing Change-Id', then your /.git/hooks/commit-msg is probably incorrect. it should look something like:

CHANGE_ID_AFTER="Bug|Issue" MSG="$1"

add_ChangeId { clean_message=`sed -e ' /^diff --git a\/.*/{ s/// q               } /^Signed-off-by:/d /^#/d ' "$MSG" | git stripspace` if test -z "$clean_message" then return fi
 * 1) Check for, and add if missing, a unique Change-Id

You will also get a missing Change-ID message when trying to merge some change from git that does not have. It seems that the hook isn't called by cherry-pick, but it is fortunately called by.

In the example below we will be moving trivial change bd7a268e4be2da23ba0b9943c3b0ba1ac88294dc from git master in the mediawiki/core project (it came via SVN trunk) to REL1_19.

Sample session to exhibit this problem:

(...full trivial diff to one file omitted...)

To fix this, use  (don't commit) option to  : git cherry-pick -n bd7a268e4be2da23ba0b9943c3b0ba1ac88294dc git commit -c bd7a268e4be2da23ba0b9943c3b0ba1ac88294dc

Unfortunately, if you want to add the original commit ID to the message (as done by ) you have to add it yourself.

The change above has been submitted as 3c88c61f1b7e36d5d374a42bb0f50783ab5391a4 for  review.

Don't push
If you attempt to do 'git push' after doing 'git commit' you may receive a response 'Everything up-to-date'. You have not pushed to the branch. You have to do 'git review' to move your changes to gerrit, and only from gerrit will the branch be updated. This seems to be a side effect of checking out master as a branch as of February 2012.

In some projects (e.g. test/) it is possible to do 'git push' instead of 'git review' and have the push succeed. It is probably better not to do that, as it confuses those who find your changes later and don't know where they came from.

git review complains about multiple commits
If git review asks you if you really want to submit multiple commits, and lists a bunch of unrelated commits from different branches, try this:

git fetch --all git remote update

git review doesn't like merge commits
If you merged a development branch, and now want to submit a merge commit to Gerrit, git review</tt> may not let you. It may ask you for submitting lots of changes from one of the merged branches, or otherwise mange the commit. To avoid this, push the commit directly to Gerrit, bypassing git review</tt>:

git push gerrit HEAD:refs/for/master

For more information, see the Gerrit documentation.

Unlink bogus dependencies (rebase changes)
Example for https://gerrit.wikimedia.org/r/#change,5154

git fetch --all # To make sure we have latest changes git review -d Ie6e3c9be git rebase -i gerrit/master # Delete the commits you want to get rid of git commit --amend # Add a note git review -f # -f deletes the branch after submit

Maybe also have look at Gerrit/resolve conflict

Create a dependency
If you are about to create a patch that depends on another (unmerged) patch, or if you already submitted a patch but need to fix the dependency (i.e. currently it is based on master and would break if merged without the dependency, or maybe you squashed your change on top of the dependency). Then this is the section you're looking for. If you want to fix the patch to have the right dependency rather than to create a new patch with a dependency, then make sure your working copy is clean (no uncommitted changes).

git fetch --all # Make sure we have latest info from the repository git review -d 1234 # Gerrit change number of the change you want as dependency ("parent")

Now we need to make sure the patch has the correct git-parent. Depending on whether you are creating a new patch or fixing an existing patch, there is two different ways to do this. If you are starting fresh: git checkout -b bug/1234 # Creates a new branch, with the current branch (the dependency) as parent git add someFile.php some/other/file.js git commit # Commit your patch
 * 1) Edit files: make your changes

git log -n5 --decorate --pretty=oneline # Verify that the last 5 entries of the log now start with:
 * 1) * (HEAD, bug/1234) your change
 * 2) * (review/john/700) the dependency
 * 3) * (gerrit/master)

git push gerrit HEAD:refs/for/master # Use this instead of `git review`

If you need to amend your patch to have the correct dependency: git branch # Take note of the review/* branch that was created for this, it has an "*" in front of it git checkout bug/1234 # Check out the local topic branch of your change git rebase review/john/7000 # The branch name of the gerrit change we checked out earlier


 * 1) Resolve conflicts if needed,
 * 2) - use "git status" to see the files that need resolution
 * 3) - after fixing it in your editor, "git add filename" for each of the fixed files

git commit --amend -c HEAD # Re-commit your patch replacing the one with the wrong parent

git log -n5 --decorate --pretty=oneline # Verify that the last 5 entries of the log now start with:
 * 1) * (HEAD, bug/1234) your change
 * 2) * (review/john/700) the dependency
 * 3) * (gerrit/master)

git push gerrit HEAD:refs/for/master # Use this instead of `git review`

The  directly will make sure that the dependency is kept and the other revisions that are already in gerrit will not be re-submitted.

Splitting a commit in smaller one
Mixing out changes is probably not the best to do nowadays :-D You could split the patch by using something like: git-review -d 4381 git rebase 0d3c396^ git cherry-pick -n 0d3c396 You should now have all changes not staged for commit. Create a topic branch and select the chunks you want by to craft a new commit. git checkout -b language_converter git add --patch You will then be asked what to do with each of the chunk. `?` gives you an help menu, `y` stage the chunk, `s` split it in smaller parts, `n` do not stage it. Then `git diff --cached` to review change and as usual `git commit && git-review -f`
 * 1) Move back to parent of patch set 1
 * 1) Apply patch set 1 changes without generating a commit

How we review code
The things we look for in code won't change, but the workflow is different than it was before the Git switch.

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 extensions author who wants it for their extension. (The default is to use the current model we've been using with Subversion -- pushed and automatically merged.) For this decision we will defer to whoever is considered the primary author on the extension. See Git/Gerrit project ownership.

The one exception is i18n 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 to manage code review. Anyone can ask for a Gerrit account (Get an account!). Within Gerrit, anyone can comment on commits and signal their criticisms and approvals. Anyone can give a nonbinding "+1" to any commit (this is like "inspection" and "signoff" in the old Subversion code review interface). 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. (Within gerrit, 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".  To learn about becoming a Gerrit project owner, see Git/Gerrit project ownership.

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

To make a new Project Owner:
 * Create a group
 * Give it ownership of a Project
 * Anyone in that group can now add more owners via https://gerrit.wikimedia.org/r/#/admin/projects/ (but we prefer to keep that process public via Git/Gerrit project ownership)
 * Click Groups
 * As long as you are a member of the group, you can edit the group
 * example: https://gerrit.wikimedia.org/r/#/admin/projects/mediawiki,access

MediaWiki core
We are maintaining a "WMF" branch of mediawiki/core.git. We use submodules for deployed extensions, and can pull from master as regularly as we want for deployments. At the start of the migration to git, the project owners of this branch are going to be the people who have the ability to deploy code to Wikimedia Foundation servers. gerrit will offer a list of the "Gerrit project owners" for this branch, except for the Operations (system administration) group, which is an LDAP group. Every member of the Wikimedia Foundation operations team will also be in the Gerrit project owners group insofar as they have code review rights globally, but in practice will rarely review code. We may add some existing code reviewers to this Gerrit project owners group. Details; you can request to be added.

At the start of the migration, this list of Gerrit project owners for the WMF branch is also the list of Gerrit project owners for the master branch. However, eventually, we will add to the list of Gerrit project owners for master, using as criteria the number and quality of developers' previous commits and code reviews.

Details and procedure for adding and removing people from the Gerrit project owners groups.

MediaWiki has release branches (19 so far) for core, and master (the default branch previously known as "trunk" in SVN). Example: ("heads" is gitweb's term for branches). MediaWiki core and WMF-deployed extensions will be tagging releases just as we did in Subversion, except they'll be Git tags instead of SVN tags. Any other extension will make its own decisions regarding tagging.

MediaWiki extensions that the Wikimedia Foundation deploys
Same procedure as for MediaWiki core, and the same Gerrit project owner groups.

Other MediaWiki extensions
Every extension author can choose between two choices here for non-master branches: the gated-trunk/push-for-review model, and a straight push model. For any given extension, we will honor the wishes of the person/s listed as the main author on the extension's mediawiki.org page.


 * The gated-trunk/push-for-review is the model that we are using for MediaWiki core, as mentioned above. A Gerrit project owners group (plus the above mentioned Gerrit project owners group for MediaWiki core) will be able to "+2" (approve and merge) changes to their extensions.  The extension author(s) will be able to define a Gerrit project owners group and add others to it.


 * The straight push model is similar to how we did things in Subversion; anyone can suggest a change and submit a pull request, and it will automatically be approved and merged.

Master branches must go through Gerrit and cannot be straight push. This is necessary to facilitate a number of Gerrit features, including replication, updating of the extension meta-repository, and ability of Translatewiki to provide localization updates.

We could define groups to make this easier for batches of extensions (e.g. SMW developers). Chad will offer your community a choice. Please let Chad what you would like via Git/New repositories.

Other Gerrit projects
Same procedure as for "other MediaWiki extensions" above.

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://labsconsole.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,2713 ), 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 changeset has a few important fields, links and buttons:
 * Reviewers. 'jenkins-bot' is the autoreviewer that auto-verifies anything that passes the Jenkins tests. If it passes, you see a green checkmark. If it fails, a red X.  A changeset needs a green checkmark before anyone can merge it.
 * Add reviewer (manually ping someone to request their review. It'll show up in their Gerrit stream)
 * Old Version History dropdown menu. This menu will allow you to change what changes you're reviewing. This is helpful if you reviewed a past changeset, and want to make sure your changes were taken into account. Rather than reading through the entire changeset diff'd against the base commit, you can read only the differences between the current changeset and the changeset you reviewed. There's a bonus, too: You can see your comments on the left hand side of the If there was a rebase commit, there will be garbage in the diffs, but you can read things one changeset at a time and it will still be faster.
 * Diff All Unified button:
 * Opens the diff(s) in a new tab. 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.
 * For commits that contain whitespace changes (i.e. indent a block that was changed), it is best to set the diff-preferences appropriately to make it easier to review. When viewing a diff, on top there is a link "Preferences". Then there is two important settings to focus on. "Ignore Whitespace" and "Intraline Difference". The last one (Intraline Difference) is especially useful if a block of code was indented, as this setting will show the added tabs themselves allowing other changes to be recognizable without having to compare every word in your mind (see screenshot).
 * Abandon Change button (you'll see this if you are the creator of this change set. This action removes the change set from the merge queue, but leaves it in Gerrit for archival purposes)
 * Review button:
 * On this page you can leave an overall comment, view inline comments from the diff that are still in draft form and awaiting publication, and signal your thoughts on the commit. You can signal approval with a "+1" and disapproval with a "-1".  These numbers are nonbinding, won't cause merges or rejections, and have no formal effect on the code review.  To publish your draft inline comments plus your comments on the diff as a whole, click Publish.

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 Bugzilla bug, please go to that bug and mark it RESOLVED: FIXED and reference the merge ID.


 * ''Teacher: for this section, add the participant to the project owner group for the  Gerrit project at https://gerrit.wikimedia.org/r/#/admin/groups/17,members . Add the "Member" by email or wiki username.

How to comment on, review, and merge code in Eclipse
As an alternative to Gerrit's web interface, you can also review code from Eclipse using the Mylyn task-management framework. To get started, download and install Eclipse, and then download Mylyn and install it by unzipping it in the base Eclipse folder. When you next launch Eclipse, you'll be prompted to add a task for Mylyn. From there, you'll need to install the connector for Gerrit, specify  as the server URL, and add your username and password.

Your change could not be merged due to a path conflict
If you get the error "Your change could not be merged due to a path conflict" when submitting a change set in Gerrit, you need to resolve the conflict in a manner very similar to how you would in SVN.
 * 1) Make sure your master branch is up to date: git pull master</tt>
 * 2) Create and switch to a new branch in which to checkout the change set with the conflict: git checkout -b BRANCHNAME</tt>
 * 3) Checkout the conflicting change set into this branch. You can copy/paste the correct command from the 'Download' section in the Gerrit review. It will look something like this: git fetch ssh://awjrichards@gerrit.wikimedia.org:29418/mediawiki/extensions/MobileFrontend refs/changes/38/3538/2 && git checkout FETCH_HEAD</tt>
 * 4) Rebase against master (this should give you a conflict warning. this is OK!): git rebase master</tt>
 * 5) Open the file(s) with the conflict, and resolve them. They will be denoted the same way they are in SVN (with <<<<< >>>>>)
 * 6) Once you have finished resolving the conflicts, you need to git add the file again. For instance: git add HtmlFormatter.php</tt>
 * 7) Tell the rebase to continue now that the issue is resolved: git rebase --continue</tt>
 * 8) Push the resolved conflict to Gerrit for review: git review</tt>
 * 9) Re-review the change set in Gerrit, and then submit the changes to be merged to master.

Your change requires a recursive merge to resolve
If you get the error "Your change requires a recursive merge to resolve", you need to rebase the change set against master.
 * 1) Make sure your master branch is up to date: git pull origin master</tt>
 * 2) Create and switch to a new branch in which to checkout the change set with the conflict: git checkout -b BRANCHNAME</tt>
 * 3) Checkout the conflicting change set into this branch. You can copy/paste the correct command from the 'Download' section in the Gerrit review. It will look something like this: git fetch ssh://awjrichards@gerrit.wikimedia.org:29418/mediawiki/extensions/MobileFrontend refs/changes/14/3414/3 && git checkout FETCH_HEAD</tt>
 * 4) Rebase against master: git rebase master</tt>
 * 5) Push the change to Gerrit for review: git review</tt>
 * 6) Re-review the change set in Gerrit, and then submit the changes to be merged to master.

How to create a repository ("Gerrit project")
See "Request a new Git repository". There's a form to fill out. It should get processed very quickly (within a couple of days).