---
breadcrumbs:
- - /chromium-os/developer-library/guides
  - ChromiumOS > Guides
page_name: work-on-branch
title: ChromiumOS Guide to Working on Branches
---

This guide covers tips to work with branches. You may need to work on release
branches for ChromeOS versions e.g. `release-R76-12239.B`, or factory and
stabilize branches that serve a project-specific purpose
e.g. `stabilize-nocturne-10986.B`.

*** note
This applies to commits in ChromiumOS repositories. For changes to Chromium
repository branches, see the information about [Drover][drover];
for Blink, see [experimental branches][experimental-branches].
***

[TOC]

## Process: When to merge, How to get approval

Check out the Chromium [merge request] overview for details on branch
life-cycle, when to request merges and how to get approval for merging to
release branches. For project-specific factory and stabilize branches, a similar
process applies, except the approval comes from the kernel/firmware lead or
SIE on the project, rather than the ChromeOS TPM managing the release branch.

## Merge via Gerrit UI

The Gerrit UI contains a 'Cherry Pick' feature, you may need to click on the
&vellip; menu in the top-right to find it. This is currently the easiest way of
merging a change that does not have conflicts with the target branch. If the
change you want to merge to a branch is already on Gerrit, you need only a
browser.

1.   Open up the CL in question on Gerrit.
1.   Select "Cherry Pick" from the &vellip; menu in the top right.
1.   Enter the branch name, for instance **release-R58-9334.B**. The UI has
     an autocomplete feature for branch names to help you with this.
1.   Optionally you can edit the commit message, or specify a target git SHA
     to rebase your cherry-pick on top of (if you want to apply the change on
     top of a commit that is not the head of your target branch). Reasons for
     editing the commit message could be changing `Cq-Depend` directives as
     appropriate, explaining why the change is needed in the target branch
     or explaining any modifications or conflict-resolutions made while
     cherry-picking.
1.   Click "Cherry Pick" at the bottom of the pop up.
1.   This should create a new CL against that branch in Gerrit. To land the CL,
     mark it ready as usual. See the [contributing] guide for what votes you
     need to mark your CL as ready.

Note this only works if the patch applies cleanly on the target branch.
Otherwise, if there is a conflict then the merge must be done manually using one
of the methods below, or resolved via editing files directly in Gerrit.

To resolve simple conflicts manually in Gerrit:
1.   Cherry-picking via the UI will be interrupted before actually creating the
     cherry-picked CL.
1.   The UI will offer to create the cherry-picked CL (with conflicts) anyway.
     Create it.
1.   In the cherry-picked CL, click the "Edit" button to directly edit files
     that have conflict resolution markers in them (i.e. <<<<<<<), resolving all
     conflicts.

*** promo
Note: When to update ebuilds while merging changes

This works the same way on other branches as it does on [ToT].
If you're merging a change to code that is built as part of a `cros_workon`
package, or to a `.ebuild` file for a `cros_workon` package, the package will be
uprev-ed automatically.

If you're changing a non-`cros_workon` package, you must uprev the corresponding
`.ebuild` file on the branch manually, just as you do when making changes to
non-`cros_workon` packages on [ToT].
***

## Merge via Gerrit CLI

The `gerrit cherry-pick` tool uses the same backend APIs as the
[Gerrit UI](#merge-via-gerrit-ui).

```shell
gerrit cherry-pick --branches release-R76 1376991
```

The `--branches` option supports multiple branches and autocompletion.
If there is only one branch that matches `release-R76`, we will expand to the
full name for you.

Multiple CLs can be specified, but they will be cherry-picked independently.
This tool cannot be used to cherry-pick stacks of CLs that depend on each other.

## Check out the whole tree (with repo)

You must have different checkouts (yes, new chroots in a completely new
directory) for every branch you are working on. This is to ensure all the
prebuilts work automatically for you. You have to pass the -b <branch\_name>
option to repo during init and you will follow exactly the same workflow
described in the [ChromiumOS Developer Guide][developer-guide] i.e.
`cros_workon` and `repo start` etc.

**If you have an existing repo checkout**: You can run `repo init` with
`--reference` to re-use the objects of your existing checkout, to reduce sync
time. Note that an absolute path is required (`../../foo` won't work) and that
it must be the topmost directory of the existing repo checkout, i.e. the one
that contains the `.repo` directory.

You can find the exact name of the branch by browsing the
[manifest repo](https://chromium.googlesource.com/chromiumos/manifest/+refs).

```bash
mkdir release-R76-12239.B
cd release-R76-12239.B/
repo init <URL> -b <branchname> [-g minilayout] [--reference /path/to/existing/checkout]
repo sync
```

Example (See the [developer guide][developer-guide] if you are doing an internal build and
replace the manifest.git link with the appropriate one).

```bash
repo init \
    https://chromium.googlesource.com/chromiumos/manifest.git \
    -b release-R76-12239.B
```

Next, follow steps in the [developer guide][developer-guide] to
sync/edit/modify files i.e `repo sync`, `cros_workon start`, `repo start`, etc.
After you've cherry-picked or made the changes you want, upload the changes for
review.

## Check out a single repository (with repo)

If you don't have a full repo checked out already and want to do a quick one-off
merge, you can still check out the much smaller buildtools group:

```bash
repo init \
    https://chromium.googlesource.com/chromiumos/manifest.git \
    -g buildtools
```

This will get you chromite and all the tools it includes. Make sure you pass
the `--no-mirror` option so it will fetch the single git repo needed to
cherry-pick & upload the CL.

## Checking out a single repository (with git)

If you want to push up a few changes without checking out the entire tree,
then you can use git to do just that.
You can re-use an existing repo checkout if you like (but make sure you clean
up when you're done). Let's assume you're going to make a new checkout to keep
things clean though.

### Cloning a new repository

Find the git url you care about. You can get it by going into your repo
checkout and look at `.git/config` (the url field). You'll need to use the
-review variant of the URL to push to the special `refs/for/*` refs. Let's
demonstrate with the chromite git tree.

```bash
git clone https://chromium-review.googlesource.com/chromiumos/chromite.git
```

If you want to speed things up, you can use the `--reference` option to re-use a
local tree.

```bash
git clone https://chromium-review.googlesource.com/chromiumos/chromite.git \
    --reference ~/chromiumos/chromite/.git
```

### Setting your author/committer settings

If your normal user information is not your chromium.org e-mail, you'll need to
set it in the new repo.

```bash
git config user.name "Awesome Developer"
git config user.email ${USER}@chromium.org
```

### Start a new branch

Let's assume you want to work on the R76 branch.  You need the full name of the
branch, and then create a new local branch to work on with that info.

```bash
git branch -a | grep R76
```

That shows us the full branch name is "remotes/cros/release-R76-12239.B", so we
can do:

```bash
git checkout -b R76 remotes/cros/release-R76-12239.B
```

### Make your changes

This part is where the real work happens. Use git's or repo's cherry-pick
feature, or make the changes by hand, or apply patches, or whatever you want.

```bash
# When the editor pops, try to change a few attributes to help tracking commit
# history. Change Reviewed-on to Previous-Reviewed-on, and
# add a line like
# `**(cherry picked from commit b9e382afa7e410745ac96b12b49d5a941070db1e).**`
# For changes in different branches, you can keep same Change-Id;
# otherwise remove that to get a new unique Change-Id.
git cherry-pick -x -e <SHA1>
```

### Publish your commits to gerrit

Now for the last step.  If you didn't create a new clone, you might have to
change "origin" to "cros", or replace it with the full git url.  The "R76" is
whatever you called the local branch, and the "release-R76-12239.B" is exactly
what the official branch name is called - make sure it is correct as gerrit will
allow you to push to anything.

```bash
git push ${REMOTE_NAME} ${LOCAL_BRANCH_NAME}:refs/for/${REMOTE_BRANCH_NAME}
# for example, if remote is 'origin', your local branch is called 'R76'
# and the branch to merge to is the R76 branch on the ChromeOS server:
git push origin R76:refs/for/release-R76-12239.B
```

## Reusing a single repository in an existing repo checkout

While it is possible to manually checkout a different branch in an existing
repo checkout (e.g. checking out `release-R69-10895.B` in `chromite/` when the
rest of the manifest is tracking [ToT]), this is *strongly not recommended*.

Mixing different branches in git trees in a single repo checkout can easily
break existing tools and is not supported. Even if you want to do it as a one
off (e.g. checkout a branch, make a change, upload it, and then discard the
branch), it's still not recommended as sometimes people forget to clean up when
they're done. Depending on the git tree, this can manifest itself days, weeks,
or even months later as a weird error in a seemingly unrelated location.

This is why we only support the methods listed above.

[contributing]: /chromium-os/developer-library/guides/development/contributing/#Getting-Code_Review
[drover]: /developers/how-tos/drover
[developer-guide]: /chromium-os/developer-library/guides/development/developer-guide/
[experimental-branches]: /developers/experimental-branches
[merge request]: https://chromium.googlesource.com/chromium/src/+/HEAD/docs/process/merge_request.md
[ToT]: /glossary
