什么是 Git Worktree
Git Worktree 是 Git 2.5 版本引入的一项强大功能,它允许用户在同一个仓库中同时检出多个工作目录。每个 worktree 拥有独立的工作区和暂存区,但共享同一个 .git 对象数据库。这意味着你可以在不切换分支的情况下,同时在多个分支上进行开发工作。
传统的 Git 工作流要求开发者在单一工作目录中通过 git checkout 或 git switch 切换分支。这种方式存在明显的局限性:切换分支会导致当前未提交的更改丢失或产生冲突,编辑器中打开的文件需要重新加载,构建缓存可能失效。Worktree 通过创建完全独立的目录结构来解决这些问题。
PinableAgents 充分利用了这一机制,将每个智能体任务隔离在独立的 worktree 中执行。这样做的核心优势在于:即使智能体的代码生成出现错误,也不会影响主工作目录中的任何文件。
为什么需要隔离机制
在 AI 辅助编程的场景中,隔离机制的重要性远超传统开发。智能体生成的代码具有不确定性,一次看似合理的重构可能引入难以察觉的 bug,一次数据库迁移脚本可能破坏现有数据结构。如果这些操作直接在主工作目录中执行,回退代价将非常高昂。
PinableAgents 的隔离策略遵循三个核心原则:
- 零污染原则:任何智能体的操作都不会修改主工作目录中的任何文件,直到用户明确批准合并。
- 可审查原则:每个 worktree 中的变更都以标准的 Git diff 形式呈现,用户可以逐行审查每个修改。
- 可回滚原则:任何阶段都可以一键丢弃 worktree,恢复到任务开始前的状态,没有任何副作用。
将智能体视为一个不可完全信任的协作者。它可能写出优秀的代码,也可能犯错。Worktree 隔离确保你始终保有最终决定权。
Worktree 生命周期
PinableAgents 中的 worktree 遵循严格的四阶段生命周期管理:创建 → 执行 → 验证 → 合并/丢弃。每个阶段都有明确的入口条件和出口条件。
阶段一:创建(Create)
当用户触发一个工作流任务时,编排引擎首先在配置的基础路径下创建一个新的 worktree。分支命名遵循 pinable/<workflow>/<timestamp> 的格式,确保唯一性和可追溯性。
# 内部执行的创建流程
git worktree add ../worktrees/pinable-do-20260225-143022 -b pinable/do/20260225-143022
cd ../worktrees/pinable-do-20260225-143022
阶段二:执行(Execute)
智能体在 worktree 目录中执行所有代码生成和修改操作。此阶段中,智能体可以自由地创建文件、修改代码、运行测试,所有变更都被限制在这个隔离的目录中。编排引擎会实时监控文件变更,并记录到执行日志中。
阶段三:验证(Validate)
执行完成后,系统自动运行一系列验证检查。这些检查包括:语法检查(linting)、单元测试、类型检查以及用户自定义的验证脚本。只有当所有检查通过时,才会进入下一阶段。
阶段四:合并或丢弃(Merge / Discard)
验证通过后,用户可以选择将变更合并回主分支或丢弃整个 worktree。合并操作使用 git merge --no-ff 策略,确保保留完整的分支历史。丢弃操作则清理 worktree 目录和对应的分支引用。
失败时的自动回滚
当验证阶段检测到失败时,PinableAgents 提供两种回滚策略:
| 策略 | 行为 | 适用场景 |
|---|---|---|
auto-discard |
自动删除 worktree 和分支,不保留任何痕迹 | 快速迭代、试探性变更 |
preserve-on-fail |
保留 worktree 目录但标记为失败状态,供后续调查 | 复杂任务调试、问题分析 |
自动回滚的触发条件包括:测试失败、编译错误、智能体执行超时、以及用户定义的自定义失败条件。回滚操作是原子性的,要么完全回退要么完全不执行,不会留下半完成状态。
# 自动回滚时的内部操作
git worktree remove ../worktrees/pinable-do-20260225-143022 --force
git branch -D pinable/do/20260225-143022
# 日志记录:[ROLLBACK] Task do-20260225-143022 failed validation, worktree removed
配置选项详解
Worktree 隔离行为可以通过 config.json 中的 worktree 字段进行细粒度配置。
{
"worktree": {
"base_path": "../.pinable-worktrees",
"branch_prefix": "pinable",
"cleanup_policy": "auto-discard",
"max_parallel": 4,
"ttl_hours": 48,
"preserve_on_fail": true,
"merge_strategy": "no-ff",
"pre_merge_hooks": ["npm test", "npm run lint"],
"post_merge_hooks": ["npm run build"]
}
}
| 配置项 | 类型 | 默认值 | 说明 |
|---|---|---|---|
base_path |
string | ../.pinable-worktrees |
Worktree 目录的基础路径,相对于项目根目录 |
branch_prefix |
string | pinable |
自动创建的分支名前缀 |
cleanup_policy |
string | auto-discard |
清理策略:auto-discard 或 preserve-on-fail |
max_parallel |
number | 4 |
允许同时存在的最大 worktree 数量 |
ttl_hours |
number | 48 |
未操作的 worktree 自动清理时间(小时) |
merge_strategy |
string | no-ff |
合并策略:no-ff(保留分支历史)或 squash(压缩提交) |
并行 Worktree 与并发任务
PinableAgents 支持同时运行多个 worktree,每个处理独立的任务。这在团队协作或复杂项目中尤其有用。例如,一个智能体在 worktree A 中进行前端组件开发,同时另一个智能体在 worktree B 中编写对应的 API 端点。
并行 worktree 的管理涉及几个关键问题:
- 资源限制:通过
max_parallel配置项限制同时存在的 worktree 数量,防止磁盘空间耗尽。 - 锁管理:Git 内部使用锁文件防止对同一分支的并发操作。PinableAgents 在创建 worktree 前会检查锁状态,避免冲突。
- 合并顺序:当多个 worktree 同时完成时,系统按照任务优先级和完成时间排定合并顺序,避免合并冲突累积。
# 查看当前活跃的所有 worktree
pinable-agents worktree list
# 输出示例:
# ID 分支 状态 创建时间
# do-20260225-143022 pinable/do/20260225-143022 执行中 14:30
# omo-20260225-144510 pinable/omo/20260225-144510 验证中 14:45
# do-20260225-150000 pinable/do/20260225-150000 等待中 15:00
合并回主分支时的冲突解决
当 worktree 中的变更与主分支产生冲突时,PinableAgents 提供三种冲突解决策略:
- 交互式解决:系统暂停合并流程,在桌面端展示冲突文件的 diff 视图,由用户手动选择保留哪些变更。这是默认策略。
- 智能体辅助:将冲突信息交给专门的代码审查智能体,由其分析冲突上下文并提出解决方案。用户审核后确认。
- 自动放弃:当冲突超过设定阈值(默认 5 个文件)时,自动丢弃 worktree 并通知用户重新发起任务。
# 冲突解决的配置
{
"worktree": {
"conflict_strategy": "interactive",
"conflict_threshold": 5,
"allow_agent_resolve": true
}
}
实战示例:数据库 Schema 变更
假设你需要让智能体为一个 PostgreSQL 数据库添加新的用户权限表。这是一个高风险操作,因为错误的迁移脚本可能破坏现有数据。以下是使用 worktree 隔离的完整流程:
# 步骤 1:发起任务,系统自动创建 worktree
pinable-agents run do --task "创建 user_permissions 表并编写迁移脚本"
# 步骤 2:智能体在隔离的 worktree 中工作
# - 生成迁移文件 migrations/20260225_add_user_permissions.sql
# - 修改 models/user.go 添加权限关联
# - 编写对应的单元测试
# 步骤 3:自动验证阶段
# - 运行 go build 确认编译通过
# - 运行 go test ./... 确认测试通过
# - 执行 sqlc generate 确认 SQL 语法正确
# 步骤 4:用户审查
pinable-agents worktree diff do-20260225-143022
# 审查通过后合并
pinable-agents worktree merge do-20260225-143022
如果迁移脚本存在语法错误,验证阶段会自动捕获并触发回滚。整个过程中,你的主分支和数据库保持完全不变。
内部使用的 Git 命令
了解 PinableAgents 在底层使用的 Git 命令有助于排查问题和理解运行机制。以下是核心命令清单:
# 创建 worktree
git worktree add <path> -b <branch-name>
# 列出所有 worktree
git worktree list --porcelain
# 移除 worktree
git worktree remove <path> [--force]
# 修剪失效的 worktree 引用
git worktree prune
# 合并 worktree 分支
git merge --no-ff <branch-name> -m "Merge pinable task: <description>"
# 清理分支引用
git branch -d <branch-name>
如果你在使用过程中遇到 worktree 锁定问题,可以运行
git worktree prune清理失效引用,然后重试。
Worktree 管理最佳实践
经过大量实际项目验证,以下是 worktree 隔离的推荐实践:
- 设置合理的 TTL:对于快速迭代项目,建议将
ttl_hours设为 24 小时。对于大型项目,可以延长到 72 小时。过长的 TTL 会浪费磁盘空间。 - 使用 squash 合并策略:对于小型变更,使用
squash策略可以保持主分支提交历史的整洁。对于大型特性开发,使用no-ff保留完整的开发历程。 - 定期运行 prune:每周运行
pinable-agents worktree prune清理失效的 worktree 引用和孤立的分支。 - 监控磁盘空间:每个 worktree 是主仓库的完整工作副本。对于大型仓库,注意
max_parallel的设置,避免磁盘空间耗尽。 - 将 worktree 目录加入 .gitignore:在
.gitignore中添加.pinable-worktrees/,防止 worktree 目录被意外提交。 - 使用 pre_merge_hooks:配置合并前的验证钩子,确保合并到主分支的代码始终通过完整的质量检查。
遵循这些实践,你可以在享受 AI 辅助编程便利性的同时,确保代码库的安全性和完整性。Worktree 隔离是 PinableAgents 安全执行哲学的基石。