文章讨论为每个编码 Agent 分配独立 Git worktree 后,多个变更并行运行给本地服务、端口、数据库和运行环境带来的隔离难题。它指出代码目录隔离并不等于运行时隔离,是多 Agent 工作流落地时容易忽略的工程约束。
我们很高兴你的到来。每周一至周五,你都将收到 TNS 的优质内容,及时掌握最新动态,让自己始终保持最佳状态。
请查看收件箱中的确认邮件,你可以在邮件中调整偏好设置,还可以加入其他群组。
在你喜爱的社交媒体平台上关注 TNS。
在 LinkedIn 上关注 TNS。
等待第一封 TNS newsletter 期间,不妨先看看最新的精选文章和热门内容。
一名开发者同时监督四个 coding Agent,也就意味着有四项变更正在并行推进,每项变更都有各自的 git worktree。如今,这已经不是什么少见的配置:Anthropic 的文档现在将“每个 session 使用一个 worktree”视为并行运行 Agent 的默认方式。两年前还属于专家级的工作流,如今已经成了官方推荐的起点。
branch 本身并不新鲜。20 年前,Git 就已经让创建 branch 变得成本极低,使开发者能够隔离变更,同时处理多项工作。但在实践中,开发者通常只是在不同 branch 之间切换,然后每次交付一项变更。这使得代码层以下的一切仍然保持单一:一条持续集成(CI)队列、一个 staging 环境,以及一个供所有人测试的数据库。争用这些共享资源的变更数量受团队人数限制,而在 Agent 出现之前,只有规模较大的团队才会触及这一上限。
“Coding Agent 打破了这一上限。branch 不能再止步于代码层。”
Coding Agent 打破了这一上限。现在,这四个 branch 不再是一个开发者轮流切换处理的工作内容,而是四项正在并行推进、等待 merge 的活跃变更。由此产生的断层已经难以维系:代码层可以免费创建 branch,但代码层以下却没有相应能力。每项变更都需要贯穿整个技术栈真实存在,不只是某个目录中的 diff,而是一个能够运行、能够测试的系统版本。branch 不能再止步于代码层。
代码可以在几毫秒内完成 branching。只需付出一次 checkout 的成本,worktree 就能为每个 Agent 提供一份私有的 repository 副本,10 个 Agent 可以并肩工作,彼此看不到对方的修改。
随之而来的产出会涌向下游。Faros AI 对超过 10,000 名开发者的 telemetry 数据显示,高度采用 AI 的团队 merge 的 pull request 数量增加了 98%,与此同时,review 时间也增长了 91%。代码生成下游的任何环节,都没有为这样的到达速率做好准备。
接下来,每项变更都需要真正运行起来。然而,团队通常只有一个 staging cluster、一个预填充数据的数据库、一条 message queue,以及一套依赖服务。每个抵达这一层的 branch 都会停止并行。四个 Agent 一个下午就能产出四项候选变更,而这四项变更全都要在同一个共享环境后排队,等待确认自己能否正常工作。
这条队列的代价比看上去更高,因为 Agent 并不擅长等待。被环境阻塞的 Agent,要么空闲下来,继续持有一份已经过时的系统视图;要么硬着头皮使用 mock 做验证。与此同时,负责监督它的开发者也会切换到其他上下文。等共享环境终于空出来时,前面那些成本低廉的工作还得部分重做。
瓶颈不在代码生成,也不只是 review capacity,而是变更接触到的第一个共享资源。因为一个无法运行的 branch,也就无法获得信任。
“瓶颈不在代码生成,也不只是 review capacity,而是变更接触到的第一个共享资源。”

摆脱困境的方法,是不再把 branching 仅仅看作 Git 所做的事情,而要把它视为每一层都应该具备的能力。“基于 branch 的开发”定义了这一模式:技术栈的每一层都提供一种低成本、即时且可随时丢弃的 branch 原语,让一项变更能够端到端存在,同时又不必复制任何没有被它修改的内容。
其机制正是 Git 奠定、所有人沿用了 20 年的那一套:branch 之所以成本低,是因为它共享所有未改变的内容,只携带增量。此后的技术栈一直在逐层重新学习这一理念——默认共享,只隔离发生变化的部分。
为这种模式命名很重要,因为每一层都是独立发现它的,又给它起了不同的名字。worktree、pipeline caching、preview deploy、database branching 和 environment sandboxing,听起来像五种彼此无关的功能。实际上,它们只是同一个理念在五个不同层级上的应用。意识到这一点,也会改变你对那些尚不具备此能力的层级提出的要求。
CI 在十年前就吸收了这一经验。每个 branch 都能在共享的 runner pool 上拥有自己的 pipeline run,build cache 则承担 copy-on-write 的工作,复用未改变的 artifact。没有人会为每个 branch 单独配置一套 build system,也不再有人需要排在唯一的全局 build 后面等待。
前端随后也采用了同样的模式。在 Vercel 上,每次向非 production branch push,默认都会得到自己的 preview deployment;Netlify 的工作方式同样如此。branch 本身就是一次不可变的 build,再加上共享托管基础设施上的 routing。reviewer 不再追问某项变更能否在某个人的笔记本电脑上运行,因为这项变更已经在某个地方真实运行起来了。
这两种情况具有相同的结构:昂贵的基础设施由大家共享,branch 本身很轻量,创建成本低到没人需要特意考虑它。这正是某一层具备 branch 原语之后应有的体验。
这些原语出现后,也改变了团队的行为。per-branch CI 让每次 push 都运行完整 test suite 成为常态,而不再是每晚运行一次。preview deploy 让 product manager 在 merge 前亲自点击体验变更成为常态。低成本的 branch 不只是消除了一条队列,还提高了 merge 前检查工作的标准。
数据库承载着状态,因此传统观点认为,branching 在数据库上永远行不通。但 Neon、PlanetScale 和 Xata 还是实现了它。如今,Neon 的文档已经明确给出了这种类比:像为代码创建 branch 一样,为数据创建 branch。
database branch 是建立在共享 storage page 之上的 copy-on-write 视图。无论数据库规模多大,都可以在几秒内完成创建。schema migration 和高风险的数据变更可以在具有 production 数据形态的数据集上完成验证,而不是依赖陈旧的 seed script;工作 merge 后,这个 branch 随即消失。
“如果状态最多的那一层都能在几秒内分配 branch,那么 stateless 从来就不是真正的必要条件。”
数据层之所以对这个故事至关重要,是因为它消除了最有力的借口。如果状态最多的那一层都能在几秒内分配 branch,那么 stateless 从来就不是真正的必要条件。任何仍然没有 branch 能力的层级,都只是主动选择了不这么做。
microservices runtime 最晚才接受这一模式,因为它看上去完全不像一棵文件树。它包含实时流量、service graph 和数十个不断变化的依赖。最朴素的 branch 实现方式——完整复制整个环境——成本高得惊人,以至于大多数团队得出结论:branching 并不适用于这里。
但 copy-on-write 的思路依然有效。运行一个从 main 持续部署的共享、稳定系统版本。对于每项变更,只将其涉及的服务部署为轻量级 ephemeral environment;然后,让每个测试请求经过发生变更的服务,其余部分则回落到共享的稳定版本。environment branch 的成本大致只相当于发生变更的那些服务,因此 Agent 产出的每项变更都可以拥有自己的环境。
routing 是其中听起来很新奇、实际却并不陌生的部分。带有 label 的请求会在每一跳被引导至发生变更的服务版本,该 label 会沿着调用链持续传播,就像 trace context 已经在大多数完成 instrumentation 的系统中流动一样。共享的稳定环境扮演 main 的角色,发生变更的服务就是增量,而 label 则是一个指针,负责为每个请求组装出一致的系统视图。
这并不是一种假想架构。Uber 构建了 SLATE,为每位开发者提供一个通过 routing 接入共享 production-grade 依赖的 ephemeral environment,因为 staging 环境的争用已经无法跟上其开发者人数的增长。

把这些层级组合起来,就会出现一种全新的开发模型。Agent 接到一项任务后,这项变更从一开始就会拥有一个 worktree、一次 pipeline run、一个 preview、一个 data branch 和一个可运行环境。验证不再是迫使所有上游工作串行化的稀缺资源。
一些团队已经开始组合这些下层能力。拥有 250 多名工程师的加密货币交易所 Bitso,会为每项变更配套创建 environment branch 和 database branch,让 runtime 增量与数据增量一起流转,从而使共享 staging 环境退出关键路径。
所谓 Agent-native software development lifecycle,指的就应该是这种端到端的 branch。它不是简单地把 Agent 接入昨天的 pipeline,而是构建这样一套技术栈:无论变更由人还是机器产生,都能在每一层存在,持续到验证结束,然后消失。
随着 Agent 数量增加,收益还会不断叠加。当每一层的 branch 原语都是建立在共享资源之上的增量时,验证并发度将随 cluster capacity 扩展,而不是受预算限制;团队每天能够证明正确的变更数量,也会随其生成变更的能力一起增长。正是这一比例决定了 Agent 的采用最终会转化为已交付的软件,还是一条更长的队列。
执行这项审计的成本很低。选择一项变更,从 worktree 一路追踪到验证完成,记录它最先在哪一层开始等待共享资源。你的技术栈就是从那里停止 branching 的。
对大多数团队而言,答案是 runtime。如果你的情况也是如此,Signadot 是一个务实的起点。