|  | :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`. | 
|  |  |