跨仓库协作工作流

多仓库项目的统一管理 — Claude Code 工程实践

一、概述:跨仓库协作的挑战

现代软件工程中,项目规模不断膨胀,单一代码仓库(Monorepo)和多仓库(Polyrepo)两种架构各有利弊。当团队选择多仓库策略时,跨仓库协作便成为不可回避的工程难题。依赖管理、版本同步、CI/CD 协调、代码共享、Issue 追踪等环节都需要专门的工具和工作流来支撑。

Claude Code 作为 AI 辅助编程工具,能够在跨仓库协作场景中发挥独特作用——通过上下文感知、多文件分析、自动化脚本生成等能力,帮助团队高效管理多仓库间的复杂依赖关系。

核心挑战一览:

  • 多仓库间的依赖版本管理 —— 如何确保 A 仓库的变更不会破坏 B 仓库
  • 跨仓库的代码共享机制 —— 共享库、内部包的分发和版本控制
  • 统一 CI/CD 流水线 —— 依赖仓库更新后如何自动触发下游构建
  • 跨仓库 Issue 和 PR 的追踪 —— 全局视角的项目管理
  • Git 子模块和子树的管理 —— 子仓库的更新、冲突解决和迁移

二、多仓库策略选型:Monorepo vs Polyrepo

2.1 Monorepo 方案

Monorepo 将所有相关项目放在同一个 Git 仓库中管理。优点在于原子提交、统一构建、简化依赖。但仓库体积会快速增长,Git 操作性能下降,权限控制粒度较粗。

Turborepo 配置示例

# turbo.json — Turborepo 流水线配置 { "$schema": "https://turbo.build/schema.json", "globalDependencies": ["**/.env.*local"], "pipeline": { "build": { "dependsOn": ["^build"], "outputs": ["dist/**", ".next/**"], "inputs": ["src/**/*.ts", "src/**/*.tsx"] }, "test": { "dependsOn": ["build"], "inputs": ["src/**/*.test.ts", "src/**/*.spec.ts"] }, "lint": { "outputs": [] }, "deploy": { "dependsOn": ["build", "test", "lint"], "outputs": [] } } }

Nx 工作空间配置示例

# nx.json — Nx 工作空间配置 { "extends": "nx/presets/npm.json", "tasksRunnerOptions": { "default": { "runner": "nx/tasks-runners/default", "options": { "cacheableOperations": ["build", "test", "lint"], "parallel": 5 } } }, "targetDefaults": { "build": { "dependsOn": ["^build"], "outputs": ["{projectRoot}/dist"] }, "test": { "dependsOn": ["build"] } } }

2.2 Polyrepo 方案

Polyrepo 将不同服务或模块放在独立的 Git 仓库中。优点在于团队自治、独立发布、权限隔离。缺点是跨仓库变更需要多个 PR,版本对齐困难,全局重构成本高。

2.3 Workspace 方案

包管理器内置的 Workspace 功能是实现 Monorepo 的基础设施:

npm Workspaces

# package.json — npm workspaces 配置 { "name": "my-monorepo", "private": true, "workspaces": [ "packages/*", "apps/*" ], "scripts": { "build": "npm run build --workspaces --if-present", "test": "npm run test --workspaces --if-present", "lint": "npm run lint --workspaces --if-present" } }

Yarn Workspaces

# package.json — Yarn workspaces 配置 { "name": "my-monorepo", "private": true, "workspaces": { "packages": ["packages/*", "apps/*"], "nohoist": ["**/react-native", "**/react-native/**"] } }

pnpm Workspaces

# pnpm-workspace.yaml — pnpm workspace 配置 packages: - "packages/*" - "apps/*" - "tools/*" - "!**/test/fixtures/**"

选型建议:

  • 小型团队(<10人): Monorepo + pnpm workspaces + Turborepo,学习成本低,开箱即用
  • 中型团队(10-50人): Monorepo + Nx,缓存和分布式任务执行能力强
  • 大型组织(>50人): Polyrepo + 统一工具链 + 自动同步机制,团队自治与全局协调兼顾
  • 微服务架构: Polyrepo + CI/CD 协调发布 + 跨仓库依赖追踪

三、跨仓库依赖管理

3.1 版本同步策略

跨仓库依赖的核心问题是版本同步。常用的策略包括:

版本对齐脚本示例

# scripts/align-versions.sh — 多仓库版本对齐 #!/bin/bash # 跨仓库版本同步脚本:将核心库版本更新到所有下游仓库 CORE_VERSION=$(node -p "require('./packages/core/package.json').version") REPOS=("service-a" "service-b" "service-c" "web-app" "mobile-app") for repo in "${REPOS[@]}"; do echo "更新 $repo 中的 @myorg/core 到 v$CORE_VERSION ..." cd "../$repo" jq ".dependencies[\"@myorg/core\"] = \"^$CORE_VERSION\"" package.json \ > package.json.tmp && mv package.json.tmp package.json git add package.json git commit -m "chore: sync @myorg/core to v$CORE_VERSION" git push origin main cd - done echo "所有仓库版本已同步完成。"

3.2 依赖更新与变更检测

依赖更新需要自动化的变更检测机制。常用的方案是基于文件变化触发依赖分析:

# scripts/detect-changes.js — 变更检测自动化脚本 // 检测依赖变更并生成影响分析报告 const { execSync } = require('child_process'); const fs = require('fs'); function getDependentRepos(changedPackage) { const config = JSON.parse( fs.readFileSync('dependency-graph.json', 'utf-8') ); return config.dependencies .filter(dep => dep.dependency === changedPackage) .map(dep => dep.repository); } function checkForBreakingChanges(repo, oldVersion, newVersion) { const log = execSync( `git log ${oldVersion}..${newVersion} --oneline --grep="BREAKING"` ).toString().trim(); return log.length > 0; } const changedPkg = process.argv[2]; const oldVer = process.argv[3]; const newVer = process.argv[4]; const downstream = getDependentRepos(changedPkg); const hasBreaking = checkForBreakingChanges(changedPkg, oldVer, newVer); console.log(`检测到变更: ${changedPkg} ${oldVer} → ${newVer}`); console.log(`影响的下游仓库: ${downstream.join(', ')}`); console.log(`是否包含破坏性变更: ${hasBreaking ? '是' : '否'}`); if (hasBreaking) { console.log('建议: 创建跨仓库 PR 进行适配更新'); } else { console.log('建议: 自动提交依赖更新 PR 到下游仓库'); }

3.3 版本兼容矩阵管理

当涉及多个互相依赖的包时,维护版本兼容矩阵变得至关重要:

@myorg/core@myorg/utilsservice-aservice-b兼容性
1.0.x1.0.x2.x3.x兼容
1.1.x1.1.x2.x3.x兼容
2.0.x2.0.x3.x4.x需要迁移
2.0.x1.x不兼容
# dependency-graph.json — 版本兼容矩阵定义 { "packages": { "@myorg/core": { "latest": "2.0.0", "compatible": ["1.0.0", "1.1.0"] }, "@myorg/utils": { "latest": "2.0.0", "compatible": ["1.0.0", "1.1.0"] }, "@myorg/types": { "latest": "1.5.0", "compatible": ["1.0.0"] } }, "dependencies": [ { "repository": "service-a", "dependency": "@myorg/core", "range": "^1.0.0" }, { "repository": "service-b", "dependency": "@myorg/core", "range": "^2.0.0" }, { "repository": "service-a", "dependency": "@myorg/utils", "range": "^1.0.0" } ], "rules": [ { "if": "core@^1.0.0 && utils@^1.0.0", "then": "service-a@2.x" }, { "if": "core@^2.0.0 && utils@^2.0.0", "then": "service-b@4.x" } ] }

3.4 自动发布与包发布顺序

在多包仓库中,包的发布顺序直接影响下游依赖的可用性。正确的策略是拓扑排序:先发布最底层的依赖包,逐层向上发布。

# scripts/publish-order.sh — 拓扑排序发布脚本 #!/bin/bash # 基于依赖关系拓扑排序,确定包发布顺序 calculate_publish_order() { node -e " const graph = { '@myorg/types': [], '@myorg/utils': ['@myorg/types'], '@myorg/core': ['@myorg/utils'], '@myorg/react-ui': ['@myorg/core', '@myorg/utils'], '@myorg/server-sdk': ['@myorg/core'], '@myorg/client-sdk': ['@myorg/core', '@myorg/utils'], }; // Kahn 拓扑排序 const inDegree = {}; const adj = {}; Object.keys(graph).forEach(pkg => { inDegree[pkg] = inDegree[pkg] || 0; adj[pkg] = adj[pkg] || []; graph[pkg].forEach(dep => { adj[dep] = adj[dep] || []; adj[dep].push(pkg); inDegree[pkg] = (inDegree[pkg] || 0) + 1; }); }); const queue = Object.keys(inDegree).filter(p => inDegree[p] === 0); const order = []; while (queue.length > 0) { const pkg = queue.shift(); order.push(pkg); (adj[pkg] || []).forEach(dep => { inDegree[dep]--; if (inDegree[dep] === 0) queue.push(dep); }); } console.log('发布顺序:'); order.forEach((pkg, i) => console.log(\` \${i + 1}. \${pkg}\`)); " } order=$(calculate_publish_order) echo "$order" # 按顺序执行发布 for pkg in $(echo "$order" | grep -oP '\d+\.\s+\K\S+'); do echo "正在发布 $pkg ..." (cd "packages/$pkg" && npm publish) done echo "所有包发布完成!"

四、统一 CI/CD 流水线

4.1 多仓库流水线架构

跨仓库的 CI/CD 策略需要在独立构建和统一协调之间取得平衡。推荐的架构是:每个仓库维护自己的 CI 配置,但通过共享的 Workflow 模板和跨仓库触发机制实现统一调度。

GitHub Actions 跨仓库触发

# .github/workflows/跨仓库触发.yml — 上游更新时触发下游构建 name: 跨仓库触发构建 on: push: branches: [main] paths: - 'packages/core/**' - 'packages/utils/**' jobs: trigger-downstream: runs-on: ubuntu-latest steps: - name: 触发下游仓库构建 uses: peter-evans/repository-dispatch@v3 with: token: ${{ secrets.CROSS_REPO_PAT }} repository: myorg/service-a event-type: upstream-changed client-payload: | { "upstream": "${{ github.repository }}", "ref": "${{ github.ref }}", "commit": "${{ github.sha }}", "changed-packages": ["core", "utils"] } - name: 触发 service-b 构建 uses: peter-evans/repository-dispatch@v3 with: token: ${{ secrets.CROSS_REPO_PAT }} repository: myorg/service-b event-type: upstream-changed client-payload: '{"upstream": "${{ github.repository }}"}' - name: 等待下游构建完成 run: | echo "等待所有下游仓库构建完成..." # 实际可用 GitHub API 轮询构建状态 sleep 30 echo "所有下游构建已触发。"

下游仓库接收事件并构建

# .github/workflows/上游依赖更新.yml — 下游仓库接收上游事件 name: 上游依赖更新 on: repository_dispatch: types: [upstream-changed] jobs: build-and-test: runs-on: ubuntu-latest steps: - uses: actions/checkout@v4 - name: 解析上游信息 run: | echo "上游仓库: ${{ github.event.client_payload.upstream }}" echo "触发提交: ${{ github.event.client_payload.commit }}" - name: 更新依赖版本 run: | UPSTREAM_COMMIT="${{ github.event.client_payload.commit }}" # 更新 package.json 中的依赖引用 jq '.dependencies["@myorg/core"] = "github:myorg/core#'$UPSTREAM_COMMIT'"' \ package.json > package.json.tmp mv package.json.tmp package.json - name: 安装依赖 run: npm ci - name: 运行测试 run: npm test - name: 构建 run: npm run build - name: 创建自动更新 PR if: success() uses: peter-evans/create-pull-request@v6 with: token: ${{ secrets.GITHUB_TOKEN }} commit-message: "chore: auto-update dependency to ${{ github.event.client_payload.commit }}" title: "自动依赖更新: 来自 ${{ github.event.client_payload.upstream }}" body: | 上游仓库 ${{ github.event.client_payload.upstream }} 已更新。 本次提交已通过构建和测试验证。 branch: auto-dependency-update delete-branch: true

4.2 协调发布与批量更新

当多个仓库需要同时发布时,协调发布策略至关重要。常用的模式包括:

跨仓库批量更新脚本

# scripts/batch-update.sh — 跨仓库批量更新 #!/bin/bash # 批量创建跨仓库 PR 用于更新依赖 REPOS=("service-a" "service-b" "service-c" "web-app" "admin-panel") BRANCH="chore/update-core-to-v2" TITLE="chore: 更新 @myorg/core 到 v2.0.0" BODY="更新核心库到 v2.0.0,修复了若干安全性问题并提升了性能。" for repo in "${REPOS[@]}"; do echo "处理 $repo ..." git clone "git@github.com:myorg/$repo.git" "tmp/$repo" cd "tmp/$repo" git checkout -b "$BRANCH" # 更新依赖版本 jq '.dependencies["@myorg/core"] = "^2.0.0"' package.json > pkg.tmp mv pkg.tmp package.json git add package.json git commit -m "$TITLE" git push origin "$BRANCH" # 创建 PR gh pr create \ --repo "myorg/$repo" \ --title "$TITLE" \ --body "$BODY" \ --base main \ --head "$BRANCH" cd ../.. rm -rf "tmp/$repo" done echo "所有仓库的 PR 已创建完成!"

五、代码共享策略

5.1 共享库与内部包

代码共享是跨仓库协作的核心需求。常见的共享方式包括:

私有 npm 包发布示例

# scripts/publish-private-pkg.sh — 发布到私有 npm registry #!/bin/bash set -e REGISTRY="https://npm.pkg.github.com" SCOPE="@myorg" PACKAGE_DIR="./packages/shared-utils" echo "构建共享包..." cd "$PACKAGE_DIR" npm run build echo "配置私有 registry..." echo "registry=$REGISTRY" > .npmrc echo "//npm.pkg.github.com/:_authToken=$GITHUB_TOKEN" >> .npmrc echo "发布到私有 registry..." npm publish --registry="$REGISTRY" --access restricted echo "清理..." rm .npmrc echo "共享包发布成功!版本: $(node -p 'require(\"./package.json\").version')"

5.2 代码生成器与模板仓库

对于需要在多个仓库中重复使用的标准化代码结构,代码生成器和模板仓库是最有效的方案。

使用 Claude Code 生成跨仓库代码生成器

# generator/cli.js — 基于模板的跨仓库代码生成器 const fs = require('fs-extra'); const path = require('path'); const handlebars = require('handlebars'); const { execSync } = require('child_process'); async function generateService(name, { repo, description, port }) { const templateDir = path.resolve(__dirname, '../templates/service'); const outputDir = path.resolve(process.cwd(), repo); // 克隆基础模板仓库 execSync(`git clone git@github.com:myorg/service-template.git ${outputDir}`); // 读取模板文件 const files = await fs.readdir(templateDir); for (const file of files) { const content = await fs.readFile( path.join(templateDir, file), 'utf-8' ); const template = handlebars.compile(content); const rendered = template({ name, description, port }); const outputFile = file.replace('.hbs', ''); await fs.writeFile( path.join(outputDir, outputFile), rendered ); } // 初始化 Git 并推送 execSync(` cd ${outputDir} && git init && git add . && git commit -m "chore: initial commit from template" && git remote add origin git@github.com:myorg/${repo}.git && git push -u origin main `); console.log(`服务 ${name} 已生成并推送到 ${repo} 仓库`); } generateService('user-service', { repo: 'user-service', description: '用户管理微服务', port: 3001 });

5.3 脚手架工具

专业的脚手架工具可以大幅提升跨仓库初始化的效率:

# .claude/settings.json — Claude Code 跨仓库脚手架配置 { "hooks": { "postCreate": { "command": "node .claude/init-repo.js", "description": "初始化仓库结构和依赖" } }, "allowedCommands": { "createRepo": { "command": "gh repo create myorg/${1} --private --template myorg/service-template", "description": "从模板创建新仓库" }, "setupWorkspace": { "command": "node .claude/setup-workspace.js ${1}", "description": "设置跨仓库开发环境" } } }
# .claude/setup-workspace.js — 跨仓库开发环境初始化 const { execSync } = require('child_process'); const fs = require('fs'); const path = require('path'); function setupCrossRepoWorkspace(workspaceName) { const rootDir = path.resolve(process.cwd(), '..', workspaceName); if (!fs.existsSync(rootDir)) { fs.mkdirSync(rootDir, { recursive: true }); } // 创建 workspace 级别的 package.json const workspacePkg = { name: workspaceName, private: true, workspaces: ['packages/*', 'services/*'], scripts: { build: 'turbo run build', test: 'turbo run test', lint: 'turbo run lint', clean: 'turbo run clean', }, devDependencies: { turbo: 'latest', typescript: '^5.0.0', }, }; fs.writeFileSync( path.join(rootDir, 'package.json'), JSON.stringify(workspacePkg, null, 2) ); console.log(`Workspace ${workspaceName} 已创建`); console.log(`请运行: cd ${rootDir} && npm install`); } const name = process.argv[2] || 'my-workspace'; setupCrossRepoWorkspace(name);

六、跨仓库 Issue 管理

6.1 全局看板与跨仓库标签

当 Issue 分散在多个仓库中时,需要一个统一的管理视图。推荐的方案包括:

跨仓库 Issue 标签同步脚本

# scripts/sync-labels.sh — 跨仓库标签同步 #!/bin/bash # 确保所有仓库使用统一的标签体系 REPOS=("core" "service-a" "service-b" "web-app" "mobile-app") LABELS=( "bug:red" "enhancement:blue" "feature:green" "breaking:orange" "good-first-issue:purple" "area/frontend:yellow" "area/backend:grey" "area/infra:dark-blue" "priority/P0:red" "priority/P1:orange" "priority/P2:yellow" "priority/P3:grey" ) for repo in "${REPOS[@]}"; do echo "同步 $repo 标签..." for label in "${LABELS[@]}"; do IFS=':' read -r name color <<< "$label" gh label create "$name" --color "$color" \ --repo "myorg/$repo" --force 2>/dev/null done done echo "所有仓库标签已同步完成!"

6.2 跨仓库 Issue 依赖追踪

当一个功能的实现需要在多个仓库中分别提交变更时,追踪 Issue 间的依赖关系就变得至关重要。

# .github/ISSUE_TEMPLATE/跨仓库功能请求.md --- name: 跨仓库功能请求 about: 描述一个需要在多个仓库中实现的功能 title: "[CROSS-REPO] " labels: cross-repo, feature --- ## 功能描述 [清晰描述需要实现的功能] ## 涉及的仓库 - [ ] myorg/core — [所需变更] - [ ] myorg/service-a — [所需变更] - [ ] myorg/web-app — [所需变更] ## 依赖关系 - [ ] 阻塞: #ISSUE_NUMBER - [ ] 被阻塞: #ISSUE_NUMBER ## 实现计划 1. 步骤 1: [仓库名] — [变更描述] 2. 步骤 2: [仓库名] — [变更描述] 3. 步骤 3: [仓库名] — [变更描述] ## 验收标准 - [ ] 标准 1 - [ ] 标准 2 ## 关联 PR - [ ] myorg/core#PR_NUMBER - [ ] myorg/service-a#PR_NUMBER

6.3 跨仓库依赖追踪工具

# scripts/cross-repo-issue-tracker.js — 跨仓库 Issue 状态汇总 const { execSync } = require('child_process'); async function getCrossRepoStatus(milestone) { const repos = ['core', 'service-a', 'service-b', 'web-app']; const report = []; for (const repo of repos) { const output = execSync( `gh issue list --repo myorg/${repo} ` + `--milestone "${milestone}" ` + `--json number,title,state,labels,assignees` ).toString(); const issues = JSON.parse(output); issues.forEach(issue => { report.push({ repo, number: issue.number, title: issue.title, state: issue.state, labels: issue.labels.map(l => l.name), assignees: issue.assignees.map(a => a.login), url: `https://github.com/myorg/${repo}/issues/${issue.number}`, }); }); } // 生成状态报告 console.log(`=== 里程碑: ${milestone} ===`); console.log(`总 Issue 数: ${report.length}`); console.log( `已完成: ${report.filter(i => i.state === 'closed').length}` ); console.log( `进行中: ${report.filter(i => i.state === 'open').length}` ); // 按仓库分组 const byRepo = {}; report.forEach(i => { byRepo[i.repo] = byRepo[i.repo] || []; byRepo[i.repo].push(i); }); Object.entries(byRepo).forEach(([repo, issues]) => { console.log(`\n--- ${repo} ---`); issues.forEach(i => { console.log(` #${i.number} [${i.state}] ${i.title}`); }); }); return report; } getCrossRepoStatus('v2.0 Release');

七、Git 子模块与子树

7.1 Git Submodule 管理

Git 子模块允许将一个仓库作为另一个仓库的子目录嵌入。虽然功能强大,但管理不当会导致诸多问题。

子模块操作命令集

# 子模块基础操作命令 # 添加子模块 git submodule add git@github.com:myorg/shared-lib.git packages/shared-lib # 克隆包含子模块的仓库 git clone --recurse-submodules git@github.com:myorg/main-repo.git # 更新所有子模块到最新提交 git submodule update --remote --merge # 初始化子模块(克隆后首次使用) git submodule update --init --recursive # 递归遍历子模块执行命令 git submodule foreach 'git checkout main && git pull' # 查看子模块状态 git submodule status # 删除子模块(步骤较多) git submodule deinit -f packages/shared-lib git rm packages/shared-lib rm -rf .git/modules/packages/shared-lib

子模块更新自动化脚本

# scripts/update-submodules.sh — 批量更新子模块脚本 #!/bin/bash # 安全地更新所有子模块到指定分支的最新提交 set -e BRANCH=${1:-main} echo "正在更新子模块到 $BRANCH 分支的最新提交..." # 遍历所有子模块 git submodule foreach " echo \"处理子模块: \$name\" git fetch origin git checkout $BRANCH git pull origin $BRANCH if [ \$? -ne 0 ]; then echo \"警告: \$name 更新失败,请手动检查\" exit 1 fi echo \"\$name 已更新到 \$(git rev-parse --short HEAD)\" " # 提交子模块更新 git add . git commit -m "chore: update submodules to latest $BRANCH" echo "所有子模块已更新完毕!"

7.2 Git Subtree 合并策略

与子模块不同,子树合并将外部仓库的代码直接复制到当前仓库中,不保留外部引用。这意味着主仓库的克隆不需要额外操作,但更新时需要手动同步。

子树操作命令集

# 子树基础操作命令 # 添加子树(将外部仓库添加到子目录) git subtree add \ --prefix packages/shared-lib \ git@github.com:myorg/shared-lib.git \ main --squash # 从子树源仓库拉取更新 git subtree pull \ --prefix packages/shared-lib \ git@github.com:myorg/shared-lib.git \ main --squash # 将子目录的变更推回源仓库 git subtree push \ --prefix packages/shared-lib \ git@github.com:myorg/shared-lib.git \ feature/new-feature # 拆分子树为独立仓库(保留历史) git subtree split \ --prefix packages/shared-lib \ --branch shared-lib-standalone # 合并子树拆分后的分支到新仓库 mkdir ../shared-lib && cd ../shared-lib git init git pull ../main-repo shared-lib-standalone

7.3 冲突解决策略

子模块和子树在团队协作中最容易遇到的问题就是冲突。以下是一些实用的冲突解决策略:

# 子模块冲突解决流程 # 1. 检查冲突状态 git status # 输出: modified: packages/shared-lib (modified content, untracked content) # 2. 进入冲突的子模块目录 cd packages/shared-lib # 3. 查看子模块当前状态 git status git log --oneline -5 # 4. 解决冲突:选择正确的提交 git checkout <正确的提交哈希> # 5. 回到主仓库,提交解决后的状态 cd ../.. git add packages/shared-lib git commit -m "fix: resolve submodule conflict in shared-lib"

子模块 vs 子树 对比

特性Git SubmoduleGit Subtree
代码存储方式指针引用(链接)直接复制代码
克隆体验需要 --recurse-submodules正常克隆即可
修改流程在子模块中修改后推送在主仓库中修改后子树推送
历史保留保留子模块完整历史可选 --squash 压缩历史
学习曲线中等较高
适合场景大型共享库、频繁更新小型工具、偶尔更新

7.4 从子模块迁移到 Monorepo

当项目规模增长到一定程度,团队可能会决定从子模块方案迁移到 Monorepo。这是一个需要谨慎规划的过程:

# scripts/migrate-submodules-to-monorepo.sh — 子模块到 Monorepo 迁移 #!/bin/bash # 将子模块仓库的历史合并到 Monorepo 中 set -e MONOREPO_DIR="my-monorepo" SUB_MODULES=( "packages/shared-lib:git@github.com:myorg/shared-lib.git" "packages/utils:git@github.com:myorg/utils.git" "services/service-a:git@github.com:myorg/service-a.git" ) echo "创建 Monorepo..." mkdir -p "$MONOREPO_DIR" cd "$MONOREPO_DIR" git init echo "合并子模块历史..." for entry in "${SUB_MODULES[@]}"; do IFS=':' read -r target_path repo_url <<< "$entry" echo "合并 $repo_url 到 $target_path ..." # 添加远程仓库 git remote add -f "remote-$(echo $target_path | tr '/' '-')" "$repo_url" # 合并历史,将仓库内容放到子目录 git merge -s ours --no-commit \ "remote-$(echo $target_path | tr '/' '-')/main" \ --allow-unrelated-histories 2>/dev/null || true # 读取源树并放到目标路径 git read-tree --prefix="$target_path/" \ "remote-$(echo $target_path | tr '/' '-')/main" git commit -m "chore: merge $target_path into monorepo" # 移除临时远程 git remote remove "remote-$(echo $target_path | tr '/' '-')" done echo "Monorepo 创建完成!" echo "所有子模块历史已保留在对应的子目录中。" echo "请验证后推送到远程仓库。"

八、使用 Claude Code 管理跨仓库工作流

8.1 跨仓库代码审查

Claude Code 可以同时分析多个仓库的代码变更,帮助审查跨仓库 PR 的整体影响。

# .claude/commands.yml — Claude Code 跨仓库命令配置 commands: cross-review: description: "审查跨仓库 PR 集合" command: | repos=("service-a" "service-b" "web-app") for repo in "${repos[@]}"; do echo "=== 审查 $repo ===" gh pr view $repo#$PR_NUMBER --json files,body,title done check-deps: description: "检查跨仓库依赖一致性" command: | node scripts/check-cross-repo-deps.js sync-versions: description: "同步所有仓库的依赖版本" command: | node scripts/sync-all-versions.js status-report: description: "生成跨仓库状态报告" command: | node scripts/cross-repo-issue-tracker.js "$MILESTONE"

8.2 自动化跨仓库 PR 创建

# scripts/create-cross-repo-pr.js — 跨仓库 PR 创建自动化 const { execSync } = require('child_process'); async function createCrossRepoPR({ repos, branch, title, body, base = 'main', }) { const results = []; for (const repo of repos) { console.log(`在 ${repo} 中创建 PR...`); try { const prUrl = execSync( `gh pr create --repo myorg/${repo} ` + `--title "${title}" ` + `--body "${body}" ` + `--base ${base} ` + `--head ${branch} ` + `--label cross-repo` ).toString().trim(); results.push({ repo, url: prUrl, status: 'success' }); console.log(` PR 创建成功: ${prUrl}`); } catch (err) { results.push({ repo, error: err.message, status: 'failed' }); console.error(` 创建失败: ${err.message}`); } } // 输出汇总报告 console.log('\n=== 跨仓库 PR 创建报告 ==='); results.forEach(r => { console.log( ` ${r.repo}: ${r.status === 'success' ? '✓' : '✗'} ${r.url || r.error}` ); }); return results; } // 示例:为版本更新创建跨仓库 PR createCrossRepoPR({ repos: ['service-a', 'service-b', 'web-app', 'admin-panel'], branch: 'chore/update-core-to-v2', title: 'chore: update @myorg/core to v2.0.0', body: `## 变更说明 更新 @myorg/core 到 v2.0.0。 ### 主要变更 - 改进了 API 响应性能 - 修复了内存泄漏问题 - 更新了 TypeScript 类型定义 ### 兼容性 - 需要 Node.js >= 18 - API 接口完全向后兼容 ### 测试 - [x] 单元测试通过 - [x] 集成测试通过 🤖 由 Claude Code 自动创建。`

8.3 跨仓库重构辅助

当需要在多个仓库中进行同步重构时,Claude Code 可以分析所有相关仓库的代码,生成一致的变更方案:

# Claude Code 提示词:跨仓库 API 重构 # 场景:将 @myorg/core 中的 getUser 改为 findUser 请帮我完成跨仓库重构: 1. **主仓库 (myorg/core)**: - 在 `src/user.ts` 中将 `getUser` 重命名为 `findUser` - 保留 `getUser` 作为别名并标记为 `@deprecated` - 更新所有内部引用 2. **下游仓库 (service-a, service-b, web-app)**: - 在 `package.json` 中更新 `@myorg/core` 版本 - 将所有 `import { getUser }` 改为 `import { findUser }` - 更新所有使用 `getUser()` 的调用 3. **验证**: - 确保类型定义同步更新(`types.ts`) - 确保测试文件同步修改 - 生成变更日志条目 请为每个仓库生成对应的 PR。

九、核心要点总结

十、进一步思考与实践建议

团队落地路线图

  1. 第一阶段(1-2周): 统一标签体系,建立跨仓库 Issue 追踪规范
  2. 第二阶段(2-4周): 搭建私有 npm registry,将共享库提取为独立包
  3. 第三阶段(4-8周): 实现 CI/CD 跨仓库触发和自动 PR 创建
  4. 第四阶段(8-12周): 评估子模块迁移到 Monorepo 的可行性,制定迁移计划
  5. 第五阶段(持续): 引入 Claude Code 等 AI 工具,优化跨仓库开发体验

推荐工具链