| :linkattrs: |
| = Gerrit Code Review - Submitting Changes Across Repositories by using Topics |
| |
| == Goal |
| |
| This document describes how to propose and submit code changes across multiple |
| Git repositories together in Gerrit. |
| |
| == When to Use |
| |
| Oftentimes, especially for larger code bases, code is split across multiple |
| repositories. The Android operating system’s code base, for example, consists of |
| https://android.googlesource.com/[hundreds] of separate repositories. When |
| making a change, you might make code changes that span multiple repositories. |
| For example, one repository could define an API which is used in another |
| repository. Submitting these changes across these repositories separately could |
| cause the build to break for other developers. |
| |
| Gerrit provides a mechanism called link:intro-user.html#topics[Topics] to submit |
| changes together to prevent this problem. |
| |
| |=== |
| |NOTE: Usage of topics to submit multiple changes together requires your |
| Gerrit host having |
| link:config-gerrit.html#change.submitWholeTopic[config.submitWholeTopic] set to |
| true. Ask your Gerrit administrator if you're not sure if this is enabled for |
| your Gerrit instance. |
| |=== |
| |
| == What is a Topic? |
| |
| * A topic is a string that can be associated with a change. |
| * Multiple changes can use that topic to be submitted at the same time (assuming |
| approvals, etc.). |
| * Submitting a change with a topic causes all of the changes in the topic *to be |
| submitted together* |
| ** Topics that span only a single repository are guaranteed to be submitted |
| together |
| ** Topics that span multiple repositories simply triggers submission of all |
| changes. No other guarantees are given. Submission of all changes could |
| fail, so you could get a partial topic submission. This is very rare but |
| can happen in some of the following situations: |
| *** Storage layer failures. This is unlikely in single-master installation and |
| more likely with multi-master setups. |
| *** Race conditions. Concurrent submits to the same repository or concurrent |
| updates of the pending changes. |
| |
| Here are a few intricacies you should be aware of: |
| |
| 1. Topics can only be used for changes within a single Gerrit instance. There is |
| no builtin support for synchronizing with other Gerrit or Git hosting sites. |
| |
| 2. A topic can be any string, and they are not namespaced in a Gerrit instance; |
| there is a chance for collisions and inadvertently grouping changes together |
| that weren’t meant to be grouped. This could even happen with changes you can’t |
| see, leading to more confusion e.g. (change not submittable, but you can't see |
| why it's not submittable.). We suggest prefixing topic strings with the author’s |
| username e.g. “username-” to help avoid this. |
| |
| You can view the assigned topic from the change screen in Gerrit: |
| |
| image::images/cross-repository-changes-topic.png[width=600] |
| |
| === Topic submission behavior |
| * Submitting a topic will submit any dependent changes as well. For example, |
| an unsubmitted parent change will also be submitted, even if it isn’t in the |
| original topic. |
| * A change with a topic is submittable when *all changes* in the topic are |
| submittable and *all of the changes’ dependent changes* (and their topics!) |
| are also submittable. |
| * Gerrit calls the totality of these changes "Submitted Together", and they can |
| be found with the |
| link:rest-api-changes.html#submitted-together[Submitted Together endpoint] or |
| on the change screen. |
| |
| image::images/cross-repository-changes-submitted-together.png[width=600] |
| |
| * A submission creates a unique submission ID |
| (link:rest-api-changes.html#change-info[`submission_id`]), which can be |
| used in Gerrit's search bar to find all the submitted changes for the |
| submission. This ID is relevant when <<reverting,reverting a submission>>. |
| |
| To better underestand this behavior, consider this following example. |
| |
| [[example_submission]] |
| === Example Submission |
| |
| image::images/cross-repository-changes-example.png[width=600] |
| |
| * Two repositories: A and B |
| * Two changes in A: A1 and A2, where A2 is the child change. |
| * Two changes in B: B1 and B2, where B2 is the child change. |
| * Topic X contains change A1 and B1 |
| * Topic Y contains change A2 and B2 |
| |
| Submission of A2 will submit all four of these changes because submission of A2 |
| submits all of topic Y as well as all dependent changes and their topics i.e. A1 |
| and topic X. |
| |
| Because of this, any submission is blocked until all four of these changes are |
| submittable. |
| |
| |=== |
| | Important point: B1 can unexpectedly block the submission of A2! |
| This kind of situation is hard to immediately grok: B1 isn't in the topic you're |
| trying to submit, and it isn't a depnedent change of A2. If your topic isn’t |
| submittable and you can’t figure out why, this might be a reason. |
| |=== |
| |
| == Submitting Changes Using Topics |
| |
| === 1. *Associate the changes to a topic* |
| |
| The first step is to associate all the changes you want to be submitted together |
| with the same topic. There are multiple ways to associate changes with a topic. |
| |
| ==== From the command line |
| You can set the topic name when uploading to Gerrit |
| |
| ---- |
| $ git push origin HEAD:refs/heads/master -o topic=[YOUR_TOPIC_NAME] |
| ---- |
| |
| *OR* |
| |
| ---- |
| $ git push origin HEAD:refs/for/master%topic=[YOUR_TOPIC_NAME] |
| ---- |
| |
| If you’re using https://source.android.com/setup/develop[repo] to upload a |
| change to Android Gerrit, you can associate a topic via: |
| |
| ---- |
| $ repo upload -o topic=[YOUR_TOPIC_NAME] |
| ---- |
| |
| If you’re using |
| https://commondatastorage.googleapis.com/chrome-infra-docs/flat/depot_tools/docs/html/depot_tools.html[depot_tools] |
| to upload a change to Chromium Gerrit, you can associate a topic via: |
| |
| ---- |
| $ git cl upload --topic=[YOUR_TOPIC_NAME] |
| ---- |
| |
| ==== From the UI |
| |
| If the change has already been created, you can add a topic from the change page |
| by clicking ADD TOPIC, found on the left side of the top of the Change screen. |
| |
| image::images/cross-repository-changes-add-topic.png[width=600] |
| |
| === 2. *Go through the normal code review process* |
| |
| Each change still goes through the normal code review process where reviewers |
| vote on each change individually. The changes won’t be able to be submitted |
| until *all* changes in the topic are submittable. |
| |
| The requirements for submittability vary based on rules set by your repository |
| administrators; often this includes being approved by all requisite parties, |
| passing presubmit testing, and being able to merge cleanly (without conflicts) |
| into the target branch. |
| |
| === 3. *Submit the change* |
| |
| When all changes in the topic are submittable, you’ll see *SUBMIT WHOLE TOPIC* |
| at the top of the _Change screen_. Clicking it will submit all the changes in |
| "Submitted Together." |
| |
| image::images/cross-repository-changes-submit-topic.png[width=600] |
| |
| [[reverting]] |
| == Reverting a Submission |
| |
| After a topic is submitted, you can revert all or one of the changes by clicking |
| the *REVERT* button on any change. |
| |
| image::images/cross-repository-changes-revert-topic.png[width=600] |
| |
| This will give you the option to either revert just the change in question or |
| the entire topic: |
| |
| image::images/cross-repository-changes-revert-topic-options.png[width=600] |
| |
| Reverting the entire submission creates revert commits for each change and |
| automatically associates them together under the same topic. To submit |
| these changes, go through the normal review process. |
| |
| When submitting a topic, dependent changes and their topics are submitted as |
| well. The RevertSubmission creates reverts for all the changes that were |
| submitted at that time. When reverting the submission described in |
| <<example_submission,Example Submission>>, all 4 of those changes will get |
| reverted. |
| |
| |=== |
| | NOTE: We say “reverting a submission” instead of “reverting a submitted |
| topic” because submissions are defined by submission id, not by the topic |
| string. So even though topics names could be reused, this doesn't effect |
| reverting. For example: |
| |
| 1. Submission #1 uses topic A |
| |
| 2. Later, Submission #2 uses topic A again |
| |
| Reverting submission #2 only reverts the changes in that submission, not all |
| changes included in topic A. |
| |=== |
| |
| == Cherry-Picking a Topic |
| |
| You may want to cherry-pick the changes (i.e. copy the changes) of a topic to |
| another branch, perhaps because you have multiple branches that all need to be |
| updated with the same change (e.g. you're porting a security fix across |
| branches). Gerrit provides a mechanism to create these changes. |
| |
| From the overflow menu (3 dot icon) in the top right of the Change Screen, |
| select “Cherry pick.” In the screenshot below, we’re showing this on a |
| submitted change, but this option is available if the change is pending as |
| well. |
| |
| image::images/cross-repository-changes-cp-menu.png[width=600] |
| |
| Afterwards, you’ll be presented with a modal where you can “Cherry Pick entire |
| topic.” |
| |
| image::images/cross-repository-changes-cp-modal.png[width=600] |
| |
| Enter the branch name that you want to target for these repositories. The |
| branch must already exist on all of the repositories. After clicking |
| “CHERRY PICK,” Gerrit will create new changes all targeting the entered |
| branch in their respective repositories, and these new changes will all be |
| associated with a new, uniquely-generated topic name. |
| |
| To submit the cherry-picked changes, go through the normal submission |
| process. |
| |
| |=== |
| | NOTE: You cannot cherry pick two or more changes that all target the same |
| repository from the Gerrit UI at this time; you’ll get an error message saying |
| “changes cannot be of the same repository.” To accomplish this, you’d |
| need to do the cherry-pick locally. |
| |=== |
| |
| == Searching for Topics |
| |
| In the Gerrit search bar, you can search for changes attached to a specific |
| topic using the `topic` operator e.g. `topic:MY_TOPIC_NAME`. The `intopic` |
| operator works similary but supports free-text and regular expression search. |
| |
| You can also search for a submission using the `submissionid` operator. Topic |
| submission IDs are "<id>-<topic>" where id is the change number of the change |
| that triggered the submission (though this could change in the future). As a |
| full example, if the topic name is my-topic and change 12345 was the one that |
| triggered submission, you could find it with `submissionid:12345-my-topic`. |
| |