乐于分享
好东西不私藏

当多个AI Agent同时改你的代码,Git还顶得住吗

当多个AI Agent同时改你的代码,Git还顶得住吗

最近我让三个 Claude Code 同时干活。

一个修 bug,一个写新功能,一个帮我整理文档。

然后他们就打起来了。

不是真的打架,是 Git 层面的那种打架——文件冲突、脏工作区、commit 历史变成一坨巨大的屎。

我和你们一样,一开始觉得这根本不是问题。AI 写代码嘛,一回开一个终端,跑完一个 Agent 再跑下一个,排队来呗,能有什么冲突?

但你想过没有。

当你真的把 Agent 当成团队成员来用的时候,它就一定会产生团队协作才有的问题。而我们的版本控制工具,Git,在设计之初就没想过未来会有 AI agent 这种东西。

这篇文章,就是我在这个坑里滚了半个月之后,总结出来的一套东西。


Git 在 Agent 时代,破了四个大洞

第一个洞:Git 只记结果,不记想法

Git commit 能精确告诉你「改了什么」,但从来不告诉你「为什么这么改」。

人类工程师至少会在 commit message 里解释一下背景。但 agent 不会。它可能跨了十几个模块探索、试错、改写、回滚,最后留下一个看起来合理但你根本不知道它脑子里怎么想出来的 diff。

更恐怖的是 agent 的两个极端提交习惯:

要么一个 commit 塞几千行。 功能、测试、重构、格式化、文档全混在一起。reviewer 看一眼就想吐。

要么碎片化到令人发指。 fix typo、update file、try again……commit 历史变成了流水账,零语义价值。

这两种都不行。

第二个洞:脏工作区像垃圾场

Agent 的探索过程比人类快太多。

未提交的临时文件、格式化变更、测试 fixture、调试代码,和真实的业务修改全混在一起。

你可能遇到过这种场景:agent 跑了一个下午,你回来看工作区,一个 git status 刷出 40 个文件。

哪个是核心变更?哪个是副作用?哪个是 agent 瞎折腾出来的临时文件?

根本看不出来。

而且更致命的——多个 agent 如果在同一个工作目录里跑,它们会互相踩到对方的改动。你以为 agent A 在修 bug,agent B 在写测试,井水不犯河水。结果 agent A 顺手改了某个共享 util,agent B 也改了同一个文件,然后你的代码就变成了薛定谔的正确。

第三个洞:合并没有冲突 ≠ 能跑

Git 的 merge 是文本层面的——只要没有行级冲突,就认为合并成功。

但 agent 不这么思考。

一个 agent 改了某个接口的语义,另一个 agent 同时在旧语义下新增了调用点。两个 branch 各自通过测试,合并的时候 Git 说「没冲突,搞定」。

然后服务就挂了。

这就好比两个人同时改一个房子的水电图。一个人把水管改粗了,另一个人在旧尺寸上定做了接头。图纸上看不出来冲突,但装上去就漏水。

多 agent 并发的时候,这种情况比单 agent 开发高出一个数量级。

第四个洞:巨型提交让排查形同虚设

你的服务出了 bug。非常熟练地跑了一个 git bisect,二分搜索定位到了问题 commit。

然后你发现这个 commit 改了 40 个文件,1500 行 diff。

你 bisect 了个寂寞。

这就是 agent 一次性产出巨型 diff 的死循环:审查质量急剧下降 → 出问题很难回滚 → git revert 会撤掉太多无关改动 → git bisect 定位到了也排查不完。


五件事,让你的 Agent 协作不打架

我翻了 TRAE 技术团队写的一篇长文,然后结合自己这半个月的实际踩坑,总结出五件「只要你做了就立刻见效」的事。

第一件事:让你的 Agent 写「带身份证」的 commit

每个 commit 必须包含三个 trailer:

Agent-Task: PROJ-234 - Add refresh token support to auth serviceAgent-Model: claude-opus-4-6Agent-Decision: Used 7-day sliding window over fixed expiry for better UX

这三个字段的意思分别是:

  • Agent-Task:这段代码是哪个任务产生的,能追溯到原始 prompt
  • Agent-Model:用的哪个模型(不同模型的质量天差地别,出问题才知道哪个模型产的代码需要重点关注)
  • Agent-Decision:agent 自己做的关键设计决策及理由

这就是 Git 原生的 commit trailer 机制。

Signed-off-byCo-authored-by 你知道吧?跟那个一样。你可以直接 git log --format='%(trailers:key=Agent-Task,valueonly)' 查所有 agent 产生的提交。

说人话就是:给你的代码做个溯源二维码。 哪段代码、哪个 agent、用的什么 prompt、做了什么决策——一条链路清清楚楚。

第二件事:Checkpoint Commit——打存档

你玩过单机游戏吧?

打 BOSS 之前先存个档,这不用我教。

Agent 干长任务也是这个道理。在完成关键节点的时候,做一个检查点提交:

  1. 完成数据模型/接口定义 → commit
  2. 完成核心逻辑实现 → commit
  3. 完成测试编写 → commit
  4. 完成文档更新 → commit

每个 checkpoint 以 [WIP] 开头。

好处太明显了:任务中断了可以从最近的 checkpoint 恢复,不用从头再来。reviewer 也可以分段审查,每个 commit 就是一个可理解的语义单元。

最后开 PR 之前,用 git rebase -i 把这些 [WIP] commit 整理成干净的 atomic commit。

这件事 agent 自己也能做。 直接甩给它这句话:

帮我整理当前分支的提交历史。分析哪些 [WIP] commit 属于同一个逻辑变更,给出一份整理方案,确认后执行 rebase。

第三件事:git worktree——一人一间房

这是最硬核的一条,也是解决「多 agent 互相踩」问题的最彻底手段。

git worktree add ../agent-task-234 -b agent/PROJ-234-refresh-tokengit worktree add ../agent-task-301 -b agent/PROJ-301-pg-migration

一个 agent 一个 worktree。

每个 agent 有自己独立的工作目录,不会互相干扰工作区状态。但它们共享同一个 .git 目录,分支管理还是统一的。

不是多个 clone。

多个 clone 的问题是你要维护多个独立的 .git 目录,push/pull 的时候容易出岔子。worktree 共享一个 .git,轻量、干净、零运维负担。

在多 agent 编排脚本里,给每个子任务指定工作目录参数指向对应 worktree 路径就行。

agent 完成跑路之后:

git worktree remove ../agent-task-234

干净利落。

第四件事:AGENT.md——Agent 的「员工手册」

你公司有员工手册吧?

Agent 也要有。

在项目根目录放一个 AGENT.md,agent 每次启动都会读取。把你的 Git 规范写进去,它就会遵守。最低成本让规范生效的方式,没有之一。

里面至少要有这些东西:

  • 分支命名规则:agent/<task-id>-<description>
  • 绝对不能直接 push main
  • commit 必须包含 Agent-Task、Agent-Decision trailer
  • 不能提交的东西:API key、.envnode_modules、大二进制文件
  • 超过 15 分钟的任务要做 checkpoint commit
  • PR 必须用指定的模板

我后面会放一个完整的可以直接用的版本。

第五件事:PR 模板——人机交接的界面

人类 reviewer 面对 agent 写的代码,最大的痛苦是什么?

不知道 agent 在想什么。

所以 agent 开 PR 的时候,必须填写以下内容:

## Task Description## Key Design Decisions(agent 做的关键设计决策及理由)## Alternatives Considered(考虑过但没采用的方案)## Known Limitations / Follow-up Tasks## Review Guidance(建议 reviewer 重点看哪里)

这不是给 agent 增加负担,是给人类 reviewer 省命。


两个新玩具:jj 和 GitButler

如果你觉得上面这些东西都是「在 Git 的旧衣服上打补丁」,那下面这两个工具可能会让你眼前一亮。

它们都不替换 Git,底层用的还是 Git 仓库,跟 GitHub、GitLab、现有 CI 完全兼容。

Jujutsu(jj):它把你工作区本身当成了一个 commit

jj 最骚的地方是:你的工作区永远是已提交状态。

不需要 git add,不需要 git commit

你改代码的那一刻,它就自动是一个 commit 了。

这有什么好处?agent 的探索过程自动被记录,不存在「未提交的临时文件丢失」的风险。而且 jj 有一个叫 change ID 的东西——不管你反复改同一个变更多少次,change ID 始终不变。相当于 GitHub PR 的编号和具体 commit SHA 的关系。

还有 jj split:如果你的 agent 把 bugfix 和格式化改动混在了一个工作区里,jj split 打开交互式编辑器,让你选哪些 hunk 归第一个 commit,剩下的自动成第二个。

还有 jj op undo:撤销任意操作。整个工作流的无限 undo。

GitButler:先干活,再分类

GitButler 的核心叫虚拟分支(Virtual Branches)。

传统 Git 是「先切分支再做事」。 GitButler 是「先做事再分类」——你直接改文件,然后按 hunk 粒度把变更分配给不同分支。

多 agent 场景下,每个 agent 绑定一个虚拟分支,它们甚至可以在同一个工作目录里跑,GitButler 自动把变更归类。


直接拿走:一个开箱即用的 AGENTS.md

上面这些坑,我都踩过。

commit 历史乱成一锅粥、两个 Agent 互相踩对方的文件、reviewer 看着巨型 PR 骂娘、git bisect 定位到问题 commit 但里面是个大杂烩……每一条都是真实的血泪。

所以我把这些规范直接写成了一份 AGENTS.md。

你只需要把这个文件丢到项目根目录。

Agent 每次启动都会自动读取,然后就会按照分支命名规则切分支、每个 commit 带 Agent-Task trailer、15 分钟以上的任务自动做 checkpoint commit、开 PR 的时候填完整模板。

不需要配什么复杂的东西。

就一个 Markdown 文件,复制粘贴,你的 Agent 协作范式就切过来了。

AGENTS.md 下载地址:AGENTS.md[1]

说人话就是——以前你的 Agent 是散兵游勇,有了这个文件,它们就是一个能打配合的团队。


写在最后

说实话,上面这些规范和方法,与其说是给 agent 的,不如说是给我们自己的。

Agent 可以写代码,但它不会天然理解什么叫「干净的提交历史」,什么叫「可回滚的变更」,什么叫「未来的你会感谢现在的你」。

这些东西以前是靠工程师的经验和团队文化在维持。但在 agentic coding 里,它们必须被写下来、工具化、自动化。

核心就三点:

隔离。 一个 agent 一个 worktree,独立的工作空间。

透明。 每个 commit 都知道是谁、用什么 prompt、为什么这么改。

自动化。 用 CI、hook、模板守住质量底线,不靠人的自觉。

Git 不会因为 agent 而终结。

但 Git 的使用纪律,确实被逼到了一个前所未有的高度。

以上,既然看到这里了,如果觉得不错,随手点个赞、在看、转发三连吧,如果想第一时间收到推送,也可以给我个星标⭐~谢谢你看我的文章,我们,下次再见。

引用链接

[1]AGENTS.md: https://github.com/Fzuim/agents_git_md.git