[yaml2obj] - Remove helper methods that are probably excessive. NFC.
[llvm-complete.git] / docs / Proposals / GitHubMove.rst
blob83d2286e7a8862d3f6387de7f185011b8484b882
1 ==============================
2 Moving LLVM Projects to GitHub
3 ==============================
5 .. contents:: Table of Contents
6   :depth: 4
7   :local:
9 Introduction
10 ============
12 This is a proposal to move our current revision control system from our own
13 hosted Subversion to GitHub. Below are the financial and technical arguments as
14 to why we are proposing such a move and how people (and validation
15 infrastructure) will continue to work with a Git-based LLVM.
17 There will be a survey pointing at this document which we'll use to gauge the
18 community's reaction and, if we collectively decide to move, the time-frame. Be
19 sure to make your view count.
21 Additionally, we will discuss this during a BoF at the next US LLVM Developer
22 meeting (http://llvm.org/devmtg/2016-11/).
24 What This Proposal is *Not* About
25 =================================
27 Changing the development policy.
29 This proposal relates only to moving the hosting of our source-code repository
30 from SVN hosted on our own servers to Git hosted on GitHub. We are not proposing
31 using GitHub's issue tracker, pull-requests, or code-review.
33 Contributors will continue to earn commit access on demand under the Developer
34 Policy, except that that a GitHub account will be required instead of SVN
35 username/password-hash.
37 Why Git, and Why GitHub?
38 ========================
40 Why Move At All?
41 ----------------
43 This discussion began because we currently host our own Subversion server
44 and Git mirror on a voluntary basis. The LLVM Foundation sponsors the server and
45 provides limited support, but there is only so much it can do.
47 Volunteers are not sysadmins themselves, but compiler engineers that happen
48 to know a thing or two about hosting servers. We also don't have 24/7 support,
49 and we sometimes wake up to see that continuous integration is broken because
50 the SVN server is either down or unresponsive.
52 We should take advantage of one of the services out there (GitHub, GitLab,
53 and BitBucket, among others) that offer better service (24/7 stability, disk
54 space, Git server, code browsing, forking facilities, etc) for free.
56 Why Git?
57 --------
59 Many new coders nowadays start with Git, and a lot of people have never used
60 SVN, CVS, or anything else. Websites like GitHub have changed the landscape
61 of open source contributions, reducing the cost of first contribution and
62 fostering collaboration.
64 Git is also the version control many LLVM developers use. Despite the
65 sources being stored in a SVN server, these developers are already using Git
66 through the Git-SVN integration.
68 Git allows you to:
70 * Commit, squash, merge, and fork locally without touching the remote server.
71 * Maintain local branches, enabling multiple threads of development.
72 * Collaborate on these branches (e.g. through your own fork of llvm on GitHub).
73 * Inspect the repository history (blame, log, bisect) without Internet access.
74 * Maintain remote forks and branches on Git hosting services and
75   integrate back to the main repository.
77 In addition, because Git seems to be replacing many OSS projects' version
78 control systems, there are many tools that are built over Git.
79 Future tooling may support Git first (if not only).
81 Why GitHub?
82 -----------
84 GitHub, like GitLab and BitBucket, provides free code hosting for open source
85 projects. Any of these could replace the code-hosting infrastructure that we
86 have today.
88 These services also have a dedicated team to monitor, migrate, improve and
89 distribute the contents of the repositories depending on region and load.
91 GitHub has one important advantage over GitLab and
92 BitBucket: it offers read-write **SVN** access to the repository
93 (https://github.com/blog/626-announcing-svn-support).
94 This would enable people to continue working post-migration as though our code
95 were still canonically in an SVN repository.
97 In addition, there are already multiple LLVM mirrors on GitHub, indicating that
98 part of our community has already settled there.
100 On Managing Revision Numbers with Git
101 -------------------------------------
103 The current SVN repository hosts all the LLVM sub-projects alongside each other.
104 A single revision number (e.g. r123456) thus identifies a consistent version of
105 all LLVM sub-projects.
107 Git does not use sequential integer revision number but instead uses a hash to
108 identify each commit.
110 The loss of a sequential integer revision number has been a sticking point in
111 past discussions about Git:
113 - "The 'branch' I most care about is mainline, and losing the ability to say
114   'fixed in r1234' (with some sort of monotonically increasing number) would
115   be a tragic loss." [LattnerRevNum]_
116 - "I like those results sorted by time and the chronology should be obvious, but
117   timestamps are incredibly cumbersome and make it difficult to verify that a
118   given checkout matches a given set of results." [TrickRevNum]_
119 - "There is still the major regression with unreadable version numbers.
120   Given the amount of Bugzilla traffic with 'Fixed in...', that's a
121   non-trivial issue." [JSonnRevNum]_
122 - "Sequential IDs are important for LNT and llvmlab bisection tool." [MatthewsRevNum]_.
124 However, Git can emulate this increasing revision number:
125 ``git rev-list --count <commit-hash>``. This identifier is unique only
126 within a single branch, but this means the tuple `(num, branch-name)` uniquely
127 identifies a commit.
129 We can thus use this revision number to ensure that e.g. `clang -v` reports a
130 user-friendly revision number (e.g. `master-12345` or `4.0-5321`), addressing
131 the objections raised above with respect to this aspect of Git.
133 What About Branches and Merges?
134 -------------------------------
136 In contrast to SVN, Git makes branching easy. Git's commit history is
137 represented as a DAG, a departure from SVN's linear history. However, we propose
138 to mandate making merge commits illegal in our canonical Git repository.
140 Unfortunately, GitHub does not support server side hooks to enforce such a
141 policy.  We must rely on the community to avoid pushing merge commits.
143 GitHub offers a feature called `Status Checks`: a branch protected by
144 `status checks` requires commits to be whitelisted before the push can happen.
145 We could supply a pre-push hook on the client side that would run and check the
146 history, before whitelisting the commit being pushed [statuschecks]_.
147 However this solution would be somewhat fragile (how do you update a script
148 installed on every developer machine?) and prevents SVN access to the
149 repository.
151 What About Commit Emails?
152 -------------------------
154 We will need a new bot to send emails for each commit. This proposal leaves the
155 email format unchanged besides the commit URL.
157 Straw Man Migration Plan
158 ========================
160 Step #1 : Before The Move
161 -------------------------
163 1. Update docs to mention the move, so people are aware of what is going on.
164 2. Set up a read-only version of the GitHub project, mirroring our current SVN
165    repository.
166 3. Add the required bots to implement the commit emails, as well as the
167    umbrella repository update (if the multirepo is selected) or the read-only
168    Git views for the sub-projects (if the monorepo is selected).
170 Step #2 : Git Move
171 ------------------
173 4. Update the buildbots to pick up updates and commits from the GitHub
174    repository. Not all bots have to migrate at this point, but it'll help
175    provide infrastructure testing.
176 5. Update Phabricator to pick up commits from the GitHub repository.
177 6. LNT and llvmlab have to be updated: they rely on unique monotonically
178    increasing integer across branch [MatthewsRevNum]_.
179 7. Instruct downstream integrators to pick up commits from the GitHub
180    repository.
181 8. Review and prepare an update for the LLVM documentation.
183 Until this point nothing has changed for developers, it will just
184 boil down to a lot of work for buildbot and other infrastructure
185 owners.
187 The migration will pause here until all dependencies have cleared, and all
188 problems have been solved.
190 Step #3: Write Access Move
191 --------------------------
193 9. Collect developers' GitHub account information, and add them to the project.
194 10. Switch the SVN repository to read-only and allow pushes to the GitHub repository.
195 11. Update the documentation.
196 12. Mirror Git to SVN.
198 Step #4 : Post Move
199 -------------------
201 13. Archive the SVN repository.
202 14. Update links on the LLVM website pointing to viewvc/klaus/phab etc. to
203     point to GitHub instead.
205 One or Multiple Repositories?
206 =============================
208 There are two major variants for how to structure our Git repository: The
209 "multirepo" and the "monorepo".
211 Multirepo Variant
212 -----------------
214 This variant recommends moving each LLVM sub-project to a separate Git
215 repository. This mimics the existing official read-only Git repositories
216 (e.g., http://llvm.org/git/compiler-rt.git), and creates new canonical
217 repositories for each sub-project.
219 This will allow the individual sub-projects to remain distinct: a
220 developer interested only in compiler-rt can checkout only this repository,
221 build it, and work in isolation of the other sub-projects.
223 A key need is to be able to check out multiple projects (i.e. lldb+clang+llvm or
224 clang+llvm+libcxx for example) at a specific revision.
226 A tuple of revisions (one entry per repository) accurately describes the state
227 across the sub-projects.
228 For example, a given version of clang would be
229 *<LLVM-12345, clang-5432, libcxx-123, etc.>*.
231 Umbrella Repository
232 ^^^^^^^^^^^^^^^^^^^
234 To make this more convenient, a separate *umbrella* repository will be
235 provided. This repository will be used for the sole purpose of understanding
236 the sequence in which commits were pushed to the different repositories and to
237 provide a single revision number.
239 This umbrella repository will be read-only and continuously updated
240 to record the above tuple. The proposed form to record this is to use Git
241 [submodules]_, possibly along with a set of scripts to help check out a
242 specific revision of the LLVM distribution.
244 A regular LLVM developer does not need to interact with the umbrella repository
245 -- the individual repositories can be checked out independently -- but you would
246 need to use the umbrella repository to bisect multiple sub-projects at the same
247 time, or to check-out old revisions of LLVM with another sub-project at a
248 consistent state.
250 This umbrella repository will be updated automatically by a bot (running on
251 notice from a webhook on every push, and periodically) on a per commit basis: a
252 single commit in the umbrella repository would match a single commit in a
253 sub-project.
255 Living Downstream
256 ^^^^^^^^^^^^^^^^^
258 Downstream SVN users can use the read/write SVN bridges with the following
259 caveats:
261  * Be prepared for a one-time change to the upstream revision numbers.
262  * The upstream sub-project revision numbers will no longer be in sync.
264 Downstream Git users can continue without any major changes, with the minor
265 change of upstreaming using `git push` instead of `git svn dcommit`.
267 Git users also have the option of adopting an umbrella repository downstream.
268 The tooling for the upstream umbrella can easily be reused for downstream needs,
269 incorporating extra sub-projects and branching in parallel with sub-project
270 branches.
272 Multirepo Preview
273 ^^^^^^^^^^^^^^^^^
275 As a preview (disclaimer: this rough prototype, not polished and not
276 representative of the final solution), you can look at the following:
278   * Repository: https://github.com/llvm-beanz/llvm-submodules
279   * Update bot: http://beanz-bot.com:8180/jenkins/job/submodule-update/
281 Concerns
282 ^^^^^^^^
284  * Because GitHub does not allow server-side hooks, and because there is no
285    "push timestamp" in Git, the umbrella repository sequence isn't totally
286    exact: commits from different repositories pushed around the same time can
287    appear in different orders. However, we don't expect it to be the common case
288    or to cause serious issues in practice.
289  * You can't have a single cross-projects commit that would update both LLVM and
290    other sub-projects (something that can be achieved now). It would be possible
291    to establish a protocol whereby users add a special token to their commit
292    messages that causes the umbrella repo's updater bot to group all of them
293    into a single revision.
294  * Another option is to group commits that were pushed closely enough together
295    in the umbrella repository. This has the advantage of allowing cross-project
296    commits, and is less sensitive to mis-ordering commits. However, this has the
297    potential to group unrelated commits together, especially if the bot goes
298    down and needs to catch up.
299  * This variant relies on heavier tooling. But the current prototype shows that
300    it is not out-of-reach.
301  * Submodules don't have a good reputation / are complicating the command line.
302    However, in the proposed setup, a regular developer will seldom interact with
303    submodules directly, and certainly never update them.
304  * Refactoring across projects is not friendly: taking some functions from clang
305    to make it part of a utility in libSupport wouldn't carry the history of the
306    code in the llvm repo, preventing recursively applying `git blame` for
307    instance. However, this is not very different than how most people are
308    Interacting with the repository today, by splitting such change in multiple
309    commits.
311 Workflows
312 ^^^^^^^^^
314  * :ref:`Checkout/Clone a Single Project, without Commit Access <workflow-checkout-commit>`.
315  * :ref:`Checkout/Clone a Single Project, with Commit Access <workflow-multicheckout-nocommit>`.
316  * :ref:`Checkout/Clone Multiple Projects, with Commit Access <workflow-multicheckout-multicommit>`.
317  * :ref:`Commit an API Change in LLVM and Update the Sub-projects <workflow-cross-repo-commit>`.
318  * :ref:`Branching/Stashing/Updating for Local Development or Experiments <workflow-multi-branching>`.
319  * :ref:`Bisecting <workflow-multi-bisecting>`.
321 Monorepo Variant
322 ----------------
324 This variant recommends moving all LLVM sub-projects to a single Git repository,
325 similar to https://github.com/llvm-project/llvm-project.
326 This would mimic an export of the current SVN repository, with each sub-project
327 having its own top-level directory.
328 Not all sub-projects are used for building toolchains. In practice, www/
329 and test-suite/ will probably stay out of the monorepo.
331 Putting all sub-projects in a single checkout makes cross-project refactoring
332 naturally simple:
334  * New sub-projects can be trivially split out for better reuse and/or layering
335    (e.g., to allow libSupport and/or LIT to be used by runtimes without adding a
336    dependency on LLVM).
337  * Changing an API in LLVM and upgrading the sub-projects will always be done in
338    a single commit, designing away a common source of temporary build breakage.
339  * Moving code across sub-project (during refactoring for instance) in a single
340    commit enables accurate `git blame` when tracking code change history.
341  * Tooling based on `git grep` works natively across sub-projects, allowing to
342    easier find refactoring opportunities across projects (for example reusing a
343    datastructure initially in LLDB by moving it into libSupport).
344  * Having all the sources present encourages maintaining the other sub-projects
345    when changing API.
347 Finally, the monorepo maintains the property of the existing SVN repository that
348 the sub-projects move synchronously, and a single revision number (or commit
349 hash) identifies the state of the development across all projects.
351 .. _build_single_project:
353 Building a single sub-project
354 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
356 Nobody will be forced to build unnecessary projects.  The exact structure
357 is TBD, but making it trivial to configure builds for a single sub-project
358 (or a subset of sub-projects) is a hard requirement.
360 As an example, it could look like the following::
362   mkdir build && cd build
363   # Configure only LLVM (default)
364   cmake path/to/monorepo
365   # Configure LLVM and lld
366   cmake path/to/monorepo -DLLVM_ENABLE_PROJECTS=lld
367   # Configure LLVM and clang
368   cmake path/to/monorepo -DLLVM_ENABLE_PROJECTS=clang
370 .. _git-svn-mirror:
372 Read/write sub-project mirrors
373 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
375 With the Monorepo, the existing single-subproject mirrors (e.g.
376 http://llvm.org/git/compiler-rt.git) with git-svn read-write access would
377 continue to be maintained: developers would continue to be able to use the
378 existing single-subproject git repositories as they do today, with *no changes
379 to workflow*. Everything (git fetch, git svn dcommit, etc.) could continue to
380 work identically to how it works today. The monorepo can be set-up such that the
381 SVN revision number matches the SVN revision in the GitHub SVN-bridge.
383 Living Downstream
384 ^^^^^^^^^^^^^^^^^
386 Downstream SVN users can use the read/write SVN bridge. The SVN revision
387 number can be preserved in the monorepo, minimizing the impact.
389 Downstream Git users can continue without any major changes, by using the
390 git-svn mirrors on top of the SVN bridge.
392 Git users can also work upstream with monorepo even if their downstream
393 fork has split repositories.  They can apply patches in the appropriate
394 subdirectories of the monorepo using, e.g., `git am --directory=...`, or
395 plain `diff` and `patch`.
397 Alternatively, Git users can migrate their own fork to the monorepo.  As a
398 demonstration, we've migrated the "CHERI" fork to the monorepo in two ways:
400  * Using a script that rewrites history (including merges) so that it looks
401    like the fork always lived in the monorepo [LebarCHERI]_.  The upside of
402    this is when you check out an old revision, you get a copy of all llvm
403    sub-projects at a consistent revision.  (For instance, if it's a clang
404    fork, when you check out an old revision you'll get a consistent version
405    of llvm proper.)  The downside is that this changes the fork's commit
406    hashes.
408  * Merging the fork into the monorepo [AminiCHERI]_.  This preserves the
409    fork's commit hashes, but when you check out an old commit you only get
410    the one sub-project.
412 Monorepo Preview
413 ^^^^^^^^^^^^^^^^^
415 As a preview (disclaimer: this rough prototype, not polished and not
416 representative of the final solution), you can look at the following:
418   * Full Repository: https://github.com/joker-eph/llvm-project
419   * Single sub-project view with *SVN write access* to the full repo:
420     https://github.com/joker-eph/compiler-rt
422 Concerns
423 ^^^^^^^^
425  * Using the monolithic repository may add overhead for those contributing to a
426    standalone sub-project, particularly on runtimes like libcxx and compiler-rt
427    that don't rely on LLVM; currently, a fresh clone of libcxx is only 15MB (vs.
428    1GB for the monorepo), and the commit rate of LLVM may cause more frequent
429    `git push` collisions when upstreaming. Affected contributors can continue to
430    use the SVN bridge or the single-subproject Git mirrors with git-svn for
431    read-write.
432  * Using the monolithic repository may add overhead for those *integrating* a
433    standalone sub-project, even if they aren't contributing to it, due to the
434    same disk space concern as the point above. The availability of the
435    sub-project Git mirror addresses this, even without SVN access.
436  * Preservation of the existing read/write SVN-based workflows relies on the
437    GitHub SVN bridge, which is an extra dependency.  Maintaining this locks us
438    into GitHub and could restrict future workflow changes.
440 Workflows
441 ^^^^^^^^^
443  * :ref:`Checkout/Clone a Single Project, without Commit Access <workflow-checkout-commit>`.
444  * :ref:`Checkout/Clone a Single Project, with Commit Access <workflow-monocheckout-nocommit>`.
445  * :ref:`Checkout/Clone Multiple Projects, with Commit Access <workflow-monocheckout-multicommit>`.
446  * :ref:`Commit an API Change in LLVM and Update the Sub-projects <workflow-cross-repo-commit>`.
447  * :ref:`Branching/Stashing/Updating for Local Development or Experiments <workflow-mono-branching>`.
448  * :ref:`Bisecting <workflow-mono-bisecting>`.
450 Multi/Mono Hybrid Variant
451 -------------------------
453 This variant recommends moving only the LLVM sub-projects that are *rev-locked*
454 to LLVM into a monorepo (clang, lld, lldb, ...), following the multirepo
455 proposal for the rest.  While neither variant recommends combining sub-projects
456 like www/ and test-suite/ (which are completely standalone), this goes further
457 and keeps sub-projects like libcxx and compiler-rt in their own distinct
458 repositories.
460 Concerns
461 ^^^^^^^^
463  * This has most disadvantages of multirepo and monorepo, without bringing many
464    of the advantages.
465  * Downstream have to upgrade to the monorepo structure, but only partially. So
466    they will keep the infrastructure to integrate the other separate
467    sub-projects.
468  * All projects that use LIT for testing are effectively rev-locked to LLVM.
469    Furthermore, some runtimes (like compiler-rt) are rev-locked with Clang.
470    It's not clear where to draw the lines.
473 Workflow Before/After
474 =====================
476 This section goes through a few examples of workflows, intended to illustrate
477 how end-users or developers would interact with the repository for
478 various use-cases.
480 .. _workflow-checkout-commit:
482 Checkout/Clone a Single Project, without Commit Access
483 ------------------------------------------------------
485 Except the URL, nothing changes. The possibilities today are::
487   svn co http://llvm.org/svn/llvm-project/llvm/trunk llvm
488   # or with Git
489   git clone http://llvm.org/git/llvm.git
491 After the move to GitHub, you would do either::
493   git clone https://github.com/llvm-project/llvm.git
494   # or using the GitHub svn native bridge
495   svn co https://github.com/llvm-project/llvm/trunk
497 The above works for both the monorepo and the multirepo, as we'll maintain the
498 existing read-only views of the individual sub-projects.
500 Checkout/Clone a Single Project, with Commit Access
501 ---------------------------------------------------
503 Currently
504 ^^^^^^^^^
508   # direct SVN checkout
509   svn co https://user@llvm.org/svn/llvm-project/llvm/trunk llvm
510   # or using the read-only Git view, with git-svn
511   git clone http://llvm.org/git/llvm.git
512   cd llvm
513   git svn init https://llvm.org/svn/llvm-project/llvm/trunk --username=<username>
514   git config svn-remote.svn.fetch :refs/remotes/origin/master
515   git svn rebase -l  # -l avoids fetching ahead of the git mirror.
517 Commits are performed using `svn commit` or with the sequence `git commit` and
518 `git svn dcommit`.
520 .. _workflow-multicheckout-nocommit:
522 Multirepo Variant
523 ^^^^^^^^^^^^^^^^^
525 With the multirepo variant, nothing changes but the URL, and commits can be
526 performed using `svn commit` or `git commit` and `git push`::
528   git clone https://github.com/llvm/llvm.git llvm
529   # or using the GitHub svn native bridge
530   svn co https://github.com/llvm/llvm/trunk/ llvm
532 .. _workflow-monocheckout-nocommit:
534 Monorepo Variant
535 ^^^^^^^^^^^^^^^^
537 With the monorepo variant, there are a few options, depending on your
538 constraints. First, you could just clone the full repository::
540   git clone https://github.com/llvm/llvm-projects.git llvm
541   # or using the GitHub svn native bridge
542   svn co https://github.com/llvm/llvm-projects/trunk/ llvm
544 At this point you have every sub-project (llvm, clang, lld, lldb, ...), which
545 :ref:`doesn't imply you have to build all of them <build_single_project>`. You
546 can still build only compiler-rt for instance. In this way it's not different
547 from someone who would check out all the projects with SVN today.
549 You can commit as normal using `git commit` and `git push` or `svn commit`, and
550 read the history for a single project (`git log libcxx` for example).
552 Secondly, there are a few options to avoid checking out all the sources.
554 **Using the GitHub SVN bridge**
556 The GitHub SVN native bridge allows to checkout a subdirectory directly:
558   svn co https://github.com/llvm/llvm-projects/trunk/compiler-rt compiler-rt  â€”username=...
560 This checks out only compiler-rt and provides commit access using "svn commit",
561 in the same way as it would do today.
563 **Using a Subproject Git Mirror**
565 You can use *git-svn* and one of the sub-project mirrors::
567   # Clone from the single read-only Git repo
568   git clone http://llvm.org/git/llvm.git
569   cd llvm
570   # Configure the SVN remote and initialize the svn metadata
571   $ git svn init https://github.com/joker-eph/llvm-project/trunk/llvm â€”username=...
572   git config svn-remote.svn.fetch :refs/remotes/origin/master
573   git svn rebase -l
575 In this case the repository contains only a single sub-project, and commits can
576 be made using `git svn dcommit`, again exactly as we do today.
578 **Using a Sparse Checkouts**
580 You can hide the other directories using a Git sparse checkout::
582   git config core.sparseCheckout true
583   echo /compiler-rt > .git/info/sparse-checkout
584   git read-tree -mu HEAD
586 The data for all sub-projects is still in your `.git` directory, but in your
587 checkout, you only see `compiler-rt`.
588 Before you push, you'll need to fetch and rebase (`git pull --rebase`) as
589 usual.
591 Note that when you fetch you'll likely pull in changes to sub-projects you don't
592 care about. If you are using spasre checkout, the files from other projects
593 won't appear on your disk. The only effect is that your commit hash changes.
595 You can check whether the changes in the last fetch are relevant to your commit
596 by running::
598   git log origin/master@{1}..origin/master -- libcxx
600 This command can be hidden in a script so that `git llvmpush` would perform all
601 these steps, fail only if such a dependent change exists, and show immediately
602 the change that prevented the push. An immediate repeat of the command would
603 (almost) certainly result in a successful push.
604 Note that today with SVN or git-svn, this step is not possible since the
605 "rebase" implicitly happens while committing (unless a conflict occurs).
607 Checkout/Clone Multiple Projects, with Commit Access
608 ----------------------------------------------------
610 Let's look how to assemble llvm+clang+libcxx at a given revision.
612 Currently
613 ^^^^^^^^^
617   svn co http://llvm.org/svn/llvm-project/llvm/trunk llvm -r $REVISION
618   cd llvm/tools
619   svn co http://llvm.org/svn/llvm-project/clang/trunk clang -r $REVISION
620   cd ../projects
621   svn co http://llvm.org/svn/llvm-project/libcxx/trunk libcxx -r $REVISION
623 Or using git-svn::
625   git clone http://llvm.org/git/llvm.git
626   cd llvm/
627   git svn init https://llvm.org/svn/llvm-project/llvm/trunk --username=<username>
628   git config svn-remote.svn.fetch :refs/remotes/origin/master
629   git svn rebase -l
630   git checkout `git svn find-rev -B r258109`
631   cd tools
632   git clone http://llvm.org/git/clang.git
633   cd clang/
634   git svn init https://llvm.org/svn/llvm-project/clang/trunk --username=<username>
635   git config svn-remote.svn.fetch :refs/remotes/origin/master
636   git svn rebase -l
637   git checkout `git svn find-rev -B r258109`
638   cd ../../projects/
639   git clone http://llvm.org/git/libcxx.git
640   cd libcxx
641   git svn init https://llvm.org/svn/llvm-project/libcxx/trunk --username=<username>
642   git config svn-remote.svn.fetch :refs/remotes/origin/master
643   git svn rebase -l
644   git checkout `git svn find-rev -B r258109`
646 Note that the list would be longer with more sub-projects.
648 .. _workflow-multicheckout-multicommit:
650 Multirepo Variant
651 ^^^^^^^^^^^^^^^^^
653 With the multirepo variant, the umbrella repository will be used. This is
654 where the mapping from a single revision number to the individual repositories
655 revisions is stored.::
657   git clone https://github.com/llvm-beanz/llvm-submodules
658   cd llvm-submodules
659   git checkout $REVISION
660   git submodule init
661   git submodule update clang llvm libcxx
662   # the list of sub-project is optional, `git submodule update` would get them all.
664 At this point the clang, llvm, and libcxx individual repositories are cloned
665 and stored alongside each other. There are CMake flags to describe the directory
666 structure; alternatively, you can just symlink `clang` to `llvm/tools/clang`,
667 etc.
669 Another option is to checkout repositories based on the commit timestamp::
671   git checkout `git rev-list -n 1 --before="2009-07-27 13:37" master`
673 .. _workflow-monocheckout-multicommit:
675 Monorepo Variant
676 ^^^^^^^^^^^^^^^^
678 The repository contains natively the source for every sub-projects at the right
679 revision, which makes this straightforward::
681   git clone https://github.com/llvm/llvm-projects.git llvm-projects
682   cd llvm-projects
683   git checkout $REVISION
685 As before, at this point clang, llvm, and libcxx are stored in directories
686 alongside each other.
688 .. _workflow-cross-repo-commit:
690 Commit an API Change in LLVM and Update the Sub-projects
691 --------------------------------------------------------
693 Today this is possible, even though not common (at least not documented) for
694 subversion users and for git-svn users. For example, few Git users try to update
695 LLD or Clang in the same commit as they change an LLVM API.
697 The multirepo variant does not address this: one would have to commit and push
698 separately in every individual repository. It would be possible to establish a
699 protocol whereby users add a special token to their commit messages that causes
700 the umbrella repo's updater bot to group all of them into a single revision.
702 The monorepo variant handles this natively.
704 Branching/Stashing/Updating for Local Development or Experiments
705 ----------------------------------------------------------------
707 Currently
708 ^^^^^^^^^
710 SVN does not allow this use case, but developers that are currently using
711 git-svn can do it. Let's look in practice what it means when dealing with
712 multiple sub-projects.
714 To update the repository to tip of trunk::
716   git pull
717   cd tools/clang
718   git pull
719   cd ../../projects/libcxx
720   git pull
722 To create a new branch::
724   git checkout -b MyBranch
725   cd tools/clang
726   git checkout -b MyBranch
727   cd ../../projects/libcxx
728   git checkout -b MyBranch
730 To switch branches::
732   git checkout AnotherBranch
733   cd tools/clang
734   git checkout AnotherBranch
735   cd ../../projects/libcxx
736   git checkout AnotherBranch
738 .. _workflow-multi-branching:
740 Multirepo Variant
741 ^^^^^^^^^^^^^^^^^
743 The multirepo works the same as the current Git workflow: every command needs
744 to be applied to each of the individual repositories.
745 However, the umbrella repository makes this easy using `git submodule foreach`
746 to replicate a command on all the individual repositories (or submodules
747 in this case):
749 To create a new branch::
751   git submodule foreach git checkout -b MyBranch
753 To switch branches::
755   git submodule foreach git checkout AnotherBranch
757 .. _workflow-mono-branching:
759 Monorepo Variant
760 ^^^^^^^^^^^^^^^^
762 Regular Git commands are sufficient, because everything is in a single
763 repository:
765 To update the repository to tip of trunk::
767   git pull
769 To create a new branch::
771   git checkout -b MyBranch
773 To switch branches::
775   git checkout AnotherBranch
777 Bisecting
778 ---------
780 Assuming a developer is looking for a bug in clang (or lld, or lldb, ...).
782 Currently
783 ^^^^^^^^^
785 SVN does not have builtin bisection support, but the single revision across
786 sub-projects makes it possible to script around.
788 Using the existing Git read-only view of the repositories, it is possible to use
789 the native Git bisection script over the llvm repository, and use some scripting
790 to synchronize the clang repository to match the llvm revision.
792 .. _workflow-multi-bisecting:
794 Multirepo Variant
795 ^^^^^^^^^^^^^^^^^
797 With the multi-repositories variant, the cross-repository synchronization is
798 achieved using the umbrella repository. This repository contains only
799 submodules for the other sub-projects. The native Git bisection can be used on
800 the umbrella repository directly. A subtlety is that the bisect script itself
801 needs to make sure the submodules are updated accordingly.
803 For example, to find which commit introduces a regression where clang-3.9
804 crashes but not clang-3.8 passes, one should be able to simply do::
806   git bisect start release_39 release_38
807   git bisect run ./bisect_script.sh
809 With the `bisect_script.sh` script being::
811   #!/bin/sh
812   cd $UMBRELLA_DIRECTORY
813   git submodule update llvm clang libcxx #....
814   cd $BUILD_DIR
816   ninja clang || exit 125   # an exit code of 125 asks "git bisect"
817                             # to "skip" the current commit
819   ./bin/clang some_crash_test.cpp
821 When the `git bisect run` command returns, the umbrella repository is set to
822 the state where the regression is introduced. The commit diff in the umbrella
823 indicate which submodule was updated, and the last commit in this sub-projects
824 is the one that the bisect found.
826 .. _workflow-mono-bisecting:
828 Monorepo Variant
829 ^^^^^^^^^^^^^^^^
831 Bisecting on the monorepo is straightforward, and very similar to the above,
832 except that the bisection script does not need to include the
833 `git submodule update` step.
835 The same example, finding which commit introduces a regression where clang-3.9
836 crashes but not clang-3.8 passes, will look like::
838   git bisect start release_39 release_38
839   git bisect run ./bisect_script.sh
841 With the `bisect_script.sh` script being::
843   #!/bin/sh
844   cd $BUILD_DIR
846   ninja clang || exit 125   # an exit code of 125 asks "git bisect"
847                             # to "skip" the current commit
849   ./bin/clang some_crash_test.cpp
851 Also, since the monorepo handles commits update across multiple projects, you're
852 less like to encounter a build failure where a commit change an API in LLVM and
853 another later one "fixes" the build in clang.
855 Moving Local Branches to the Monorepo
856 =====================================
858 Suppose you have been developing against the existing LLVM git
859 mirrors.  You have one or more git branches that you want to migrate
860 to the "final monorepo".
862 The simplest way to migrate such branches is with the
863 ``migrate-downstream-fork.py`` tool at
864 https://github.com/jyknight/llvm-git-migration.
866 Basic migration
867 ---------------
869 Basic instructions for ``migrate-downstream-fork.py`` are in the
870 Python script and are expanded on below to a more general recipe::
872   # Make a repository which will become your final local mirror of the
873   # monorepo.
874   mkdir my-monorepo
875   git -C my-monorepo init
877   # Add a remote to the monorepo.
878   git -C my-monorepo remote add upstream/monorepo https://github.com/llvm/llvm-project.git
880   # Add remotes for each git mirror you use, from upstream as well as
881   # your local mirror.  All projects are listed here but you need only
882   # import those for which you have local branches.
883   my_projects=( clang
884                 clang-tools-extra
885                 compiler-rt
886                 debuginfo-tests
887                 libcxx
888                 libcxxabi
889                 libunwind
890                 lld
891                 lldb
892                 llvm
893                 openmp
894                 polly )
895   for p in ${my_projects[@]}; do
896     git -C my-monorepo remote add upstream/split/${p} https://github.com/llvm-mirror/${p}.git
897     git -C my-monorepo remote add local/split/${p} https://my.local.mirror.org/${p}.git
898   done
900   # Pull in all the commits.
901   git -C my-monorepo fetch --all
903   # Run migrate-downstream-fork to rewrite local branches on top of
904   # the upstream monorepo.
905   (
906      cd my-monorepo
907      migrate-downstream-fork.py \
908        refs/remotes/local \
909        refs/tags \
910        --new-repo-prefix=refs/remotes/upstream/monorepo \
911        --old-repo-prefix=refs/remotes/upstream/split \
912        --source-kind=split \
913        --revmap-out=monorepo-map.txt
914   )
916   # Octopus-merge the resulting local split histories to unify them.
918   # Assumes local work on local split mirrors is on master (and
919   # upstream is presumably represented by some other branch like
920   # upstream/master).
921   my_local_branch="master"
923   git -C my-monorepo branch --no-track local/octopus/master \
924     $(git -C my-monorepo merge-base refs/remotes/upstream/monorepo/master \
925                                     refs/remotes/local/split/llvm/${my_local_branch})
926   git -C my-monorepo checkout local/octopus/${my_local_branch}
928   subproject_branches=()
929   for p in ${my_projects[@]}; do
930     subproject_branch=${p}/local/monorepo/${my_local_branch}
931     git -C my-monorepo branch ${subproject_branch} \
932       refs/remotes/local/split/${p}/${my_local_branch}
933     if [[ "${p}" != "llvm" ]]; then
934       subproject_branches+=( ${subproject_branch} )
935     fi
936   done
938   git -C my-monorepo merge ${subproject_branches[@]}
940   for p in ${my_projects[@]}; do
941     subproject_branch=${p}/local/monorepo/${my_local_branch}
942     git -C my-monorepo branch -d ${subproject_branch}
943   done
945   # Create local branches for upstream monorepo branches.
946   for ref in $(git -C my-monorepo for-each-ref --format="%(refname)" \
947                    refs/remotes/upstream/monorepo); do
948     upstream_branch=${ref#refs/remotes/upstream/monorepo/}
949     git -C my-monorepo branch upstream/${upstream_branch} ${ref}
950   done
952 The above gets you to a state like the following::
954   U1 - U2 - U3 <- upstream/master
955     \   \    \
956      \   \    - Llld1 - Llld2 -
957       \   \                    \
958        \   - Lclang1 - Lclang2-- Lmerge <- local/octopus/master
959         \                      /
960          - Lllvm1 - Lllvm2-----
962 Each branched component has its branch rewritten on top of the
963 monorepo and all components are unified by a giant octopus merge.
965 If additional active local branches need to be preserved, the above
966 operations following the assignment to ``my_local_branch`` should be
967 done for each branch.  Ref paths will need to be updated to map the
968 local branch to the corresponding upstream branch.  If local branches
969 have no corresponding upstream branch, then the creation of
970 ``local/octopus/<local branch>`` need not use ``git-merge-base`` to
971 pinpont its root commit; it may simply be branched from the
972 appropriate component branch (say, ``llvm/local_release_X``).
974 Zipping local history
975 ---------------------
977 The octopus merge is suboptimal for many cases, because walking back
978 through the history of one component leaves the other components fixed
979 at a history that likely makes things unbuildable.
981 Some downstream users track the order commits were made to subprojects
982 with some kind of "umbrella" project that imports the project git
983 mirrors as submodules, similar to the multirepo umbrella proposed
984 above.  Such an umbrella repository looks something like this::
986    UM1 ---- UM2 -- UM3 -- UM4 ---- UM5 ---- UM6 ---- UM7 ---- UM8 <- master
987    |        |             |        |        |        |        |
988   Lllvm1   Llld1         Lclang1  Lclang2  Lllvm2   Llld2     Lmyproj1
990 The vertical bars represent submodule updates to a particular local
991 commit in the project mirror.  ``UM3`` in this case is a commit of
992 some local umbrella repository state that is not a submodule update,
993 perhaps a ``README`` or project build script update.  Commit ``UM8``
994 updates a submodule of local project ``myproj``.
996 The tool ``zip-downstream-fork.py`` at
997 https://github.com/greened/llvm-git-migration/tree/zip can be used to
998 convert the umbrella history into a monorepo-based history with
999 commits in the order implied by submodule updates::
1001   U1 - U2 - U3 <- upstream/master
1002    \    \    \
1003     \    -----\---------------                                    local/zip--.
1004      \         \              \                                               |
1005     - Lllvm1 - Llld1 - UM3 -  Lclang1 - Lclang2 - Lllvm2 - Llld2 - Lmyproj1 <-'
1008 The ``U*`` commits represent upstream commits to the monorepo master
1009 branch.  Each submodule update in the local ``UM*`` commits brought in
1010 a subproject tree at some local commit.  The trees in the ``L*1``
1011 commits represent merges from upstream.  These result in edges from
1012 the ``U*`` commits to their corresponding rewritten ``L*1`` commits.
1013 The ``L*2`` commits did not do any merges from upstream.
1015 Note that the merge from ``U2`` to ``Lclang1`` appears redundant, but
1016 if, say, ``U3`` changed some files in upstream clang, the ``Lclang1``
1017 commit appearing after the ``Llld1`` commit would actually represent a
1018 clang tree *earlier* in the upstream clang history.  We want the
1019 ``local/zip`` branch to accurately represent the state of our umbrella
1020 history and so the edge ``U2 -> Lclang1`` is a visual reminder of what
1021 clang's tree actually looks like in ``Lclang1``.
1023 Even so, the edge ``U3 -> Llld1`` could be problematic for future
1024 merges from upstream.  git will think that we've already merged from
1025 ``U3``, and we have, except for the state of the clang tree.  One
1026 possible migitation strategy is to manually diff clang between ``U2``
1027 and ``U3`` and apply those updates to ``local/zip``.  Another,
1028 possibly simpler strategy is to freeze local work on downstream
1029 branches and merge all submodules from the latest upstream before
1030 running ``zip-downstream-fork.py``.  If downstream merged each project
1031 from upstream in lockstep without any intervening local commits, then
1032 things should be fine without any special action.  We anticipate this
1033 to be the common case.
1035 The tree for ``Lclang1`` outside of clang will represent the state of
1036 things at ``U3`` since all of the upstream projects not participating
1037 in the umbrella history should be in a state respecting the commit
1038 ``U3``.  The trees for llvm and lld should correctly represent commits
1039 ``Lllvm1`` and ``Llld1``, respectively.
1041 Commit ``UM3`` changed files not related to submodules and we need
1042 somewhere to put them.  It is not safe in general to put them in the
1043 monorepo root directory because they may conflict with files in the
1044 monorepo.  Let's assume we want them in a directory ``local`` in the
1045 monorepo.
1047 **Example 1: Umbrella looks like the monorepo**
1049 For this example, we'll assume that each subproject appears in its own
1050 top-level directory in the umbrella, just as they do in the monorepo .
1051 Let's also assume that we want the files in directory ``myproj`` to
1052 appear in ``local/myproj``.
1054 Given the above run of ``migrate-downstream-fork.py``, a recipe to
1055 create the zipped history is below::
1057   # Import any non-LLVM repositories the umbrella references.
1058   git -C my-monorepo remote add localrepo \
1059                                 https://my.local.mirror.org/localrepo.git
1060   git fetch localrepo
1062   subprojects=( clang clang-tools-extra compiler-rt debuginfo-tests libclc
1063                 libcxx libcxxabi libunwind lld lldb llgo llvm openmp
1064                 parallel-libs polly pstl )
1066   # Import histories for upstream split projects (this was probably
1067   # already done for the ``migrate-downstream-fork.py`` run).
1068   for project in ${subprojects[@]}; do
1069     git remote add upstream/split/${project} \
1070                    https://github.com/llvm-mirror/${subproject}.git
1071     git fetch umbrella/split/${project}
1072   done
1074   # Import histories for downstream split projects (this was probably
1075   # already done for the ``migrate-downstream-fork.py`` run).
1076   for project in ${subprojects[@]}; do
1077     git remote add local/split/${project} \
1078                    https://my.local.mirror.org/${subproject}.git
1079     git fetch local/split/${project}
1080   done
1082   # Import umbrella history.
1083   git -C my-monorepo remote add umbrella \
1084                                 https://my.local.mirror.org/umbrella.git
1085   git fetch umbrella
1087   # Put myproj in local/myproj
1088   echo "myproj local/myproj" > my-monorepo/submodule-map.txt
1090   # Rewrite history
1091   (
1092     cd my-monorepo
1093     zip-downstream-fork.py \
1094       refs/remotes/umbrella \
1095       --new-repo-prefix=refs/remotes/upstream/monorepo \
1096       --old-repo-prefix=refs/remotes/upstream/split \
1097       --revmap-in=monorepo-map.txt \
1098       --revmap-out=zip-map.txt \
1099       --subdir=local \
1100       --submodule-map=submodule-map.txt \
1101       --update-tags
1102    )
1104    # Create the zip branch (assuming umbrella master is wanted).
1105    git -C my-monorepo branch --no-track local/zip/master refs/remotes/umbrella/master
1107 Note that if the umbrella has submodules to non-LLVM repositories,
1108 ``zip-downstream-fork.py`` needs to know about them to be able to
1109 rewrite commits.  That is why the first step above is to fetch commits
1110 from such repositories.
1112 With ``--update-tags`` the tool will migrate annotated tags pointing
1113 to submodule commits that were inlined into the zipped history.  If
1114 the umbrella pulled in an upstream commit that happened to have a tag
1115 pointing to it, that tag will be migrated, which is almost certainly
1116 not what is wanted.  The tag can always be moved back to its original
1117 commit after rewriting, or the ``--update-tags`` option may be
1118 discarded and any local tags would then be migrated manually.
1120 **Example 2: Nested sources layout**
1122 The tool handles nested submodules (e.g. llvm is a submodule in
1123 umbrella and clang is a submodule in llvm).  The file
1124 ``submodule-map.txt`` is a list of pairs, one per line.  The first
1125 pair item describes the path to a submodule in the umbrella
1126 repository.  The second pair item secribes the path where trees for
1127 that submodule should be written in the zipped history.  
1129 Let's say your umbrella repository is actually the llvm repository and
1130 it has submodules in the "nested sources" layout (clang in
1131 tools/clang, etc.).  Let's also say ``projects/myproj`` is a submodule
1132 pointing to some downstream repository.  The submodule map file should
1133 look like this (we still want myproj mapped the same way as
1134 previously)::
1136   tools/clang clang
1137   tools/clang/tools/extra clang-tools-extra
1138   projects/compiler-rt compiler-rt
1139   projects/debuginfo-tests debuginfo-tests
1140   projects/libclc libclc
1141   projects/libcxx libcxx
1142   projects/libcxxabi libcxxabi
1143   projects/libunwind libunwind
1144   tools/lld lld
1145   tools/lldb lldb
1146   projects/openmp openmp
1147   tools/polly polly
1148   projects/myproj local/myproj
1150 If a submodule path does not appear in the map, the tools assumes it
1151 should be placed in the same place in the monorepo.  That means if you
1152 use the "nested sources" layout in your umrella, you *must* provide
1153 map entries for all of the projects in your umbrella (except llvm).
1154 Otherwise trees from submodule updates will appear underneath llvm in
1155 the zippped history.
1157 Because llvm is itself the umbrella, we use --subdir to write its
1158 content into ``llvm`` in the zippped history::
1160   # Import any non-LLVM repositories the umbrella references.
1161   git -C my-monorepo remote add localrepo \
1162                                 https://my.local.mirror.org/localrepo.git
1163   git fetch localrepo
1165   subprojects=( clang clang-tools-extra compiler-rt debuginfo-tests libclc
1166                 libcxx libcxxabi libunwind lld lldb llgo llvm openmp
1167                 parallel-libs polly pstl )
1169   # Import histories for upstream split projects (this was probably
1170   # already done for the ``migrate-downstream-fork.py`` run).
1171   for project in ${subprojects[@]}; do
1172     git remote add upstream/split/${project} \
1173                    https://github.com/llvm-mirror/${subproject}.git
1174     git fetch umbrella/split/${project}
1175   done
1177   # Import histories for downstream split projects (this was probably
1178   # already done for the ``migrate-downstream-fork.py`` run).
1179   for project in ${subprojects[@]}; do
1180     git remote add local/split/${project} \
1181                    https://my.local.mirror.org/${subproject}.git
1182     git fetch local/split/${project}
1183   done
1185   # Import umbrella history.  We want this under a different refspec
1186   # so zip-downstream-fork.py knows what it is.
1187   git -C my-monorepo remote add umbrella \
1188                                  https://my.local.mirror.org/llvm.git
1189   git fetch umbrella
1191   # Create the submodule map.
1192   echo "tools/clang clang" > my-monorepo/submodule-map.txt
1193   echo "tools/clang/tools/extra clang-tools-extra" >> my-monorepo/submodule-map.txt
1194   echo "projects/compiler-rt compiler-rt" >> my-monorepo/submodule-map.txt
1195   echo "projects/debuginfo-tests debuginfo-tests" >> my-monorepo/submodule-map.txt
1196   echo "projects/libclc libclc" >> my-monorepo/submodule-map.txt
1197   echo "projects/libcxx libcxx" >> my-monorepo/submodule-map.txt
1198   echo "projects/libcxxabi libcxxabi" >> my-monorepo/submodule-map.txt
1199   echo "projects/libunwind libunwind" >> my-monorepo/submodule-map.txt
1200   echo "tools/lld lld" >> my-monorepo/submodule-map.txt
1201   echo "tools/lldb lldb" >> my-monorepo/submodule-map.txt
1202   echo "projects/openmp openmp" >> my-monorepo/submodule-map.txt
1203   echo "tools/polly polly" >> my-monorepo/submodule-map.txt
1204   echo "projects/myproj local/myproj" >> my-monorepo/submodule-map.txt
1206   # Rewrite history
1207   (
1208     cd my-monorepo
1209     zip-downstream-fork.py \
1210       refs/remotes/umbrella \
1211       --new-repo-prefix=refs/remotes/upstream/monorepo \
1212       --old-repo-prefix=refs/remotes/upstream/split \
1213       --revmap-in=monorepo-map.txt \
1214       --revmap-out=zip-map.txt \
1215       --subdir=llvm \
1216       --submodule-map=submodule-map.txt \
1217       --update-tags
1218    )
1220    # Create the zip branch (assuming umbrella master is wanted).
1221    git -C my-monorepo branch --no-track local/zip/master refs/remotes/umbrella/master
1224 Comments at the top of ``zip-downstream-fork.py`` describe in more
1225 detail how the tool works and various implications of its operation.
1227 Importing local repositories
1228 ----------------------------
1230 You may have additional repositories that integrate with the LLVM
1231 ecosystem, essentially extending it with new tools.  If such
1232 repositories are tightly coupled with LLVM, it may make sense to
1233 import them into your local mirror of the monorepo.
1235 If such repositores participated in the umbrella repository used
1236 during the zipping process above, they will automatically be added to
1237 the monorepo.  For downstream repositories that don't participate in
1238 an umbrella setup, the ``import-downstream-repo.py`` tool at
1239 https://github.com/greened/llvm-git-migration/tree/import can help with
1240 getting them into the monorepo.  A recipe follows::
1242   # Import downstream repo history into the monorepo.
1243   git -C my-monorepo remote add myrepo https://my.local.mirror.org/myrepo.git
1244   git fetch myrepo
1246   my_local_tags=( refs/tags/release
1247                   refs/tags/hotfix )
1249   (
1250     cd my-monorepo
1251     import-downstream-repo.py \
1252       refs/remotes/myrepo \
1253       ${my_local_tags[@]} \
1254       --new-repo-prefix=refs/remotes/upstream/monorepo \
1255       --subdir=myrepo \
1256       --tag-prefix="myrepo-"
1257    )
1259    # Preserve release braches.
1260    for ref in $(git -C my-monorepo for-each-ref --format="%(refname)" \
1261                   refs/remotes/myrepo/release); do
1262      branch=${ref#refs/remotes/myrepo/}
1263      git -C my-monorepo branch --no-track myrepo/${branch} ${ref}
1264    done
1266    # Preserve master.
1267    git -C my-monorepo branch --no-track myrepo/master refs/remotes/myrepo/master
1269    # Merge master.
1270    git -C my-monorepo checkout local/zip/master  # Or local/octopus/master
1271    git -C my-monorepo merge myrepo/master
1273 You may want to merge other corresponding branches, for example
1274 ``myrepo`` release branches if they were in lockstep with LLVM project
1275 releases.
1277 ``--tag-prefix`` tells ``import-downstream-repo.py`` to rename
1278 annotated tags with the given prefix.  Due to limitations with
1279 ``fast_filter_branch.py``, unannotated tags cannot be renamed
1280 (``fast_filter_branch.py`` considers them branches, not tags).  Since
1281 the upstream monorepo had its tags rewritten with an "llvmorg-"
1282 prefix, name conflicts should not be an issue.  ``--tag-prefix`` can
1283 be used to more clearly indicate which tags correspond to various
1284 imported repositories.
1286 Given this repository history::
1288   R1 - R2 - R3 <- master
1289        ^
1290        |
1291     release/1
1293 The above recipe results in a history like this::
1295   U1 - U2 - U3 <- upstream/master
1296    \    \    \
1297     \    -----\---------------                                         local/zip--.
1298      \         \              \                                                    |
1299     - Lllvm1 - Llld1 - UM3 -  Lclang1 - Lclang2 - Lllvm2 - Llld2 - Lmyproj1 - M1 <-'
1300                                                                              /
1301                                                                  R1 - R2 - R3  <-.
1302                                                                       ^           |
1303                                                                       |           |
1304                                                                myrepo-release/1   |
1305                                                                                   |
1306                                                                    myrepo/master--'
1308 Commits ``R1``, ``R2`` and ``R3`` have trees that *only* contain blobs
1309 from ``myrepo``.  If you require commits from ``myrepo`` to be
1310 interleaved with commits on local project branches (for example,
1311 interleaved with ``llvm1``, ``llvm2``, etc. above) and myrepo doesn't
1312 appear in an umbrella repository, a new tool will need to be
1313 developed.  Creating such a tool would involve:
1315 1. Modifying ``fast_filter_branch.py`` to optionally take a
1316    revlist directly rather than generating it itself
1318 2. Creating a tool to generate an interleaved ordering of local
1319    commits based on some criteria (``zip-downstream-fork.py`` uses the
1320    umbrella history as its criterion)
1322 3. Generating such an ordering and feeding it to
1323    ``fast_filter_branch.py`` as a revlist
1325 Some care will also likely need to be taken to handle merge commits,
1326 to ensure the parents of such commits migrate correctly.
1328 Scrubbing the Local Monorepo
1329 ----------------------------
1331 Once all of the migrating, zipping and importing is done, it's time to
1332 clean up.  The python tools use ``git-fast-import`` which leaves a lot
1333 of cruft around and we want to shrink our new monorepo mirror as much
1334 as possible.  Here is one way to do it::
1336   git -C my-monorepo checkout master
1338   # Delete branches we no longer need.  Do this for any other branches
1339   # you merged above.
1340   git -C my-monorepo branch -D local/zip/master || true
1341   git -C my-monorepo branch -D local/octopus/master || true
1343   # Remove remotes.
1344   git -C my-monorepo remote remove upstream/monorepo
1346   for p in ${my_projects[@]}; do
1347     git -C my-monorepo remote remove upstream/split/${p}
1348     git -C my-monorepo remote remove local/split/${p}
1349   done
1351   git -C my-monorepo remote remove localrepo
1352   git -C my-monorepo remote remove umbrella
1353   git -C my-monorepo remote remove myrepo
1355   # Add anything else here you don't need.  refs/tags/release is
1356   # listed below assuming tags have been rewritten with a local prefix.
1357   # If not, remove it from this list.
1358   refs_to_clean=(
1359     refs/original
1360     refs/remotes
1361     refs/tags/backups
1362     refs/tags/release
1363   )
1365   git -C my-monorepo for-each-ref --format="%(refname)" ${refs_to_clean[@]} |
1366     xargs -n1 --no-run-if-empty git -C my-monorepo update-ref -d
1368   git -C my-monorepo reflog expire --all --expire=now
1370   # fast_filter_branch.py might have gc running in the background.
1371   while ! git -C my-monorepo \
1372     -c gc.reflogExpire=0 \
1373     -c gc.reflogExpireUnreachable=0 \
1374     -c gc.rerereresolved=0 \
1375     -c gc.rerereunresolved=0 \
1376     -c gc.pruneExpire=now \
1377     gc --prune=now; do
1378     continue
1379   done
1381   # Takes a LOOOONG time!
1382   git -C my-monorepo repack -A -d -f --depth=250 --window=250
1384   git -C my-monorepo prune-packed
1385   git -C my-monorepo prune
1387 You should now have a trim monorepo.  Upload it to your git server and
1388 happy hacking!
1390 References
1391 ==========
1393 .. [LattnerRevNum] Chris Lattner, http://lists.llvm.org/pipermail/llvm-dev/2011-July/041739.html
1394 .. [TrickRevNum] Andrew Trick, http://lists.llvm.org/pipermail/llvm-dev/2011-July/041721.html
1395 .. [JSonnRevNum] Joerg Sonnenberg, http://lists.llvm.org/pipermail/llvm-dev/2011-July/041688.html
1396 .. [MatthewsRevNum] Chris Matthews, http://lists.llvm.org/pipermail/cfe-dev/2016-July/049886.html
1397 .. [submodules] Git submodules, https://git-scm.com/book/en/v2/Git-Tools-Submodules)
1398 .. [statuschecks] GitHub status-checks, https://help.github.com/articles/about-required-status-checks/
1399 .. [LebarCHERI] Port *CHERI* to a single repository rewriting history, http://lists.llvm.org/pipermail/llvm-dev/2016-July/102787.html
1400 .. [AminiCHERI] Port *CHERI* to a single repository preserving history, http://lists.llvm.org/pipermail/llvm-dev/2016-July/102804.html