| name | git-worktrees |
| description | Use whenever a code task (new feature, bug fix, refactor, experiment) begins, or when invoked via the /git-worktrees command — by default develop in an isolated git worktree (fix/… for fixes, feature/… for features), then merge to test/main and auto-clean on completion. 涉及任何代码变动时默认在隔离 git worktree 中开发(fix/ 或 feature/ 分支),完成后合并到 test/main 并自动清理。 |
| type | procedure |
| category | coding |
| platform | shared |
── 质量追踪 ──
{
"status": "production",
"rating": "★★★★★",
"last_used": "2026-07-16",
"total_uses": 1,
"trace": [
{"date": "2026-07-16", "usage": "收录 agent-skills", "result": "✅ 已投产使用"}
]
}
Git Worktrees 隔离工作区
概述
在开始任何代码变动之前,确保工作在一个隔离的 git worktree 中,避免污染当前分支。
默认行为: 每当任务涉及任何代码变动(新功能、bug 修复、重构、实验性改动)时,默认创建隔离 worktree,无需询问用户是否使用。
分支命名规则:
- bug 修复 →
fix/<简短描述>(例如:fix/login-crash)
- 新功能 →
feature/<简短描述>(例如:feature/add-login)
- 无法判断时,简要询问用户这是修复还是新功能,再据此命名。
核心原则: 先检测现有隔离状态,再创建,不重复创建。
Step 0:检测是否已在隔离工作区
在做任何操作之前,先检测当前是否已处于 worktree 中。
GIT_DIR=$(cd "$(git rev-parse --git-dir)" 2>/dev/null && pwd -P)
GIT_COMMON=$(cd "$(git rev-parse --git-common-dir)" 2>/dev/null && pwd -P)
BRANCH=$(git branch --show-current)
Submodule 保护: GIT_DIR != GIT_COMMON 在 git submodule 里也成立。先排除:
git rev-parse --show-superproject-working-tree 2>/dev/null
判断结果:
GIT_DIR != GIT_COMMON(且不在 submodule)→ 已在 linked worktree 中,直接跳到 Step 3,不重复创建。
报告:已在隔离工作区 <path>,分支:<name>
GIT_DIR == GIT_COMMON(或在 submodule)→ 在主仓库检出目录,继续 Step 1。
Step 1:确定分支类型与名称(默认创建)
当检测到当前处于主仓库,且任务涉及任何代码变动时,默认创建隔离 worktree,不再询问"是否使用 worktree"。
判断变更类型并命名分支:
- 任务是修复缺陷 / 报错 / 异常行为 →
fix/<简短描述>
- 任务是新增能力 / 新特性 →
feature/<简短描述>
- 若从任务描述无法判断是修复还是新功能 → 简要询问用户类型后命名。
确定分支名后直接继续 Step 2。
Step 2:创建隔离工作区
目录选择优先级
按以下顺序确定 worktree 存放位置(用户明确指定的优先级最高):
- 用户明确指定的路径 → 直接使用
- 项目已存在的 worktree 目录:
ls -d .worktrees 2>/dev/null
ls -d worktrees 2>/dev/null
两者都存在时用 .worktrees/
- 默认值 → 项目根目录下的
.worktrees/
安全验证(项目本地目录必须执行)
创建前必须确认目录已被 git 忽略:
git check-ignore -q .worktrees 2>/dev/null || echo "未被忽略"
若未被忽略: 先将目录名加入 .gitignore 并提交,再继续。
echo ".worktrees/" >> .gitignore
git add .gitignore
git commit -m "chore: ignore .worktrees directory"
创建 Worktree
BRANCH_NAME="<fix|feature>/<简短描述>"
WORKTREE_PATH=".worktrees/$BRANCH_NAME"
git worktree add "$WORKTREE_PATH" -b "$BRANCH_NAME"
cd "$WORKTREE_PATH"
权限失败处理: 若 git worktree add 因沙箱权限失败,告知用户并改为在当前目录原地工作,然后继续 Step 3。
Step 3:项目环境初始化
进入 worktree 后自动检测并安装依赖:
[ -f package.json ] && npm install
[ -f go.mod ] && go mod download
[ -f requirements.txt ] && pip install -r requirements.txt
[ -f pyproject.toml ] && poetry install
[ -f Cargo.toml ] && cargo build
Step 4:验证基线状态
运行项目测试,确保工作区从干净状态开始:
npm test
go test ./...
pytest
cargo test
测试失败时: 报告失败详情,询问是继续还是先排查问题。
测试通过时: 报告就绪状态:
工作区已就绪:<完整路径>
分支:<branch-name>
测试:全部通过(<N> 个测试)
可以开始实现 <功能描述>
Step 5:开发完成后询问合并目标
开发完成(代码改动已提交到 worktree 分支)后,主动询问用户合并目标:
开发已完成,分支 <branch-name> 是否需要合并?合并到哪个分支?
- test → 合并到测试分支验证
- main → 合并到主分支
- 暂不合并 → 保留 worktree,后续再处理
用户选择:
- 合并到 test 或 main → 继续 Step 6 执行合并与清理。
- 暂不合并 → 保留 worktree,报告分支与路径,结束。
合并前确保 worktree 内所有改动已提交:
git -C "$WORKTREE_PATH" status --porcelain
Step 6:合并并清理(区分 test 与 main)
关键前提:test 是易变的共享集成分支。 本仓库规范明说 test 可随时用 main 重置,
任何协作者都可能对它 force-reset / 重置为 main + 自己的 feature。这意味着你 push 到
origin/test 的提交随时可能被他人的重置抹掉。因此合并到 test 与合并到 main
的清理策略不同,见下文。
确认合并目标分支(test 或 main)后执行:
TARGET="<test|main>"
BRANCH_NAME="<fix|feature>/..."
cd <项目根目录>
git fetch origin
git checkout "$TARGET"
git merge --ff-only "origin/$TARGET" 2>/dev/null || git reset --hard "origin/$TARGET"
git merge --no-ff "$BRANCH_NAME"
git push
合并冲突处理: 若 git merge 出现冲突,停止自动清理,报告冲突文件并请用户决定如何解决。冲突解决并提交后再继续清理。
6a. 合并到 test(共享易变分支)—— 只清理 worktree,保留 feature 分支
test 可能在你 push 后被他人重置,因此:
- 只删除 worktree 目录,保留 feature 分支,直到该改动经由「feature 分支 → main 的 MR」
真正落地
main 后,才允许删除 feature 分支(见 6b)。这样即便 origin/test 被重置抹掉,
你的代码仍完整保留在 feature 分支上,可随时重新合并。
git worktree remove .worktrees/"$BRANCH_NAME"
push 后必须做「落地校验」——确认自己的提交仍在 origin/test 上:
FEATURE_SHA=$(git rev-parse "$BRANCH_NAME")
git fetch origin test
if git merge-base --is-ancestor "$FEATURE_SHA" origin/test; then
echo "OK: 提交仍在 origin/test 上"
else
echo "警告: 提交已被他人重置抹掉,需要重新合并并 push"
fi
若已被他人重置抹掉(--is-ancestor 返回非 0),重新把 feature 合并到当前 origin/test 再推:
git checkout test
git fetch origin test
git reset --hard origin/test
git merge --no-ff "$BRANCH_NAME"
git push
部署后必须做运行时功能校验,而不是只看发布 gate 的 commit SHA 匹配:
名义 commit SHA 匹配 ≠ 你的代码真的在运行。发布 gate 只校验名义 SHA,无法发现
「origin/test 被重置后流水线基于旧代码构建」这种情况。务必实际打一次新端点 /
触发一次新功能确认改动真的生效(例如 curl 新增的接口应返回 200 而非 404)。
这是本次踩坑的关键:曾经 SHA 显示匹配、却因 test 被重置导致部署的二进制里没有改动、
新端点 404。
6b. 合并到 main(正式落地)—— 按原样清理 worktree 与分支
main 不会被随意重置,合并到 main 后可安全清理:
git worktree remove .worktrees/"$BRANCH_NAME"
git branch -d "$BRANCH_NAME"
报告完成状态:
已合并 <branch-name> → <target>
已清理 worktree:.worktrees/<branch-name>
合并到 test:保留分支 <branch-name>(待 MR 落地 main 后再删)
合并到 main:已删除分支 <branch-name>
快速参考
| 场景 | 操作 |
|---|
| 任何代码变动 | 默认创建 worktree(不再询问是否使用) |
| 任务是 bug 修复 | 分支命名 fix/<描述> |
| 任务是新功能 | 分支命名 feature/<描述> |
| 无法判断修复/新功能 | 简要询问类型后命名 |
| 已在 linked worktree 中 | 跳过创建(Step 0 检测到) |
| 在 submodule 中 | 按普通仓库处理(Step 0 保护) |
.worktrees/ 已存在 | 复用(验证已被 ignore) |
worktrees/ 已存在 | 复用(验证已被 ignore) |
| 两者都存在 | 用 .worktrees/ |
| 都不存在 | 默认创建 .worktrees/ |
| 目录未被 ignore | 先加入 .gitignore 并提交 |
| 创建权限失败(沙箱) | 告知用户,在当前目录原地工作 |
| 无 package.json / go.mod 等 | 跳过依赖安装 |
| 基线测试失败 | 报告失败,询问是否继续 |
| 开发完成 | 询问合并到 test / main / 暂不合并 |
| push 前 | 先 git fetch 并基于最新 origin/<target> 合并 |
| 合并到 test(共享易变分支) | 只删 worktree,保留 feature 分支;fetch 做落地校验 |
| test 被他人重置抹掉了我的提交 | reset --hard origin/test + 重新 merge + push,直到校验通过 |
| 部署后验证 | 打新端点/触发新功能做运行时校验,不能只看 SHA 匹配 |
| 合并到 main(正式落地) | 清理 worktree 与分支 |
| test 改动最终落地 main 后 | 才删除当初保留的 feature 分支 |
| 合并冲突 | 停止清理,报告冲突请用户处理 |
Worktree 生命周期管理
查看所有 worktree
git worktree list
手动清理(暂不合并或被丢弃时)
cd <项目根目录>
git worktree remove .worktrees/<branch-name>
git branch -d <branch-name>
强制删除(未合并时)
git worktree remove --force .worktrees/<branch-name>
git branch -D <branch-name>
常见错误
在已有 worktree 中再次创建
- 问题: 嵌套创建 worktree,造成混乱
- 修复: 始终先运行 Step 0 检测
跳过 ignore 验证
- 问题: worktree 内容被意外 git 追踪,污染仓库状态
- 修复: 创建前必须执行
git check-ignore
分支命名不符合规则
- 问题: 修复用了 feature/、新功能用了 fix/,破坏分支约定
- 修复: 严格按 bug 修复 →
fix/、新功能 → feature/ 命名
基线测试失败时直接继续
- 问题: 无法区分新引入的 bug 与已存在的问题
- 修复: 测试失败时必须报告并征得用户同意后再继续
合并冲突时强行清理
- 问题: 改动丢失,无法回溯
- 修复: 出现冲突时停止清理,交由用户处理
合并到共享 test 后立即删除 feature 分支
- 问题:
test 被他人 force-reset 抹掉你的提交后,本地分支也已删除 → 改动彻底丢失,
且线上 test / 部署产物里都不含你的改动
- 修复: 合并到
test 只删 worktree、保留 feature 分支;待改动经 MR 落地 main 后再删
只凭 commit SHA 匹配判定部署成功
- 问题: 发布 gate 显示 SHA 匹配,但
origin/test 已被重置、流水线基于旧代码构建,
实际部署的二进制里没有你的改动,新端点 404 却误以为「部署成功」
- 修复: 部署后实际打一次新端点 / 触发新功能做运行时校验,名义 SHA 匹配不等于代码在运行
禁止行为
- 已处于 linked worktree 时,禁止再次创建
- 项目本地目录未经 ignore 验证,禁止直接创建
- 禁止违反分支命名规则(修复必须
fix/、新功能必须 feature/)
- 禁止未经用户确认就自行决定合并目标分支
- 合并出现冲突时,禁止静默清理或丢弃改动
- 基线测试失败时,禁止静默继续
- 禁止在合并到易变的共享
test 后立即删除 feature 分支(须待改动落地 main 后再删)
- 禁止仅凭发布 gate 的 commit SHA 匹配就认定「部署成功 / 改动已生效」
必须执行
- 每次代码变动任务开始前先运行 Step 0 检测
- 默认创建 worktree(任何代码变动),无需询问是否使用
- 按
fix/ / feature/ 规则命名分支
- 项目本地目录创建前验证 .gitignore
- 自动检测并安装项目依赖
- 验证测试基线
- 开发完成后询问合并目标(test / main / 暂不合并)
- push 前先
git fetch 并基于最新 origin/<target> 合并
- 合并到共享
test 后 fetch 校验自己的提交仍在 origin/test 上;被抹掉则重新 merge+push
- 合并到
test 只清理 worktree、保留 feature 分支;合并到 main 才清理 worktree 与分支
- 部署后做运行时功能校验(实际打新端点/触发新功能),不能只看 SHA 匹配