go.fuchsia.dev/jiri@v0.0.0-20240502161911-b66513b29486/README.md (about)

     1  # Jiri
     2  /jɪəri/ YEER-ee
     3  
     4  *"Jiri integrates repositories intelligently"*
     5  
     6  Jiri is a tool for multi-repo development.
     7  It supports:
     8  * syncing multiple local GIT repos with upstream,
     9  * capturing the current state of all local repos in a "snapshot",
    10  * restoring local project state from a snapshot, and
    11  * facilitating sending change lists to [Gerrit][gerrit].
    12  
    13  Jiri has an extensible plugin model, making it easy to create new sub-commands.
    14  
    15  Jiri is open-source.
    16  
    17  ## Manually build jiri
    18  We have [prebuilts](#Bootstrapping) for linux and darwin `x86_64` systems. In
    19  order to fetch latest jiri source code and build jiri manually, latest version
    20  of [Go](https://golang.org) should be installed. After installing Go, you can
    21  fetch the latest jiri source code by using the command:
    22  
    23  ```
    24  git clone https://fuchsia.googlesource.com/jiri
    25  ```
    26  
    27  To build (or rebuild) jiri, simply type the following commands:
    28  
    29  ```
    30  cd jiri
    31  go install ./cmd/jiri
    32  ```
    33  
    34  The binary will be installed to `$HOME/go/bin/jiri` (or `$GOPATH/bin/jiri`, if
    35  you set `GOPATH`) and can be copied to any directory in your PATH, as long as it
    36  is writable (to support jiri bootstrapping and self-updates).
    37  
    38  ## Uploading a change to the jiri repository
    39  
    40  To upload a change to Jiri itself, commit your changes locally
    41  and run:
    42  
    43  ```
    44  git push origin HEAD:refs/for/main
    45  ```
    46  
    47  The first time you run this command you will see instructions for
    48  installing and running a git commit-hook.
    49  
    50  Running the above command again will print out the URL for your Changelist.
    51  
    52  ## Jiri Behaviour
    53  [See this][behaviour]
    54  
    55  ## Jiri Tricks
    56  [See this][how do i]
    57  
    58  ## Jiri Basics
    59  Jiri organizes a set of GIT repositories on your local filesystem according to
    60  a [manifest][manifests].  These repositories are referred to as "projects", and
    61  are all contained within a single directory called the "jiri root".
    62  
    63  Jiri also supports [CIPD][cipd] "packages", to download potentially large
    64  _read-only_ files, like toolchain binaries or test data, into the jiri root.
    65  
    66  The manifest file specifies the relative location of each project or package
    67  within the jiri root, and also includes other metadata, such as its remote url,
    68  the remote branch or revision it should track, and more.
    69  
    70  The `jiri update` command syncs the main branch of all local projects to the
    71  revision and remote branch specified in the manifest for each project. Jiri
    72  will create the project locally if it does not exist, and if run with the `-gc`
    73  flag, jiri will "garbage collect" any projects that are not listed in the
    74  manifest by deleting them locally.
    75  
    76  The command will also download, update or remove CIPD packages according to
    77  manifest changes, if necessary.
    78  
    79  The `.jiri_manifest` file in the jiri root describes which project jiri should
    80  sync.  Typically the `.jiri_manifest` file will import other manifests, but it
    81  can also contain a list of projects.
    82  
    83  For example, here is a simple `.jiri_manifest` with just two projects, "foo"
    84  and "bar", which are hosted on github and bitbucket respectively.
    85  ```
    86  <?xml version="1.0" encoding="UTF-8"?>
    87  <manifest>
    88    <projects>
    89      <project name="foo-project"
    90               remote="https://github.com/my-org/foo"
    91               path="foo"/>
    92      <project name="bar"
    93               remote="https://bitbucket.com/other-org/bar"
    94               path="bar"/>
    95    </projects>
    96  </manifest>
    97  ```
    98  When you run `jiri update` for the first time, the "foo" and "bar" repos will
    99  be cloned into `foo` and `bar` respectively and repos would be put on DETACHED
   100  HEAD.  Running `jiri update` again will update all the remote refs and
   101  rebase your current branch to its upstream branch.
   102  
   103  Note that the project paths do not need to be immediate children of the jiri
   104  root.  We could have decided to set the `path` attribute for the "bar" project
   105  to "third_party/bar", or even nest "bar" inside the "foo" project by setting
   106  the `path` to  "foo/bar" (assuming no files in the foo repo conflict with bar).
   107  
   108  Because manifest files also need to be kept in sync between various team
   109  members, it often makes sense to keep your team's manifests in a version
   110  controlled repository.
   111  
   112  Jiri makes it easy to "import" a remote manifest from your local
   113  `.jiri_manifest` file with the `jiri import` command.  For example, running the
   114  following command will create a `.jiri_manifest` file (or append to an existing
   115  one) with an `import` tag that imports the jiri manifest from the
   116  `https://fuchsia.googlesource.com/jiri` repo.
   117  
   118  ```
   119  jiri import -name jiri manifest https://fuchsia.googlesource.com/jiri
   120  ```
   121  
   122  The next time you run `jiri update`, jiri will sync all projects listed in the
   123  jiri manifest.
   124  
   125  ## Quickstart
   126  
   127  This section explains how to get started with jiri.
   128  
   129  First we "bootstrap" jiri so that it can sync and build itself.
   130  
   131  Then we create and import a new manifest, which specifies how jiri should
   132  manage your projects.
   133  
   134  ### Bootstrapping
   135  
   136  You can get jiri up-and-running in no time with the help of the [bootstrap
   137  script][bootstrap_jiri].
   138  
   139  First, pick a jiri root directory.  All projects will be synced to
   140  subdirectories of the root.
   141  
   142  ```
   143  export MY_ROOT=$HOME/myroot
   144  ```
   145  
   146  Execute the `jiri_bootstrap` script, which will fetch and build the jiri tool,
   147  and initialize the root directory.
   148  
   149  ```
   150  curl -s https://fuchsia.googlesource.com/jiri/+/HEAD/scripts/bootstrap_jiri?format=TEXT | base64 --decode | bash -s "$MY_ROOT"
   151  ```
   152  
   153  The `jiri` command line tool will be installed in
   154  `$MY_ROOT/.jiri_root/bin/jiri`, so add that to your `PATH`.
   155  
   156  ```
   157  export PATH="$MY_ROOT"/.jiri_root/bin:$PATH
   158  ```
   159  
   160  Next, use the `jiri import` command to import the "jiri" manifest from the
   161  Jiri repo.  This manifest includes Jiri's repository.
   162  
   163  You can see the jiri manifest [here][jiri manifest]. For more
   164  information on manifests, read the [manifest docs][manifests].
   165  
   166  ```
   167  cd "$MY_ROOT"
   168  jiri import -name jiri manifest https://fuchsia.googlesource.com/jiri
   169  ```
   170  
   171  You should now have a file in the root directory called `.jiri_manifest`, which
   172  will contain a single import.
   173  
   174  Finally, run `jiri update`, which will sync all local projects to the revisions
   175  listed in the manifest (which in this case will be `HEAD`).
   176  
   177  ```
   178  jiri update
   179  ```
   180  
   181  You should now see the imported project in `$MY_ROOT/go/src/fuchsia.googlesource.com/jiri`.
   182  
   183  Running `jiri update` again will sync the local repos to the remotes, and
   184  update the jiri tool.
   185  
   186  ### Managing your projects with jiri
   187  
   188  Now that jiri is able to sync and build itself, we must tell it how to manage
   189  your projects.
   190  
   191  In order for jiri to manage a set of projects, those projects must be listed in
   192  a [manifest][manifests], and that manifest must be hosted in a git repo.
   193  
   194  If you already have a manifest hosted in a git repo, you can import that
   195  manifest the same way we imported the "jiri" manifest.
   196  
   197  For example, if your manifest is called "my_manifest" and is in a repo hosted
   198  at "https://github.com/my_org/manifests", then you can import that manifest
   199  as follows.
   200  
   201  ```
   202  jiri import my_manifest https://github.com/my_org/manifests
   203  ```
   204  
   205  The rest of this section walks through how to create a manifest from scratch,
   206  host it from a local git repo, and get jiri to manage it.
   207  
   208  Suppose that the project you want jiri to manage is the "Hello-World" repo
   209  located at https://github.com/Test-Octowin/Hello-World.
   210  
   211  First we'll create a new git repo to host the manifest we'll be writing.
   212  
   213  ```
   214  mkdir -p /tmp/my_manifest_repo
   215  cd /tmp/my_manifest_repo
   216  git init
   217  ```
   218  
   219  Next we'll create a manifest and commit it to the manifest repo.
   220  
   221  The manifest file will include the Hello-World repo as well as the manifest
   222  repo itself.
   223  
   224  ```
   225  cat <<EOF > my_manifest
   226  <?xml version="1.0" encoding="UTF-8"?>
   227  <manifest>
   228    <projects>
   229      <project name="Hello-World"
   230               remote="https://github.com/Test-Octowin/Hello-World"
   231               path="helloworld"/>
   232      <project name="my_manifest_repo"
   233               remote="/tmp/my_manifest_repo"
   234               path="my_manifest_repo"/>
   235    </projects>
   236  </manifest>
   237  EOF
   238  
   239  git add my_manifest
   240  git commit -m "Add my_manifest."
   241  ```
   242  
   243  This manifest contains a single project with the name "Hello-World" and the
   244  remote of the repo.  The `path` attribute tells jiri to sync this repo inside
   245  the `helloworld` directory.
   246  
   247  Normally we would want to push this repo to some remote to make it accessible
   248  to other users who want to sync the same projects.  For now, however, we'll
   249  just refer to the repo by its path in the local filesystem.
   250  
   251  Now we just need to import that new manifest and `jiri update`.
   252  
   253  ```
   254  cd "$MY_ROOT"
   255  jiri import -name=my_manifest_repo my_manifest /tmp/my_manifest_repo
   256  jiri update
   257  ```
   258  
   259  You should now see the Hello-World repo in `$MY_ROOT/helloworld`, and your
   260  manifest repo in `$MY_ROOT/my_manifest_repo`.
   261  
   262  ## Command-line help
   263  
   264  The `jiri help` command will print help documentation about the `jiri` tool and
   265  its subcommands.
   266  
   267  For general documentation, including a list of subcommands, run `jiri help`.
   268  To find documentation about a specific topic or subcommand, run `jiri help
   269  <command>`.
   270  
   271  ### Main commands are:
   272  ```
   273     branch          Show or delete branches
   274     diff            Prints diff between two snapshots
   275     grep            Search across projects.
   276     import          Adds imports to .jiri_manifest file
   277     init            Create a new jiri root
   278     patch           Patch in the existing change
   279     project         Manage the jiri projects
   280     project-config  Prints/sets project's local config
   281     run-hooks       Run hooks using local manifest
   282     runp            Run a command in parallel across jiri projects
   283     selfupdate      Update jiri tool
   284     snapshot        Create a new project snapshot
   285     source-manifest Create a new source-manifest from current checkout
   286     status          Prints status of all the projects
   287     update          Update all jiri projects
   288     upload          Upload a changelist for review
   289     version         Print the jiri version
   290     help            Display help for commands or topics
   291  ```
   292  Run `jiri help [command]` for command usage.
   293  
   294  ## Filesystem
   295  
   296  See the jiri [filesystem docs][filesystem doc].
   297  
   298  ## Manifests<a name="manifests"></a>
   299  
   300  See the jiri [manifest docs][manifest doc].
   301  
   302  ## Snapshots
   303  
   304  TODO(anmittal): Write me.
   305  
   306  ## Gerrit CL workflow
   307  
   308  [Gerrit][gerrit] is a collaborative code-review tool used by many open source
   309  projects.
   310  
   311  One of the peculiarities of Gerrit is that it expects a changelist to be
   312  represented by a single commit.  This constrains the way developers may use git
   313  to work on their changes.  In particular, they must use the --amend flag with
   314  all but the first git commit operation and they need to use git rebase to sync
   315  their pending code change with the remote.  See Android's [repo command
   316  reference][android repo] or Go's [contributing instructions][go contrib] for
   317  examples of how intricate the workflow for resolving conflicts between the
   318  pending code change and the remote is.
   319  
   320  The rest of this section describes common development operations using `jiri
   321  upload`.
   322  
   323  ### Using feature branches
   324  
   325  All development should take place on a non-main "feature" branch.  Once the
   326  code is reviewed and approved, it is merged into the remote main branch via the
   327  Gerrit code review system.  The change can then be merged into the local
   328  branches with `jiri update -rebase-all`.
   329  
   330  ### Creating a new CL
   331  
   332  1. Sync the main branch with the remote.
   333    ```
   334    jiri update
   335    ```
   336  2. Create a new feature branch for the CL.
   337    ```
   338    git checkout -b <branch-name> --track origin/main
   339    ```
   340  3. Make modifications to the project source code.
   341  4. Stage any changed files for commit.
   342    ```
   343    git add <file1> <file2> ... <fileN>
   344    ```
   345  5. Commit the changes.
   346    ```
   347    git commit
   348    ```
   349  
   350  ### Syncing a CL with the remote
   351  
   352  1. Sync the main branch with the remote.
   353    ```
   354    jiri update
   355    ```
   356  2. Switch to the feature branch that corresponds to the CL under development.
   357    ```
   358    git checkout <branch-name>
   359    ```
   360  3. Sync the feature branch with the main branch.
   361    ```
   362    git rebase origin/main
   363    ```
   364  4. If there are no conflicts between the main branch and the feature branch, the CL
   365     has been successfully synced with the remote.
   366  5. If there are conflicts:
   367    1. Manually [resolve the conflicts][github resolve conflict].
   368    2. Stage any changed files for a commit.
   369      ```
   370      git add <file1> <file2> ... <fileN>
   371      ```
   372    3. Commit the changes.
   373      ```
   374      git commit --amend
   375      ```
   376  
   377  ### Requesting a code review
   378  
   379  1. Switch to the feature branch that corresponds to the CL under development.
   380    ```
   381    git checkout <branch-name>
   382    ```
   383  2.  Upload the CL to Gerrit.
   384    ```
   385    jiri upload
   386    ```
   387  
   388  If the CL upload is  successful, this will print the URL of the CL hosted on
   389  Gerrit.  You can add reviewers and comments through the [Gerrit web UI][gerrit
   390  web ui] at that URL.
   391  
   392  Note that there are many useful flags for `jiri upload`.  You can learn about them
   393  by running `jiri help upload`.
   394  
   395  ### Reviewing a CL
   396  
   397  1. Follow the link received in the code review email request.
   398  2. Use the [Gerrit web UI][gerrit web UI] to comment on the CL and click the
   399     "Reply" button to submit comments, selecting the appropriate code-review
   400     score.
   401  
   402  ### Addressing review comments
   403  
   404  
   405  1. Switch to the feature branch that corresponds to the CL under development.
   406    ```
   407    git checkout <branch-name>
   408    ```
   409  2. Modify the code.
   410  3. Add your modified code.
   411    ```
   412    git add -u
   413    ```
   414  4. Commit the code.
   415    ```
   416    git commit --amend
   417    ```
   418  5. Reply to each Gerrit comment and click the "Reply" button to send them.
   419  6. Send the updated CL to Gerrit.
   420    ```
   421    jiri upload
   422    ```
   423  
   424  ### Submitting a CL
   425  1. Note that if the CL conflicts with any changes that have been submitted since
   426     the last update of the CL, these conflicts need to be resolved before the CL
   427     can be submitted.  To do so, rebase your changes then upload the updated CL
   428     to Gerrit.
   429    ```
   430    jiri upload
   431    ```
   432  2. Once a CL meets the conditions for being submitted, it can be merged into
   433     the remote main branch by clicking the "Submit" button on the Gerrit web
   434     UI.
   435  3. Delete the local feature branch after the CL has been submitted to Gerrit.
   436    1. Sync the main branch to the laster version of the remote.
   437      ```
   438      jiri update
   439      ```
   440    2. Safely delete the feature branch that corresponds to the CL.
   441      ```
   442      git checkout JIRI_HEAD && git branch -d <branch-name>
   443      ```
   444  
   445  ### Dependent CLs
   446  If you have changes A and B, and B depends on A, you can still submit distinct
   447  CLs for A and B that can be reviewed and submitted independently (although A
   448  must be submitted before B).
   449  
   450  First, create your feature branch for A, make your change, and upload the CL
   451  for review according to the instructions above.
   452  
   453  Then, while still on the feature branch for A, create your feature branch for B.
   454  ```
   455  git checkout -b feature-B --track origin/main
   456  ```
   457  Then make your change and upload the CL for review according to the
   458  instructions above.
   459  
   460  You can respond to review comments by submitting new patch sets as normal.
   461  
   462  After the CL for A has been submitted, make sure to clean up A's feature branch
   463  and upload a new patch set for feature B.
   464  ```
   465  jiri update # fetch update that includes feature A
   466  git checkout feature-B
   467  git rebase -i origin/main # if u see commit from A, delete it and then rebase
   468  properly
   469  jiri upload # send new patch set for feature B
   470  ```
   471  The CL for feature B can now be submitted.
   472  
   473  This process can be extended for more than 2 CLs.  You must keep two things in mind:
   474  * always create the dependent feature branch from the parent feature branch, and
   475  * after a parent feature has been submitted, rebase feature-B onto origin/main
   476  
   477  ## FAQ
   478  
   479  ### Why the name "jiri"?
   480  The tool was conceived by engineers working on the [Vanadium][vanadium] project
   481  to facilitate the multi-repository management needs of the project. At the time,
   482  it was called "v23". It was renamed to "jiri" shortly after its creator (named
   483  Jiří) left the project and Google.
   484  
   485  [Jiří][jiri-wiki] is a very popular boys name in the Czech Republic.
   486  
   487  ### How do you pronounce "jiri"?
   488  We pronounce "jiri" like "yiree".
   489  
   490  The actual Czech name [Jiří][jiri-wiki] is pronounced something like "yirzhee".
   491  
   492  ### How can I test changes to a manifest without pushing it upstream?
   493  see [Jiri local update][hacking doc]
   494  
   495  [android repo]: https://source.android.com/source/using-repo.html "Repo command reference"
   496  [bootstrap_jiri]: scripts/bootstrap_jiri "bootstrap_jiri"
   497  [gerrit]: https://www.gerritcodereview.com/ "Gerrit code review"
   498  [gerrit web ui]: https://gerrit-review.googlesource.com/Documentation/user-review-ui.html "Gerrit review UI"
   499  [github resolve conflict]: https://help.github.com/articles/resolving-a-merge-conflict-from-the-command-line/ "Resolving a merge conflict"
   500  [go contrib]: https://golang.org/doc/contribute.html#Code_review "Go Contribution Guidelines - Code Review"
   501  [jiri-wiki]: https://en.wikipedia.org/wiki/Ji%C5%99%C3%AD "Jiří"
   502  [manifests]: #manifests "manifests"
   503  [jiri manifest]: https://fuchsia.googlesource.com/jiri/+/refs/heads/main/manifest "jiri manifest"
   504  [manifest doc]:/manifest.md "Jiri manifest"
   505  [filesystem doc]:/filesystem.md "Jiri filesystem"
   506  [hacking doc]:/HACKING.md "Jiri local updates"
   507  [behaviour]:/behaviour.md
   508  [how do i]:/howdoi.md
   509  [vanadium]: https://v.io/
   510  [cipd]: https://chromium.googlesource.com/infra/luci/luci-go/+/main/cipd/