关于我
Monorepo 工程范式第一部分 · Rush 实战
从零搭建一个 Rush 仓:init、迁移与 CI 引导

从零搭建一个 Rush 仓:init、迁移与 CI 引导

一章走完一个 Rush 仓的诞生:rush init 生成一套配置文件、把已有项目按依赖图迁进来、用 install-run-rush.js 让 CI 自举出与本地一致的 Rush 版本,最后接上官方 MCP 与规范文件教会 agent 使用这个仓。上手实操一遍。

上一章我们把 Rush 的能力地图看完了,知道了它管哪些事、每块对抗哪一种混乱。这一章开始动手,把"从零建一个仓"真实执行一遍,把每一步的使用细节都摸清楚。

全文包含四个步骤:

  1. rush init 建一个能跑的空仓;
  2. 再把一堆已有项目按依赖图迁进来;
  3. 接着把 CI 环境搭起来,让仓库能在 CI 上跑通 install 和 build;
  4. 最后接上 AI 向导,让编码助手看得懂、用得动这个仓。

走完这四步,你会拿到:一个能跑的空 Rush 仓,一条把已有项目搬进来的最小路径,一份能在 CI 上装出与本地一致 Rush 版本的 workflow,以及一套让 agent 不必啃完全部配置就能上手的向导。

先说清适用边界:这套流程是给"会长到数百个包"的仓准备的。如果你手上只有三五个包,pnpm workspace 的 glob 目录就够用,不必上这一整套——这一点第 2 章横评时已经论证过,这里不重复。

1. 初始化

第一步是 rush init。在一个空目录里跑 rush init,它会初始化出这样一批配置文件:

my-repo/
├── rush.json                                    # 项目登记表 + 工具版本锁
└── common/
    ├── config/
    │   └── rush/
    │       ├── common-versions.json             # 全仓统一的依赖版本与例外
    │       ├── command-line.json                # 自定义命令
    │       ├── version-policies.json            # 发布与版本策略
    │       └── pnpm-config.json                 # 包管理器行为
    ├── git-hooks/                               # 提交期检查模板
    └── scripts/
        └── install-run-rush.js                  # CI 自举脚本

不用急着逐个记住,下面一块块过一遍,了解每个关键文件负责什么、各自解决什么问题:

  • rush.json 是全仓的目录页,同时锁工具版本。它有一个 projects 数组登记仓里的每个项目,还锁了 rushVersionpnpmVersionnodeSupportedVersionRange。它挡住的是"没人说得清仓里到底有哪些包、该用哪个版本的工具"。
  • common/config/rush/ 下那几个文件,分别管依赖版本收敛(common-versions.json)、自定义命令(command-line.json)、发布版本策略(version-policies.json)、包管理器行为(pnpm-config.json)。它们合起来把依赖、命令、版本策略统一到一处,挡住的是"每个项目各配一套、口径各行其是"。
  • common/git-hooks/ 放的是 Git hook,rush install 时会装进 .git/hooks。它挡住的是"约定只能靠人自觉,总有人忘"。
  • common/scripts/install-run-rush.js 是 CI 的自举脚本,第 4 节会专门讲。它挡住的是"本地和 CI 两边环境悄悄分叉"。
  • common/temp/ 是安装工作区,被 gitignore,不进 Git——它是每次安装解析出来的中间产物,跟着机器走,提交进去只会污染仓库。

这几个文件加起来,就是 Rush 用配置换来的确定性——每一个都对应一类它帮你挡住的具体问题。

这些文件不必死记。最快的上手方式,是把某个文件直接丢给 AI,让它结合本仓讲清"这个文件管什么、我该怎么填":

读取 common/config/rush/common-versions.json,结合 rush.json,解释这个文件
在这个仓里控制什么、哪些字段是我要关心的,一段话说清,别贴官方文档原文。

这里也顺带点出 Rush 一个贯穿始终的设计取向:约定式 vs 配置式pnpm workspace 靠约定——把包放进 glob 匹配的目录就自动生效;Rush 靠显式登记——一个项目必须写进 rush.jsonprojects[] 才算数。显式确实要多敲几行,但换来的是仓库构成一目了然,任何增删都走一条可 review 的 diff。projects[] 的完整字段留到第 5 章展开。

文件盘完了,再看 rush init 帮你默认开启、但很值得你了解的几个配置。

2. 初始化决策

rush init 生成的这批配置里,有几个关键项需要单独拿出来讲讲。下面挑四个最重要的展开,它们的共同点是一旦定下就不好改,而且新人容易忽略。

第一个是包管理器pnpm、npm、yarn 三选一,在 rush.json 里用对应的 xxxVersion 字段声明——写哪个字段,就等于选了哪个包管理器:

// rush.json
{
  "rushVersion": "5.162.0",

  // 三选一,注释掉另外两个
  "pnpmVersion": "9.5.0",
  // "npmVersion": "6.14.15",
  // "yarnVersion": "1.9.4",
}

本课程用 pnpm:它用硬链接省磁盘,又用严格的 node_modules 布局从结构上抑制幽灵依赖。布局的细节留到第 9 章,这里只需知道这是个 init 期就得定下的决策。

第二个是rushVersion。这是"全仓工具版本一致"的起点——它决定了每个人、每台 CI 机器跑的是不是同一个 Rush。第 4 节的 install-run-rush、第 11 章的环境一致性,都从这里牵出来。

// rush.json
{
  "rushVersion": "5.162.0",
}

第三个是 nodeSupportedVersionRange。它声明这个仓支持哪些 Node 版本,Rush 会在安装、构建前先校验一道。它挡住的是"在我机器上是好的"里最常见的一种成因:两个人的 Node 版本对不上。

// rush.json
{
  "nodeSupportedVersionRange": ">=22.16.0",
}

第四个是目录深度模型,由 projectFolderMinDepthprojectFolderMaxDepth 控制,规定项目目录能放多深——比如强制两级、不许直接平铺在仓库根。数百个包的量级,全靠它约束目录结构不失控。

// rush.json
{
  "projectFolderMinDepth": 2,
  "projectFolderMaxDepth": 2,
}

除这四个之外,单一版本约束(ensureConsistentVersions)在 rush init 时也会问你。这里只点明它是个 init 期决策,怎么配、破例怎么审计,留到第 5 章。

这些决策的共同代价是:定得越死,后面破例就越麻烦。这是"确定性换灵活性"这个权衡在本课程里第一次具体出现,后面还会多次遇到。

3. 迁移已有项目

前面建的是一个空仓,而现实里更常见的场景是迁移:手上已经有一堆项目,散在若干个独立仓库或一个 pnpm workspace 里,要把它们搬进 Rush。这个动作比新建复杂得多——项目之间有依赖关系,搬的顺序不能乱;迁移期新旧两套基建要并存,不能互相污染;每搬一个都得能验证、能回滚,不能把整个团队的开发卡住。所以迁移不能上来就动手,得先把安全和稳定放在第一位,设计好一套迁移策略再执行。这是本章最有实操价值、也最复杂的一节。

下面先用 AI 协助梳理出一份完整的迁移策略(3.1),再逐个展开策略里要考虑的关键点:怎么保证始终可回滚(3.2)、怎么按依赖图定迁移顺序(3.3)、遇到循环依赖怎么办(3.4)、迁一个项目具体做哪三个动作(3.5),以及这条路的成本与产出(3.6)。

3.1 用 AI 梳理迁移策略

迁移是个复杂、容易出问题的过程:牵扯的项目多,依赖关系绕,过程中最好让新旧两套基建并存兼容、随时能退回旧路,任何一步没考虑到都可能把整个仓库卡住。所以强烈建议动手之前先梳理出一份写下来的迁移方案,把怎么切、按什么顺序切、每步怎么验证和回滚都想清楚,而不是边迁边试。

这份方案适合让 AI 介入来出初稿:把你旧仓库的现状(用什么工具管理、有哪些项目、依赖关系大致如何)和目标(迁到 Rush、渐进迁移、可回滚)都提供给它,特别提醒它关注两套基建并存时的冲突与隔离、切换点的选择这些细节,让它产出一份技术方案,涵盖怎么切、切换顺序、每步的验证与回滚。用下面这段 Prompt 让它先输出方案、你确认后再执行:

当前仓库用 pnpm workspace 管理,我要渐进迁移到 Rush,过程中两套基建要并存、
可随时回滚。请先不动代码,输出一份迁移方案:
1) 哪些现有配置/脚本在迁移期必须保留、哪些会和 Rush 冲突要隔离;
2) 一个按依赖图分批的迁移顺序;
3) 每批的验证清单(装得上/构建过/测试通过)和回滚步骤;
4) 全部项目迁完后,最后一步统一移除旧 workspace 基建的清单。
方案先给我确认再执行。

AI 出的只是初稿,拿到后要逐条仔细审核,提前排除掉不合理的点,避免真迁到一半才发现方案有坑、被迫返工。方案定稿之后,就可以交给 agent,按规划一步步执行迁移。至于审核时具体该盯哪些地方,后面几节我结合自己踩过的坑,挑几个迁移里最容易出问题、又最值得提前想清楚的点展开讲。

3.2 渐进迁移,始终可回滚

需要注意的是:迁移到 Rush 不建议做成"停机一次大爆改",而更建议设计成一个可渐进推进、随时能回退的过程。所谓渐进,就是原有那套基建——旧工具的 workspace 配置、根 node_modules、原来的构建和 CI 脚本——都先原样留着,一个项目一个项目地往 Rush 里搬;只有当某个项目在 Rush 下装得上、构建得过、测试也通过了,才真正切走它的旧基建。任何一步出问题,都能退回旧路。

这样设计的好处,在仓库一大就很明显。一次性整体切换,失败面覆盖全仓,一旦中途出问题,谁都不敢合、也不好回滚,只能推倒重来。而新旧并存、一个个搬,失败面永远只锁在当前这一个项目上——搬一个、验一个,坏了就退这一个,随时可停、可退,迁移的风险始终是可控的。

渐进迁移,失败只退一个

代价是这个过程本身并不轻松,难点集中在新旧共存那段时间。迁移期两套 node_modules 布局、两套 lockfile、两套命令入口会短期并行,最要盯住的就是别让它们互相污染:装依赖时别把两套解析结果搅在一起,跑命令时别让开发者搞不清该走哪套入口。

具体怎么隔离,会随你旧工具的技术栈而变,与其自己硬啃,不如把这块交给 AI,让它针对你仓的实际情况推导出一套渐进兼容方案。关键是把约束交代清楚——共存、隔离、每步可验可回滚——再让它落到你这套技术栈的具体做法上:

我要把当前仓库从 <你的旧工具,如 pnpm workspace / lerna / 手写脚本> 渐进迁移到 Rush,
迁移期两套基建必须并存、随时可回滚。请针对这个技术栈,设计一套"新旧共存"的兼容方案:
1) 迁移期怎么隔离两套 node_modules / lockfile / 命令入口,确保依赖解析不互相污染;
2) 一个项目从旧基建切到 Rush 的切换点具体怎么定——切之前、切之后各自的验证清单;
3) 每一步对应的回滚操作:如果这个项目在 Rush 下没跑通,怎么干净地退回旧路;
4) 全部迁完后,统一移除旧基建的收尾清单。
先给方案我确认,不要直接改代码。

3.3 从叶子往回定顺序

要定迁移顺序,先得看清仓里的项目是怎么相互依赖的,也就是这个仓的依赖图。把每个项目当作一个节点,谁在自己 package.json 里依赖了仓内的另一个项目,就从它指向被依赖的那个,连一条边——所有节点和边合起来,就是这个仓的依赖图。举个例子:

@app/blog @ui/components @infra/utils @app/admin

这张图里,@infra/utils 不依赖仓内任何其他项目,处在最底层;@app/blog@app/admin 则站在最上层,直接或间接依赖着下面的包。像 @infra/utils 这种"只被别人依赖、自己不依赖仓内他人"的节点,就叫叶子节点

最好的迁移顺序,是从叶子节点开始,逐层往上:先迁 @infra/utils,确认它在 Rush 下装得上、构建得过,再迁依赖它的 @ui/components,最后才轮到 @app/blog@app/admin。这样每加一个包,新增的错误面都能定位到具体是哪个项目引入的;而且轮到上游时,它依赖的下游都已经在 Rush 里就位,不会出现"装到一半发现依赖的包还没迁"的空档。

问题是,四五个节点的小图靠肉眼就能扫出来,几十上百个包时,人工理清每条依赖边几乎不现实;何况迁移期这些项目还没登记进 rush.json,Rush 自己的依赖图工具也用不上。这时最好的办法是让 AI 写一个临时脚本,遍历各项目 package.json 里的 dependencies / devDependencies,只保留指向仓内其他包的边,构建出依赖图。有了这张图,迁移就变成一个可以反复跑的循环:每次让脚本报出"当前可迁的下一批"——也就是那些仓内依赖已经全部进了 Rush 的项目,迁完这批、验过之后再跑一次,报出再下一批,直到迁完。

写一个临时 Node 脚本,扫描 <待迁目录> 下所有 package.json,以 name 为节点、
只把指向这批包内部其他包的依赖当作边,构建依赖图。
入参传入"已迁移到 Rush 的包名清单"(首次为空),脚本据此输出:
1) 下一批可迁的包:仓内依赖已全部在"已迁清单"里的、尚未迁移的项目;
2) 若剩余未迁项目彼此成环、导致下一批为空,单独列出每个环上的包。
每迁完一批,把它们追加进"已迁清单"再跑一次,直到全部迁完。

拿到每一批的清单后,再把它作为迁移的施工单交回给 AI,让它一层层往 Rush 里搬:迁一个、装一个、验一个,通过了再进下一个。

3.4 循环依赖

按依赖顺序往下迁的过程里,有一种特殊情况会卡住:循环依赖。比如 @ui/components 依赖 @infra/utils,而 @infra/utils 又反过来依赖 @ui/components,两个包互相引用,构成一个环。这时你会发现,先迁哪一个都不对——迁 @ui/components,它依赖的 @infra/utils 还没进 Rush;先迁 @infra/utils,它又反过来依赖着 @ui/components。环里没有叶子,"从叶子往回"这套顺序也就排不出来。

理论上可以把整个环当成一个"打包单元"一次性迁进来,一起 rush update、一起构建。但循环依赖本身就是一种 bad case,它让模块边界变得模糊、构建和测试都难以单独进行,与其带着它进 Rush,我个人更建议趁迁移这个机会直接把环拆掉。

拆环常见的思路有两种:一是把两个包共同用到的那部分逻辑抽出来,下沉成一个新的、更底层的包,原来的两个包都改成依赖它,环就断了;二是审视这条互相引用的关系,判断其中一个方向是不是本就不该存在——很多环是"顺手 import 了一下"攒出来的,把那条多余的边去掉即可。具体拆法可以交给 AI 先出方案:

<包A> 和 <包B> 之间存在循环依赖。请:
1) 分析这两个包互相 import 了哪些符号,判断这个环是怎么形成的;
2) 给出拆环方案,优先考虑:(a) 把共同依赖的公共逻辑抽成一个新的底层包,
   两者都改为依赖它;(b) 若某个方向的依赖并非必要,直接移除那条边;
3) 说明每种方案要改动哪些文件、有什么风险,先给方案我确认,不要直接改代码。

循环依赖的系统性危害和更完整的拆解手法,留到第 7 章(依赖约束与治理)展开,这里只需在迁移时把环就地处理掉,不让它带进 Rush

3.5 迁一个项目的三个动作

确定迁移顺序后,具体的迁移动作主要包含以下三步:

  1. rush.jsonprojects[] 里显式登记,写清 packageNameprojectFolder。迁移的本质,就是往这份登记表里加行。
  2. 删掉项目级的 shrinkwrap(package-lock.json / yarn.lock)和项目级 .npmrc,把这些交给 common/config 集中管。
  3. rush scan幽灵依赖——代码里 require 了、但 package.json 没声明的那些包。迁移期这类问题最容易冒头:原来靠根 node_modules提升凑合能用,一进 Rush 的严格布局就暴露出来。这里只讲"迁移时用 rush scan 检查一遍",成因机制留到第 9 章。

这三个动作机械、繁琐、完全照图操作,正是最该交给 AI 去跑的活。给 agent 一条 Prompt,让它按顺序逐个迁:

我要把 <项目目录> 这个已有项目迁进当前 Rush 仓。请按顺序做:
1) 在 rush.json 的 projects[] 里为它加一条登记(packageName 取其 package.json
   的 name,projectFolder 取相对仓根的路径);
2) 删掉该项目目录下的 package-lock.json / yarn.lock 和项目级 .npmrc;
3) 跑 rush update 让它进全仓依赖树,再 rush scan 检查这个项目有没有幽灵依赖,
   把扫出来漏声明的包用 rush add 补进它的 package.json;
4) rushx build 确认它能单独构建通过。
每步做完告诉我结果,报错先停下来问我。

接着 3.3 定好的顺序,一次只迁一个,从叶子起,一个通过了再迁下一个。

3.6 收尾与代价

所有项目都迁进 Rush、逐个验证通过之后,才做最后一步:移除旧的 workspace 基建——旧的 workspace 配置、根 node_modules、旧的构建和 CI 脚本。这一步同样可以交给 AI,但前提是先确认旧基建确实没人再依赖:

当前仓库所有项目都已迁入 Rush 并能各自构建通过。现在要移除旧的 workspace 基建。请:
1) 先列出仓里还残留的旧基建:旧 workspace 配置(如 pnpm-workspace.yaml)、
   根目录 node_modules、旧的构建/CI 脚本,以及任何仍引用它们的地方;
2) 逐项确认这些残留是否还被引用,把"确认可删"和"仍被引用、需先改"分开列出;
3) 对可删项给出删除清单,对仍被引用项说明改动方案,先给结论我确认,再动手。

删干净之后,才算真正从旧方案切到了 Rush,与 3.2 的"渐进并存、验证通过才切走"对上——并存只是过程,清掉旧基建才是终点。

迁移不是零成本的:逐个登记、清本地锁文件、补漏声明的依赖,加上渐进期两套基建并存的维护开销,项目越多,这条路越长。但换来的是全程可回退、失败面锁定在单个项目的确定性——对一个跑着几百个包的仓来说,这笔投入是值得的。

4. CI 引导

本地建好了、项目也迁进来了,接下来让 CI 也能跑。这一节只讲"引导"这一步——怎么让 CI 装出对的 Rush、跑通 install 和 build,不碰缓存和增量(那些留到第 13 章)。

Rush 体系里 CI 的核心设计,是不在 CI 上手动全局装 Rush,而是用仓里的 install-run-rush.js 来引导:它会读 rush.json 里锁定的 rushVersion,在一个隔离目录里精确装出那个版本的 Rush,再用它执行后续命令——这样 CI 用的 Rush 就和本地严格一致(锚回第 2 节锁 rushVersion 那个决策)。这份一致性对 Monorepo 的稳定性很关键:同一份 lockfile、同一个 Rush,本地过了的东西到 CI 上就不会因为版本漂移而失败,能消除绝大多数"本地能跑、CI 却挂"的情况。

CI 自举出与本地一致的 Rush

理清这个逻辑之后,workflow 就可以直接交给 agent 生成:

为当前 Rush 仓生成一个 GitHub Actions workflow,写到 .github/workflows/。要求:
1) 用仓里的 common/scripts/install-run-rush.js 来引导 Rush,不要手动全局装 Rush;
2) 安装用 rush install(严格模式:只按 lockfile 装、不改动它,lockfile 与
   package.json 对不上就让 CI 失败),不要用 rush update;
3) 先用 setup-node 钉住 Node 版本(读 rush.json 里 nodeSupportedVersionRange 取),
   再依次 install → build。
install-run-rush.js 的路径和各版本从仓里读取自取,别写死。

这里以 GitHub Actions 为例。引导的原理和平台无关,核心都是用 install-run-rush.jsRush 自举出来;换成 GitLab CI、Jenkins 等其它平台,把上面 Prompt 里的平台和语法要求相应改一改即可。

它应当产出一份类似下面这样的最小 workflow,你可以拿来对照:

name: CI
on: [push, pull_request]

jobs:
  build:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 22.16.0
      - name: Install
        run: node common/scripts/install-run-rush.js install
      - name: Build
        run: node common/scripts/install-run-rush.js build

环境一致性见第 11 章,CI 的缓存与增量见第 13 章。

5. AI 接入

最后一步,把这个仓接进 AI。第 3 章第 9 节已经讲过为什么要接——同一份显式的结构化元信息,对人和对 AI 是同一份价值。这一节不重复那个论证,只讲怎么把它装起来用。

这里只做最小可用接入:让你建好仓之后,能直接用自然语言驱动 Rush,不必先啃完所有配置文件。更深的接入——affected、自研的 increment 命令、MCP 插件那些回路级能力——是第 14 章的主线。

官方给了两样现成资产,建好仓就能接:一个 MCP server,一套 context file 模板。

MCP server 是官方的 @rushstack/mcp-server,让 Claude Code、Cursor、Copilot 这类编码助手能实时查询和操作这个 monorepo——AI 可以直接问 Rush"有哪些项目、谁依赖谁、命令怎么跑",相当于把第 1 节那条临时问答做成了常驻能力。

接入可以用下面这条 Prompt 交给 agent 帮你完成:

把 @rushstack/mcp-server 接入当前编码助手,并配成随仓库共享给全队的形式。请:
1) 去官方 npm/CHANGELOG 查它的最新稳定版,别写死一个旧版本;
2) 按我当前用的助手(Cursor / VS Code / Claude Code 等),优先写成可提交进 Git 的
   workspace 级配置(如 .cursor/mcp.json、.vscode/mcp.json),让每人、每个分支用同一版本;
3) 配好后告诉我怎么验证它确实连上了。

MCP server 本身可用,但它的插件机制目前还是 0.x 的实验特性,想扩出团队专属能力得留意成熟度,展开在第 14 章。

context file 是各家编码助手约定的规则文件(.github/copilot-instructions.md.cursor/rules/rush.mdcCLAUDE.mdAGENTS.md 等),把"这个仓怎么用 Rush"就近喂给 AI,并随代码一起版本化。官方在 Agent context files 页面按助手列了一批现成模板。导入同样走 Prompt,让 agent 拉官方模板、再结合本仓实际裁剪出一份协作规范,每条都写清"怎么做加为什么":

去 Rush 官方文档的 Agent context files 页面(https://rushjs.io/pages/ai/context_files/),
拉取适配我当前编码助手的 context file 模板,结合本仓实际(包管理器、目录结构、
自定义命令),裁剪成一份贴合本仓的 context file,写到对应位置(如 CLAUDE.md /
AGENTS.md / .cursor/rules/rush.mdc)。至少覆盖以下规矩,每条写清"怎么做 + 为什么":
- 装依赖只走 rush update / rush install(禁止项目里直接 pnpm/npm/yarn install);
- 加第三方依赖用 rush add(会跑单一版本校验);
- 同一个库全仓统一版本,破例走 common-versions.json 显式登记;
- 构建/测试用 rush build / rushx(别在项目目录直接 pnpm run,会绕过增量与依赖图);
- 新增/移动项目同步在 rush.json 的 projects[] 登记。
描述意图、不硬编码本项目专属路径。先给我看裁剪后的内容再落盘。

这样一来,MCP 让 AI 查得到结构,context file 让它照规矩办事,一个补认知、一个补约束。

不过 context file 只是软约束,靠的是"提示 AI 该怎么做"。AI 会按自己的经验行事,有时会错误地直接用 pnpm/npm/yarn install 装依赖——这会绕过 Rush 的 symlink 还原和单一版本校验,直接制造幽灵依赖和版本漂移,属于高危动作。光靠提示拦不住,得从工具层面硬拦:这类硬约束应该写进 Claude Code 的 .claude/settings.json 的 deny 列表。软约束写进 context file 提示"该怎么做",硬约束写进 deny 直接"不许这么做",两者配合。

MCP 补认知、context file 补约束、deny 硬拦

结尾

本章从 rush init 开始,走完了把已有项目搬进 Rush、再让 CI 和 AI 都能跑起来的完整一遍。

本章重点:

  1. rush init 生成的是一套配置脚手架,但其中包管理器、工具版本锁、目录深度这几项一旦定就难改,得在一开始就想清楚、定下来。
  2. 迁移顺序按依赖图来定:先迁没有仓内依赖的叶子包,再迁依赖它们的上层包,逐层推进。每迁一个项目做三件事——往 projects[] 登记、删掉项目自己的锁文件、用 rush scan 查一遍幽灵依赖。全程渐进,任何一步都能回滚。
  3. CI 不手动全局装 Rush,而是用 install-run-rush.jsrush.json 里锁定的版本、自举出与本地一致的 Rush,这是后续一切 CI 能力的前提。
  4. 建好仓就能接入 AI:MCP server 让助手查得到仓库结构,context file 让它照 Rush 的规矩办事,高危动作再用 deny 列表从工具层拦死。

代价是这一批配置文件的认知成本,小仓不值得为此上 Rush。仓建好之后,下一章进入日常协作:登记表怎么用、单一版本策略怎么把几百个包的依赖收敛到一处。

On this page