Gerrit/Advanced usage
The basic instructions to set up and operate with Git and Gerrit are described at the Tutorial (see also its shortest version).
Warning
This page mostly documents how to do things "the hard way" in Gerrit.
The git review
tool continues to improve, and now contains built-in mechanisms to push to a branch, upload a set of dependent patches, etc.
You should probably review man git review
before deciding that you need to proceed further here.
Installation
Setup SSH shortcut (optional)
It's easier to access the repository if you don't have to specify the full yourusername@gerrit.wikimedia.org:29418 every time.
You can edit your ~/.ssh/config
file and add
Host gerrit Hostname gerrit.wikimedia.org Port 29418 User yourusername
Then you can use "Gerrit" instead.
Submitting patches
Setting up a repository for git-remote
Most repositories should already have information for git-remote where your repository is and what the name of the master branch is.
The information is stored in a .gitreview
file in the root of the repository.
If this file does not exist yet, you need to create and commit it.
The format is the following:
[gerrit]
host=gerrit.wikimedia.org
port=29418
project=operations/puppet.git
defaultbranch=production
The host
and project
fields are mandatory.
The other fields are optional:
port
defaults to 29418.
defaultbranch
defaults to master
.
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.
git checkout mingle-fr-2012-59
Paste in the cherry pick and merge any conflicts.
git fetch ssh://<USERNAME>@gerrit.wikimedia.org:29418/mediawiki/extensions/DonationInterface refs/changes/69/7669/4 && git cherry-pick FETCH_HEAD
Perform a git add on the modified files.
git add payflowpro_gateway/payflowpro.adapter.php
Do not forget to check your status and run a diff.
git diff
You should see there are no differences:
diff --cc payflowpro_gateway/payflowpro.adapter.php
index d7e510a,738c9df..0000000
--- a/payflowpro_gateway/payflowpro.adapter.php
+++ b/payflowpro_gateway/payflowpro.adapter.php
Then commit the changes:
git commit -m 'Merging patch set 4.'
[mingle-fr-2012-59 4e82e5a] Merging patch set 4.
1 files changed, 3 insertions(+), 3 deletions(-)
Submitting a change to a branch for review ("backporting")
- See also Backporting fixes , which discusses backporting changes to MediaWiki core (coordinate with the WMF Release Engineering Team, handling in Phabricator , etc.)
In this example, we will backport Gerrit #Ib27792 from master
to REL1_20
.
The basic idea is to use git cherry-pick
to apply the changes from the commit to master to a different branch.
(Note that this can also be done via the Gerrit web interface, with the 'Cherry Pick' button.)
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 the git commit hash is between "Patch Set NN" and "(gitweb)" (not to be confused with the Gerrit Change id which starts with a capital 'I'). Make sure that this commit was indeed merged into the master branch. If it wasn't then wait until it has been reviewed and merged in master — the commit may still be amended and we don't want to merge an old version.
$ git fetch origin
# The git commit hash of the change in master.
$ git show d4f2c0e8f76a7634fce1631669f4ce037965d8b5
$ git checkout origin/REL1_20
$ git reset --hard origin/REL1_20 # Ensure latest version, undo any local dependencies
$ git cherry-pick d4f2c0e8f76a7634fce1631669f4ce037965d8b5
# Do not change the commit message. In particular leave the
# "Change-Id" intact at the bottom of the message, since this is
# what Gerrit uses to relate the master change and the branch merge.
# If the merge causes conflicts, you should fix them manually,
# use git add <files> and run git commit. Move the "Conflicts" section
# of the commit message before "Change-Id", so "Change-Id" remains at
# the bottom of the message, otherwise the push will be rejected.
# Verify history looks as expected
$ git log --graph --decorate --oneline -n5
# View the original change in Gerrit and look up the topic-name,
# then use it below in place of "topic-name", e.g. "refs/for/REL1_20/bug/36151"
# or "refs/for/wmf/1.21wmf1/my-topic-name"
$ git push origin HEAD:refs/for/REL1_20/bug/36151
remote:
remote: New Changes:
remote: https://gerrit.wikimedia.org/r/25756
remote:
* [new branch] HEAD -> refs/for/REL1_20/bug/36151
- Is there any need to use complicated
git push
instead ofgit review
here? -- S Page (WMF) (talk) 02:28, 17 May 2013 (UTC)- The only reason would be so that you can give it a new topic. So alternatively, after the
git log
check, look up the topic name first (or think of a new topic) and dogit checkout -b random-new-topic-name
then followed by regulargit review -R
(instead of git push); as of git-review version 1.23, it will reuse the original topic. git review -R remote-branch-name
works too if you want to push to a remote branch from a review branch.
- The only reason would be so that you can give it a new topic. So alternatively, after the
As a result:
- https://gerrit.wikimedia.org/r/25756 is created for review.
- Gerrit #Ib27792 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).
git branch -vv
will give the full details:
$ git clone ...
$ git checkout -b REL1_19 -t gerrit/REL1_19
$ git branch -vv
REL1_19 3b2bfd3 [gerrit/REL1_19: ahead 1] .gitreview for REL1_19 branch
* master 13169c8 [gerrit/master: behind 1] * (bug 34212) ApiBlock/ApiUnblock a[...]
$
Pushing having used automatic setup
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: git-review BRANCH_NAME
.
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 create 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:
git checkout -b REL1_17 origin/REL1_17
<make code changes>
git add <files-changed>
git commit
git push gerrit REL1_17
git tag 1.17.3
git push --tags
Partial revert of previous commit
git show <commit> -- <path> | git apply -R
<commit> Can be found in gerrit patch view in small letters next to text Patch Set N. Then push for review normally.
Unlink bogus dependencies (rebase changes)
Example for gerrit: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
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 are looking for. If you want to fix the patch to have the right dependency rather than 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 are 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 # Edit files: make your changes git add someFile.php some/other/file.js git commit # Commit your patch git log -n5 --decorate --pretty=oneline # Verify that the last 5 entries of the log now start with: # * (HEAD, bug/1234) your change # * (review/john/700) the dependency # * (gerrit/master) git push gerrit HEAD:refs/for/master # or 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 # Resolve conflicts if needed, # - use "git status" to see the files that need resolution # - after fixing it in your editor, "git add filename" for each of the fixed files git rebase --continue git log -n5 --decorate --pretty=oneline # Verify that the last 5 entries of the log now start with: # * (HEAD, bug/1234) your change # * (review/john/700) the dependency # * (gerrit/master) git push gerrit HEAD:refs/for/master # or git review
git push gerrit HEAD:refs/for/master%topic=myawesometopic
or
git review -t myawesometopic
Cross-project dependencies
You can also use cross-project dependencies (e.g. an extension that requires a change in core before it can be merged).
You can accomplish this by adding e.g. Depends-On: I75b266da99e7dcb948f10d182e7f00bb3debfac6
in the footer of a commit message.
Use the full Change-ID (‘I’ + 40 characters).
See https://docs.openstack.org/infra/zuul/feature/zuulv3/user/gating.html#cross-project-dependencies for more details.
Examples: Gerrit:539718, Gerrit:534888
Splitting a commit into smaller ones
Explained in detail at Gerrit/split a submitted change .
Removing your local branch after submitting your change into Gerrit
you@yourmachine:~/puppet (production)$ git checkout -b mycoolfeature
you@yourmachine:~/puppet (mycoolfeature)$ vi foobar
you@yourmachine:~/puppet (mycoolfeature)$ git commit -a -m "Committing my cool feature"
you@yourmachine:~/puppet (mycoolfeature)$ git review -f
you@yourmachine:~/puppet (production)$
If the -f
flag is passed to git-review, it will try to submit the change, and if it succeeds it will switch back to the master branch (production in this case) and delete the feature branch.
Merging a submodule into a parent project
Using a personal sandbox for personal branches
Gerrit allows the creation of "personal sandboxes" where users can stash code that they are working on in a personal branch that doesn't require admin intervention for pushes. See Gerrit/personal sandbox.
Troubleshooting
For problems and how to solve them, see Gerrit/Troubleshooting.
Working on an existing change set
Sometimes you want to work on a change set started by some else and then upload your changes as a new patch set.
# Note in the gerrit URL the number reference to the change set,
# e.g., https://gerrit.wikimedia.org/r/#/c/70112/, thus 70112
# In your local copy of the master branch, pull down the change set
# and switch to that branch with the following command.
git review -d 70112
# Make any necessary changes and commit them as an amendment,
# adding appropriate comments to the commit message.
git commit --all --amend
# Push the patch set up to gerrit as usual.
git review -R
# Other developers can then update their local copy of the change set
# with the following command.
git review -d 70112
-m
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. (See: Amending_a_change)Manually rebase (on a branch)
Occasionally the rebase button in the Gerrit UI is unable to automatically rebase changes on the working branch and you have to perform the rebase on the command line:
# First download the current change set
$ git-review -d 424242
# Next make sure you have a fresh copy of the target branch ("main" in this case)
$ git fetch origin main
# Then rebase your change and fix any conflicts that may occur
$ git rebase -i origin/main
Manually rebase (on parent)
Sometimes the rebase button in the Gerrit UI is unable to automatically rebase a change in a change set on top of its parent and you have to perform the change on the command line.
$ PARENT=424242
$ CHILD=424243
# First get a reference to the latest PS in the parent change and check it out.
# You can get the link from the Gerrit UI: under the 'More' menu, select 'Download patch' and use the 'Checkout' link e.g.
$ git fetch "https://gerrit.wikimedia.org/r/operations/puppet" refs/changes/$i/${PARENT}/${PS} && git checkout FETCH_HEAD
# store this point in its own branch
$ git branch merge_${PARENT}
# checkout the child change
$ git-review -d ${CHILD}
# Rebase on the branch created earlier
$ git rebase -i merge_${PARENT}
# upload the change
$ git-review
Reviewing code
Viewing and commenting on code
The basic functionality is explained in the Git and Gerrit tutorial.
Some extra bits:
- Diff Against dropdown menu. This menu will allow you to change what changes you are 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. 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.
- Open All 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).
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 install Mylyn from the Install New Software menu (as of Oct 5th, 2013 you need the snapshots update site to use the Wikimedia Gerrit installation).
When you next launch Eclipse, you will be prompted to add a task for Mylyn.
From there, you will need to install the connector for Gerrit, specify https://gerrit.wikimedia.org/r/
as the server URL, and add your username and password.
How to review and merge code via command line
Using dippy-bird you can easily do command line review and merging. The query parameter is the change you want to deal with.
php dippy-bird.php --username=USERNAME --server=gerrit.wikimedia.org --port=29418 --action=submit --query=12345
You can therefore use that to approve a range of commits:
#!/bin/bash
for i in {51541..51545}
do
php dippy-bird.php --username=USERNAME --server=gerrit.wikimedia.org --port=29418 --action=submit --query=$i
done
Mass-approving changes across repositories
We might sometimes have to generates a ton of changes, for example when doing a similar change on all our repositories.
In the past, this happened after the MediaWiki extensions got migrated to Git since we had to add a .gitreview
file to each repository.
First, you can query gerrit for a list of change using the CLI! A useful alias:
alias gerrit='ssh -p 29418 gerrit.wikimedia.org gerrit'
Then use that to execute a query such as all open changes on topic dotgitreview:
gerrit query 'status:open topic:dotgitreview'
With some shell magic, you can get a list of change number:
gerrit query 'status:open topic:dotgitreview' \ | egrep '^ number' | cut -d\ -f4- > CHANGES_NUMBERS
Then loop on them and remotely approve the changes:
for i in `cat CHANGES_NUMBERS`; do gerrit review --verified=+1 --code-review=+2 --submit "$i,1"; done
Troubleshooting
For problems and how to solve them, see Gerrit/Troubleshooting.
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).
Other tips
Gerrit project dashboard
See also Documentation user-dashboards.
Each Gerrit repository has one or more dashboards that can be customised.
The default dashboard is shown when you click on a project link anywhere in Gerrit.
For example, clicking "mediawiki/core" on a commit page related to MediaWiki core will take you to https://gerrit.wikimedia.org/r/q/project:mediawiki%252Fcore.
In Gerrit, dashboards are created in groups.
Every repository inherits the "default" dashboard group from the "All-Projects" meta project.
By default a project's default dashboard defaults to "default:recent".
You can change what dashboard is used by default in the project.config
file in the refs/meta/config
branch of a repository.
Detailed instructions are below.
Refer to Module:Gerrit dashboard for more information.
It is recommended to add the following aliases to your .gitconfig
file.
See Git/aliases for more information.
[alias]
dashboards-checkout = "!f() { git fetch origin refs/meta/dashboards/teams:refs/meta/dashboards/teams && git checkout -B meta/dashboards/teams refs/meta/dashboards/teams; }; f"
dashboards-review = "!f() { git push origin HEAD:refs/for/refs/meta/dashboards/teams; }; f"
dash-co = dashboards-checkout
dash-review = dashboards-review
Manage a team dashboard
- For Wikimedia teams, we use the
wikimedia
parent repository to host team dashboards.- See Gerrit team dashboards to view examples.
- See wikimedia.git@refs/meta/dashboards/teams for the source code (Browse these files for examples of the file format and queries.)
- See Gerrit refs/meta/dashboard Code Review.
- Clone the repository if you haven't already,
git clone ssh://<gerrit-username>@gerrit.wikimedia.org:29418/wikimedia
- Check out the team dashboards branch
git dash-co
- Create (or edit) the dashboard configuration file for your team (lowercase with optional dashes, no file extension). See also Gerrit Documentation.
- Stage your changes and make a local commit.
- Push the commit for review
git dash-review
. You can generally self-merge these, but you can also propose changes for others to review if you prefer.
Go to Gerrit team dashboards and click on your dashboard. Or use the following URL pattern:
https://gerrit.wikimedia.org/r/p/wikimedia/+/dashboard/teams:my-file-name
A bad configuration/syntax error shows up as a 404 on the relevant dashboard. Files can be validated with:
git config -f FILE --list
Add team dashboard to "Your" menu
Add this to the "Your" menu in Gerrit for easy access:
- Visit your Gerrit settings
- Navigate to the "Menu" section of your settings.
- Add the url
/p/wikimedia/+/dashboard/teams:myteam
(for example) with a label that makes sense to you, like "My Team" - Consider also adding https://gerrit.wikimedia.org/r/admin/repos/wikimedia,dashboards as "All Teams" to easily get to other dashboards.
- Click "Save Changes" and reload the browser tab.
Bookmarklet to hide jenkins-bot comments
Execute this JavaScript to hide all comments from jenkins-bot.
Goes well with "Hide tagged comments" when you need to make sure all human feedback was addressed.
Prefix with javascript:
to add as a bookmarklet.[1]
Array.from(document.querySelectorAll('[class*=messageBox]')).filter(box => box.querySelector('[class*=name]').textContent === 'jenkins-bot').forEach(box => box.style.display = 'none')
Code Review links
Links to old SVN Code Review revisions are stored in commit notes. They may be fetched for display in the git log using the following command:
git fetch origin refs/notes/commits:refs/notes/commits
Note this must be done separately for each git repository.
Gerrit review scores
As above, code review metadata is stored in commit notes and may be fetched using:
git fetch gerrit refs/notes/review:refs/notes/review
To retrieve them regularly, add to your git config.
To display them in git log
(similar syntaxes work for related tools):
git log --notes=review
ssh proxy to gerrit
If gerrit is being slow, when it comes to uploading patches, it might be a network issue. (especially if you are in Europe, at certain times of the day) If you have a server / vm in the US or other proxy that you can use, then you can access gerrit via that.
In your ~/.ssh/config add something like:
Host gerrit.wikimedia.org
User aude
Port 29418
Hostname gerrit.wikimedia.org
IdentityFile=~/.ssh/gerrit
ProxyCommand nc -x 127.0.0.1:8081 %h %p
Then connect to the proxy (e.g. via ssh, with the "-D 8081" option). Then it should work to access gerrit to upload / download patches and may be faster.
Linking Gerrit URLs from Wikimedia wikis using internal link syntax
To link to Gerrit revision 1234 use [[gerrit:1234|revision 1234]]: revision 1234.
Changing the user associated with a commit
Gerrit will only accept patches committed under your registered email address. If you have multiple email addresses that you commit under (e.g. if you have "work" and "home" git settings that you want to keep distinct), you need to locally update the address you are committing under when you check out a repo.
git config user.email me@example.org
However, if you forget to do this after checking out and make a commit, you will need to update your configured email address and then fix that commit like so:
git commit --amend --no-edit --reset-author
If you want to avoid having to remember this, you can do the following in your .gitconfig
:
[includeIf "gitdir:~/src/mediawiki/"]
path = ~/.gitconfig-mediawiki
...and then create a .gitconfig-mediawiki:
# Anything in here will only be loaded in repos that are checked out under
# ~/src/mediawiki/
[user]
email = me@example.org
You can add any other mediawiki-development specific commands there that you'd like.
So long as you check out anything mediawiki-related into the ~/src/mediawiki
directory, that config file will be loaded and override your base gitconfig.
See also
- Git/Tips
- Gerrit/split a submitted change
- Gerrit/watched projects
- Gerrit/workflow/ops
- All pages under Git/ and Gerrit/
- Selection on externals links at the Git and Gerrit tutorial.
Notes
- ↑ bookmarklets — browser bookmarks that execute JavaScript instead of opening a webpage.