본문으로 건너뛰기
cccskills
무료GitHub에 공개

worktree-stack-migrate

HTCMC PCHSystem 专用 skill——指导如何在 git worktree 中正确启动/迁移开发栈 (根 docker-compose 的 postgres+backend、TestServer 的 mc-test、前端 Vite dev)。

PCHSystem 的栈路径锚定主仓(bind mount / external 网络 / MCDR 挂载 / 根 .env 插值), worktree 的目录隔离与之天然冲突,常踩「端口对不上 / token 对不上 / 配置在别的分支」三类坑。

本 skill 给出按「worktree 改了什么」选择的迁移策略 + 端口/token/网络对齐清单 + 红线陷阱。

当用户在 worktree 里要起栈测试、提到「worktree 跑后端/前端/mc-test」「worktree 端口冲突」 「token 对不上 / 401」「主仓有 WIP 没法 checkout 分支」「MCDR reload 看不到 worktree 改动」, 或要在 worktree 改了 Dockerfile / pyproject / 端口 / .env 后验证时,就应使用本 skill。

不用:纯文档或单文件编辑、不涉及运行栈的常规开发、或仅在主仓主线本地开发(不起 worktree)。

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

연동 도구PostgreSQL
설치 방법 보기

포함된 파일(1)

  • SKILL.md15.1 KB

SKILL.md(원문)

설치하기 전에 에이전트에게 전달되는 지시 내용을 확인할 수 있습니다.

worktree-stack-migrate · 把开发栈迁进 worktree

1. 这个 skill 做什么

PCHSystem 的开发栈路径锚定主仓 /home/yushen/opt/PCHSystem,而 worktree 是 .claude/worktrees/<name>/ 下的独立目录——两者天然打架。本 skill 给出两样东西:

  • 一张按改动类型选择迁移策略的决策表(§5);
  • 三份对齐清单:端口(§6)/ token 与密钥(§7)/ 网络名(§8),外加起栈后验证(§9)与红线陷阱(§10)。

目标:在 worktree 里测某分支代码时,栈能起来、和主仓栈不互踩、端口 token 自洽、不污染主线。


2. 何时用 / 何时不用

用:

  • 在 worktree 改了后端/前端/MCDR 代码,要在运行栈上验证
  • worktree 改了 Dockerfile / pyproject.toml / 端口 / .env,需要重建镜像或起独立栈
  • 主仓 main 有未提交 WIP,无法 git checkout <worktree 分支> 把代码放进主仓测
  • 遇到 worktree 起的栈端口冲突 / token 401 / mc-test 连不上 backend / MCDR reload 没反应

不用:

  • 直接在主仓主线本地开发(不起 worktree → 普通 docker compose up -d 即可,见 Docs/cheatsheets/dev-cheatsheet.md)
  • 纯文档/单文件编辑、不涉及运行栈

3. 背景:为什么 worktree 和开发栈打架

理解这四条机制,后面的规则就能推理而不是死记:

  1. 三个 bind mount 相对仓根解析:根 docker-compose.yml 的 backend 挂 ./Backend/app:/app/app、./Backend/alembic:/app/alembic、./Archive:/app/archive。在主仓跑 compose,容器读的是主仓源码;worktree 的源码对运行中的容器不可见。
  2. compose 项目名 = 目录名:主仓目录 PCHSystem → 项目名 pchsystem → 网络 pchsystem_default、容器 pchsystem-backend-1 / pchsystem-postgres-1、卷 pchsystem_pgdata。从 worktree 目录跑 compose,项目名变成 worktree 目录名,天然与 pchsystem 隔离(-p <feat> 只是显式化)。
  3. TestServer/docker-compose.yml 写死 pchsystem_default external:true:mc-test 没有自己的 postgres,加入主仓网络,容器内以 http://pchsystem-backend-1:8000 访问后端。它依赖主仓栈已在运行,且只能看到 pchsystem 项目里的 backend。
  4. MCDR 插件挂载落主仓:TestServer/docker-compose.yml 的 ../McdrPlugin/pch_system:/mcdr/plugins/pch_system,../ 相对 TestServer/ → 解析到主仓插件目录。游戏内 !!MCDR plugin reload pch_system 只读主仓工作树。
  5. compose ${VAR} 插值读根 .env(compose 文件同目录),不是 Backend/.env。Backend/.env 是另一份,仅供宿主机直跑 uvicorn/pytest(POSTGRES_HOST=localhost、POSTGRES_PORT=5433)。

推论:要在 worktree 测代码,要么让运行中的主仓栈改读 worktree 源码(策略 A/A+),要么在 worktree 起一套独立栈(策略 B)。前端 / MCDR 各有专门处理(策略 C / D)。


4. 第一步:进 worktree 前的对齐

EnterWorktree 默认 base = origin/<default>,本仓 default 常被识别成旧的 feat/backend-phase0-foundation(Frontend 几乎空)。新建 worktree 后先对齐主线最新已提交状态:

git reset --hard main     # worktree 分支对齐主线最新;不污染主仓工作树(主仓 WIP 留在主仓)
# 软链主仓已装的 node_modules(package.json 跨分支通常无差异,软链安全,省一次 npm install)
ln -s /home/yushen/opt/PCHSystem/Frontend/node_modules Frontend/node_modules

5. 按改动类型选策略(核心决策表)

先问:worktree 相对主仓改了什么? 对号入座。

worktree 改了什么策略主仓栈端口何时选它
仅 Backend/app / alembic 源码A复用 pchsystem 单栈不变(8000/5433)主仓有 WIP 不便 checkout;只想让运行中的 backend 读 worktree 源码
源码 + Dockerfile / pyproject.toml / 系统包A+复用 pchsystem 单栈不变新依赖/新字体/新系统包,必须重建镜像
要与主栈并存独立测B主栈保持运行 + worktree 独立栈错开(8002/5434)需对照主栈、或不想动主栈
仅前端C主 backend 不动5174 或复用 5173只改 Vue 代码
MCDR 插件 .pyD复用主 mc-test不变改插件后要游戏内 reload 验证

策略 A —— 主仓写 override 换挂载源(仅源码)

主仓根写 docker-compose.override.yml(已被 .gitignore,含机器绝对路径,勿提交;它是 per-machine 逃生口):

# 主仓根:docker-compose.override.yml
services:
  backend:
    build: ./.claude/worktrees/<name>/Backend
    volumes:
      - ./.claude/worktrees/<name>/Backend/app:/app/app
      - ./.claude/worktrees/<name>/Backend/alembic:/app/alembic
      # Archive 不列 → 继承 base 的 ./Archive:/app/archive(主仓 Archive,无所谓)

Compose v2 对 volumes 按 target 去重:同 target 时 override 替换 base,不会双挂载。

docker compose up -d backend          # 主仓目录跑;override 已把 build+挂载指向 worktree

恢复:rm docker-compose.override.yml && docker compose up -d backend(镜像已有依赖则无需 rebuild)。

策略 A+ —— A 之上重建镜像(依赖/字体/系统包变了)

A 的 override 已把 build context 指向 worktree,所以重建会拿 worktree 的 Dockerfile + pyproject.toml:

docker compose build backend && docker compose up -d backend

注意:主仓 override 仅换 app/ 源码挂载时,镜像仍是主仓旧依赖——新 import 会运行时报错。这就是 A+ 存在的理由。

策略 B —— worktree 起独立栈(与主栈并存)

从 worktree 根跑(项目名 = worktree 目录名,天然与 pchsystem 隔离):

ln -sfn /home/yushen/opt/PCHSystem/.env .env     # compose 插值需要根 .env(POSTGRES_PASSWORD/JWT_SECRET/MCDR_SERVICE_TOKEN…)
docker compose -p <feat> up -d --build            # -p 显式项目名 → 独立 <feat>-* 容器 + <feat>_pgdata 卷
docker compose -p <feat> exec backend alembic upgrade head   # 新 <feat>_pgdata 是空的,必须建表

端口错开(worktree 根 docker-compose.override.yml,需 Docker Compose v2.40+ 的 !override):

# worktree 根:docker-compose.override.yml
services:
  backend:
    ports: !override
      - "127.0.0.1:8002:8000"     # 只错开宿主映射;容器内仍是 8000
  postgres:
    ports: !override
      - "127.0.0.1:5434:5432"

主仓 pchsystem-* 栈保持不动(勿停,见红线 5)。<feat>_pgdata 与 pchsystem_pgdata 是两个卷,互不影响(遵守 R-1:主仓业务库仍由主仓独占)。

策略 C —— 仅前端

lsof -ti :5173 | xargs -r kill                 # 杀主仓 Vite(若占着 5173)
cd Frontend && npm run dev -- --port 5174      # 复用主仓 5173 也行;勿改 vite.config.ts(见红线 8)

前端 vite.config.ts 的 proxy 写死 /api → http://localhost:8000。若 worktree backend 也走策略 A/A+ 复用主仓 8000 端口,proxy 不用改,最省事。若走策略 B(worktree backend 在 8002),需临时把 proxy target 改 8002——改完务必 git checkout HEAD -- Frontend/vite.config.ts 还原,绝不提交。

策略 D —— MCDR 插件 .py

容器挂载的是主仓 McdrPlugin/pch_system(§3 机制 4),!!MCDR plugin reload 看不到 worktree 改动。验证前先把改动同步到主仓路径:

# 二选一:直接编辑主仓对应文件 / 或 commit 后 git -C 主仓 merge <worktree分支>
grep -n '<关键改动>' /home/yushen/opt/PCHSystem/McdrPlugin/pch_system/<file>.py   # 确认两边一致
# 游戏内:!!MCDR plugin reload pch_system

MCDR 相关 API / 命令树须先联网核实(根 CLAUDE.md §0 S-1),见 https://docs.mcdreforged.com/en/latest/plugin_dev/command.html。


6. 端口对齐

服务主栈 pchsystemworktree 独立栈 -p <feat>改哪里
backend8000127.0.0.1:8002worktree docker-compose.override.yml ports: !override
postgres127.0.0.1:5433127.0.0.1:5434同上(5432 被别项目 pf-postgres 占,主仓才用 5433)
frontend(Vite)51735174 或复用CLI --port;勿入 vite.config.ts
mc-test25565(MC)/ 25575(RCON)25566/25576 或省略仅当起 worktree mc-test

只错开「宿主→容器」映射,容器内部端口不变(backend 恒 8000、pg 恒 5432),所以 backend 的 POSTGRES_HOST=postgres / POSTGRES_PORT=5432 与 WEB_BASE_URL 在容器视角下都无需改。

WEB_BASE_URL(!!PCH login 回调前缀)要等于玩家浏览器实际访问的前端端口(默认 http://localhost:5173)。


7. token / 密钥对齐清单

变量对齐要求不一致的后果
MCDR_SERVICE_TOKENworktree backend 的根 .env 值 必须 == mc-test 插件 McdrPlugin/pch_system/config.json 加载的值插件 HTTP 上报被 backend 拒(401)
POSTGRES_PASSWORD / POSTGRES_USER / POSTGRES_DBworktree 用新卷 <feat>_pgdata(空),.env 的值就是初始化值,自洽即可若误指主仓 pchsystem_pgdata(跨 project/卷),密码不匹配连不上
JWT_SECRET每个 backend 独立即可token 不跨 backend 互通(登录态不共享,正常)
WEB_BASE_URL== 玩家访问的前端端口!!PCH login 回调跳错地址

新卷必跑迁移:策略 B 的新 <feat>_pgdata 是空的,起栈后必须 docker compose -p <feat> exec backend alembic upgrade head,否则表都不存在。不要尝试让 worktree backend 共享主仓 pchsystem_pgdata(违反 R-1 数据唯一拥有者、且跨 project 卷名对不上)。


8. 网络对齐

  • TestServer/docker-compose.yml 写死 pchsystem_default external:true → 主 mc-test 只能看到 pchsystem 项目里的 backend(http://pchsystem-backend-1:8000)。
  • worktree 策略 B 的栈在 <feat>_default 网络,backend 容器名 <feat>-backend-1,主 mc-test 看不到。
  • 要在 worktree 测 mc-test:需 worktree 自己的 mc-test compose,把 networks.pchsystem_default 改成 <feat>_default(且不再是 external),backend 引用改 <feat>-backend-1:8000。成本高,多数情况用策略 D(同步主仓 + 复用主 mc-test)更划算。

9. 起栈后验证

# 1. 挂载源必须指向 worktree,不是主仓
docker inspect <容器名> --format '{{range .Mounts}}{{.Source}}{{"\n"}}{{end}}'
#    期望看到 .claude/worktrees/<name>/Backend/app ...;若出现主仓 /home/yushen/opt/PCHSystem/Backend/app → override 没生效

# 2. 健康检查(端口按实际栈:主栈 8000 / worktree 8002)
curl -sS http://localhost:8000/healthz        # → {"status":"ok"}

# 3. 迁移状态(策略 B 新卷尤其要看)
docker compose -p <feat> exec backend alembic current

10. 红线·陷阱(硬约束)

每条都附 why——理解了就不会误踩。

  1. EnterWorktree 默认 base 是旧 phase0 → 进 worktree 先 git reset --hard main + 软链 node_modules(§4)。why:该仓 default 分支在 origin 上远早于前端/后端业务代码,不 reset 会缺前端。
  2. docker cp 写容器 bind-mount 路径 = 反写主仓宿主文件(bind mount 双向)→ 注入测试文件时 cp 到非挂载路径(如 /app/tests、/tmp)或起 docker run --rm -v <worktree>:/app 临时容器;事后 git -C 主仓 status 排查,污染立即 git checkout HEAD -- <file>。why:曾 docker cp ...:/app/app/api/sheets.py 反改主仓源码污染主线。
  3. !!MCDR plugin reload 只读主仓路径 → worktree 改动先同步主仓再 reload(策略 D)。why:容器挂载的是主仓 McdrPlugin/pch_system。
  4. docker compose --remove-orphans 会删 mc-test → worktree 操作时慎用。why:mc-test 定义在 TestServer/ 另一份 compose,根 compose 把它当 orphan。
  5. worktree 会话只起 worktree 栈(-p <feat>),勿启动/触碰主仓 pchsystem-*(让主仓栈保持 stopped 或原状)。why:混起会让主仓读到未完成代码、破坏主仓测试数据。
  6. docker-compose.override.yml 已被 .gitignore(含机器绝对路径)→ per-machine 逃生口,测完删,勿提交。
  7. .claude/worktrees/ 现已加入 .gitignore → 残留 worktree 目录曾污染主线 git status;孤立目录(不在 git worktree list)应清理。
  8. 勿以追踪方式改 vite.config.ts 端口 → 历史上 worktree 改 8002 被提交进主线造成污染;用 CLI --port 或临时改 + git checkout HEAD -- 还原。
  9. GitHub push/pull 走宿主机代理(VMware NAT 直连不稳),用户偏好自己手动执行 → 不自动跑 git 网络命令,把命令交给用户。

11. 与根 CLAUDE.md 的关系

本 skill 是根规范的操作细化,不覆写根规范:

  • R-1(数据唯一拥有者):worktree 用独立 <feat>_pgdata 卷,不碰主仓 pchsystem_pgdata 业务库。
  • R-11(密钥经 .env 注入,不进库):所有 token/密码来自根 .env,worktree 经软链复用或自洽的新值,绝不硬编码。
  • §0 S-2(中文输出)、§1(skill 目录 kebab-case):本 skill 遵守。
  • 经验来源:项目 auto-memory enter-worktree-base-old-phase0 / worktree-stack-switch-via-compose-override / worktree-stack-built-from-worktree / worktree-no-main-stack / mcdr-worktree-hotreload-mounts-main / docker-cp-bind-mount-writes-main / github-push-via-host-proxy。

本 skill 与 service-claude-md 同级,均为 PCHSystem 项目级 skill(.claude/skills/ 自动发现)。栈配置本身以 docker-compose.yml / TestServer/docker-compose.yml / .env.example 为准,本 skill 只指导如何在 worktree 中迁移与对齐,不改栈。

리뷰

아직 리뷰가 없습니다. 사용해 본 소감을 남겨 주세요.

댓글

로그인 없이 쓸 수 있습니다. 사용 후기, 질문, 작동하지 않은 환경 등을 편하게 남겨 주세요.

아직 댓글이 없습니다. 첫 댓글을 남겨 보세요.

보내면 바로 공개됩니다. 이메일 주소나 전화번호 같은 개인 정보는 쓰지 마세요. URL은 2개까지입니다.

0 / 1,000자

이 양식은 reCAPTCHA로 보호되며 Google 개인정보처리방침 및 서비스 약관이 적용됩니다.

같은 저장소의 스킬

Redesign GitHub README homepages or create project-native pure SVG, hybrid SVG-composed PNG/WebP, and opt-in animated GIF assets. Use when a user asks to beautify, redesign, rebrand, visually upgrade, simplify, or audit a GitHub README; create only a hero, section headers, diagrams, badges, motion graphics, showcase modules, or other README assets; or turn a repository homepage into a cohesive visual story. If whole-README work versus asset-only work is unclear, ask which scope the user wants. For hero-like assets where pure SVG and generated raster material are both viable, explain the tradeoffs and confirm the implementation before creating the asset.

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

YuShenLiu06/PCHSystem92026년 10월 18일 업데이트

HTCMC PCHSystem 专用 skill——为各子服务目录生成与更新「分布式 CLAUDE.md」(提炼该服务的雷点、关键要素、文档索引)。当新建子服务、子服务架构发生变更、或需要补齐/更新某个服务的 CLAUDE.md 时使用。传入服务名(mcdr-plugin / user-service / project-service / scoring-service / title-service / wiki-service / alert-service / frontend),本 skill 自动读取对应架构文档,按统一模板生成或增量更新该服务目录下的 CLAUDE.md。在 PCHSystem 项目内,只要用户提到「子服务 CLAUDE.md」「为某服务生成/更新 CLAUDE.md」「补齐服务雷点」「服务记忆文件」,或正在新增/改动某个服务目录,就应使用本 skill——禁止手写子服务 CLAUDE.md。

한국어 요약은 준비 중입니다. 원문 설명을 표시하고 있습니다.

YuShenLiu06/PCHSystem92026년 10월 18일 업데이트

YuShenLiu06의 스킬 모두 보기

이 스킬의 문제 신고