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/