feat(git): 完善 Worktree 生命周期与发布约定

This commit is contained in:
zhiye.sun
2026-08-31 17:34:27 +08:00
parent e82eb4e857
commit 9c1fb956e4
13 changed files with 249 additions and 25 deletions
@@ -0,0 +1,103 @@
# Worktree 生命周期
## 适用范围
本规则管理预集成独立 worktree 从创建到安全移除的完整生命周期。主工作区不干净、用户要求不影响当前 checkout、当前分支被 IDE/服务/测试占用、需要复用旧预集成分支或预计发生冲突时,必须使用独立 worktree。
Worktree 只隔离工作目录;所有 worktree 共享仓库对象和本地分支引用。同一个本地分支不能同时被两个 worktree 签出。
## 生命周期状态
- `planned`:已确认仓库、分支、基准和绝对路径,尚未创建。
- `active`:worktree 已创建,开发、合并或验证正在进行。
- `delivery-ready`:差异和验证完成,等待本地交付确认或发布。
- `cleanup-ready`:本地交付已确认,或用户要求的发布已经完成,可以清理。
- `cleanup-blocked`:存在未提交内容、进行中的 Git 操作、引用风险或需要保留的现场。
- `removed`:额外 worktree 已移除,分支和提交仍存在。
## 创建和占用记录
创建前确认目标绝对路径不存在、目标分支未被其他 worktree 占用、基准引用可解析并记录完整哈希。分支名可能包含中文时始终加引号,不使用 `$HOME`、`$home` 或 `$CODEX_HOME` 作为任务变量。
创建后记录并报告:
- 主仓库绝对路径;
- worktree 绝对路径;
- worktree 当前分支和 HEAD;
- 主工作区当前分支、HEAD 和未提交状态;
- 该分支已被额外 worktree 占用,主工作区不能同时签出;
- 后续操作目录和生命周期结束后的清理义务。
## 新建或复用预集成
旧预集成已经合入目标分支时,默认新建增量预集成分支,使交付历史易于审计。只有用户明确选择复用,并且旧预集成可解析、上次源分支基线已包含、旧预集成与目标分支关系已查清、最终 `<target>...HEAD` 可收敛为本次需求文件时,才能继续复用。
历史中存在直接合入错误版本分支、无关需求或异常大量文件时,不得只因引用可解析就复用。复用时推荐先合入源分支最新增量,再合入最新目标分支;项目规范规定其他拓扑时以项目规范为准。
## 交付范围和结束条件
Merge 输出出现大量目标分支文件不等于 MR/PR 包含这些文件。必须检查:
```text
git diff --check "<target>...HEAD"
git diff --stat "<target>...HEAD"
git diff --name-status "<target>...HEAD"
git log --oneline "<target>..HEAD"
git log --first-parent --oneline -20
```
只有同时满足以下条件,生命周期才可进入 `cleanup-ready`:
- 本次开发或预集成已经完成;
- 用户要求的验证已经完成;
- 用户确认仅本地交付,或用户要求的发布已经完成;
- worktree 没有未提交或未跟踪文件;
- 没有进行中的 merge、rebase、cherry-pick 或 revert;
- 当前 HEAD 已被预期本地分支引用;
- 用户不再要求保留现场。
用户要求保留现场时标记为 `delivery-ready`,明确说明生命周期尚未结束以及分支仍被该 worktree 占用。
## 清理门禁
移除前展示主仓库和 worktree 的准确绝对路径、分支、HEAD、状态、分支引用验证和唯一清理命令。检查至少包括:
```text
git -C "<worktree>" status --porcelain
git -C "<worktree>" branch --show-current
git -C "<worktree>" rev-parse HEAD
git -C "<worktree>" rev-parse -q --verify MERGE_HEAD
git -C "<main-repository>" worktree list --porcelain
git -C "<main-repository>" branch --contains "<head-sha>"
```
`MERGE_HEAD` 不存在是预期结果。还要依据 Git 状态确认不存在 rebase、cherry-pick 或 revert;任一操作未结束时标记为 `cleanup-blocked`。
用户确认准确清理信息后执行:
```text
git -C "<main-repository>" worktree remove "<absolute-worktree-path>"
```
不得直接删除目录,不得默认使用 `--force`,不得为解除占用而删除或重置分支,也不得批量清理其他 worktree。
## 清理后验证
```text
Test-Path -LiteralPath "<absolute-worktree-path>"
git -C "<main-repository>" rev-parse --verify "<branch>"
git -C "<main-repository>" worktree list --porcelain
git -C "<main-repository>" status --short --branch
```
只有目录不存在、worktree 列表已释放占用、分支和提交仍存在、主工作区原有状态未变化时,才能标记为 `removed`。
## 分支已被占用
出现以下错误表示目标分支仍由额外 worktree 签出:
```text
fatal: '<branch>' is already used by worktree at '<path>'
```
继续在错误给出的 worktree 中操作,或者在其生命周期结束并通过清理门禁后移除。不得强制 checkout、直接删除目录或删除分支绕过 Git 的占用保护。