第 2 课:Git + Coding Agent——为什么企业级 Agent 必须学会“隔离修改”
上一课建立了 LLM → Tool Call → Shell → stdout/stderr → 再决策 的 Agent Loop。今天加入第二个非常关键的基础设施:entity["software","Git","distributed version control system"]。
目标不是背 Git 命令,而是理解一个企业问题:如果同时让 3 个 Agent 修改同一个项目,怎样防止它们互相覆盖代码?
答案之一就是:
Git branch + worktree + diff + test + review
这也是现代 Coding Agent 越来越重要的一种执行模式。近期 entity["software","OpenAI Codex","coding agent"] 和 entity["software","OpenCode","AI coding agent"] 的公开 issue 中,都能看到大量围绕 worktree、工作目录、diff 捕获和 Agent session 隔离的真实工程问题。citeturn0search2turn0search3
先建立 Git 的正确心智模型
假设项目当前是:
sample-app/
├── src/
│ └── Program.cs
└── .git/
.git 可以暂时理解为项目的“版本数据库”。
你修改:
Program.cs
但还没有 commit,此时处于:
HEAD
│
▼
上一次 commit
│
└──── working tree
│
└── Program.cs 已修改
因此:
git status
回答的是:
当前工作目录与 Git 记录的状态有什么不同?
而:
git diff
回答:
到底改了哪些内容?
比如 Agent 把:
int timeout = 10;
改成:
int timeout = 30;
git diff 会近似显示:
- int timeout = 10;
+ int timeout = 30;
这对 Agent 特别重要。
因为模型不能仅凭:
“我刚才应该只改了 timeout。”
来判断自己做对了什么。
企业系统更可信的做法是:
Agent的描述
↓
不完全可信
Git实际diff
↓
事实依据
这已经引出第一个 Agent 工程原则:
不要相信 Agent 声称修改了什么,要检查实际状态。
为什么 Codex 会频繁调用 Git
现在看一个 2026 年非常有意思的真实案例。
Codex Desktop 在 Windows 上曾出现文件修改失败问题,issue 中发现后台存在类似:
git diff --no-ext-diff --no-textconv \
--color=never \
--find-renames \
--numstat -z
这样的 Git diff 读取操作。citeturn0search6
今天不用理解所有参数。
只注意:
git diff
Codex 并不是只在最后告诉你:
“我修改了三个文件。”
它的运行环境需要持续掌握 repository 的真实变化。
于是 Coding Agent 实际架构逐渐变成:
LLM
│
Agent Runtime
│
┌──────────┼──────────┐
↓ ↓ ↓
Shell Files Git
│ │ │
dotnet test patch status
npm test read diff
rg write branch
worktree
Git 实际上已经成为 Agent Runtime 的一个重要“状态传感器”。
为什么 branch 还不够
假设现在同时有两个任务:
Agent A:
修复 HTTP timeout
Agent B:
重构日志模块
最简单想法:
Agent A → branch feature/http-timeout
Agent B → branch feature/logging
但是存在一个问题:
普通 Git checkout 在一个目录里一次只能 checkout 一个 branch。
于是:
sample-app/
↓
当前只能是一个 branch
如果 A 正工作:
git switch feature/http-timeout
B 又运行:
git switch feature/logging
A 的执行环境就被改变了。
对于并行 Agent,这很危险。
Worktree 出场
Git 提供:
git worktree
它允许:
sample-app/
│
├── main workspace
│
│ branch: main
│
├── ../sample-app-timeout
│
│ branch: agent/http-timeout
│
└── ../sample-app-logging
branch: agent/logging
现在:
Agent A
↓
sample-app-timeout/
Agent B
↓
sample-app-logging/
两者:
- 文件目录不同;
- branch 不同;
- working tree 不同;
- 但共享 Git repository 历史。
这就是 Agent workspace isolation。
真实命令
假设当前:
git branch
输出:
* main
创建 Agent 专用工作区:
git worktree add ../sample-app-agent -b agent/test
拆开看:
git
│
├── worktree
│ Git worktree 功能
│
├── add
│ 创建一个工作目录
│
├── ../sample-app-agent
│ 新目录
│
├── -b
│ 同时创建 branch
│
└── agent/test
branch 名称
然后:
git worktree list
可能得到:
/Users/me/sample-app abc123 [main]
/Users/me/sample-app-agent abc123 [agent/test]
现在两个目录初始代码完全一样。
但是修改互不影响。
为什么这非常适合 Coding Agent
假设企业服务器同时收到:
Task #101
修复登录问题
Task #102
增加导出Excel
Task #103
修复数据库连接
可以变成:
Git Repository
│
┌─────────────┼─────────────┐
↓ ↓ ↓
Worktree A Worktree B Worktree C
│ │ │
Agent A Agent B Agent C
│ │ │
Test Test Test
│ │ │
Diff Diff Diff
│ │ │
└─────────────┼─────────────┘
↓
Review
↓
Merge
注意:
这已经非常接近一个 Mini Agent Platform 的 workspace manager。
后面我们自己实现 Agent 时,也会真正做这一层。
OpenCode 的真实案例
OpenCode 社区已经有专门围绕 Agent worktree 工作流的插件:
Agent
↓
worktree_create()
↓
创建 Git worktree
↓
启动新 terminal
↓
在隔离目录运行 OpenCode
↓
Agent 完成工作
↓
commit
↓
删除 worktree
插件甚至支持创建 worktree 后执行:
pnpm install
或者:
docker compose up -d
删除之前:
docker compose down
这已经把今天的 Git 和后面要学的 Docker 生命周期连接起来了。citeturn0search0
注意:这个 worktree 插件是社区项目,不是 OpenCode 官方核心组件,因此学习时要区分“OpenCode 本身”和“生态插件”。
Worktree 本身也会产生 Agent Bug
这一点特别值得企业工程师理解。
worktree 不是简单复制目录。
普通 repository:
project/
└── .git/
但 linked worktree 中:
project-feature/
└── .git
这里 .git 甚至可能不是目录,而是一个文本文件,指向:
project/.git/worktrees/project-feature
这已经让不少 Coding Agent 出过问题。
2026 年 OpenCode 的一个公开 issue 就展示了这种情况:代码错误地按每个 worktree 的 .git 路径寻找项目缓存,导致同一个 repository 的不同 worktree 被识别成不同 project ID。问题定位到了 src/project/project.ts 的目录解析逻辑;建议修复方式之一就是正确使用:
git rev-parse --git-common-dir
来找到共享 Git 目录。citeturn0search3
这就是非常好的“源码 + Git + Agent 调试”案例。
你以后看到:
Agent在主仓库正常
到了worktree:
session消失
项目识别错误
branch错误
第一反应应该增加:
.git到底是目录还是pointer?
git-common-dir是什么?
cwd在哪里?
而不是马上认为:
模型出问题了。
Codex 也有类似真实问题
2026 年 7 月 Codex App 有一个公开问题:
从任务创建 worktree fork 时,可能基于过时的默认 branch commit 创建新工作区,再把原任务的未提交 diff 应用过去。
结果就可能发生:
原始任务
main @ commit C
│
├── uncommitted diff
│
↓
创建 worktree
│
但基于旧 commit A
│
↓
再应用 C 上产生的 diff
│
↓
冲突 / 错误代码
这不是 LLM reasoning 问题。
这是:
Git base commit
+
worktree provisioning
+
patch application
的问题。citeturn0search2
这类问题就是以后 Agent 平台工程师需要定位的。
一个必须掌握的词:CWD
以后会经常看到:
cwd
就是:
Current Working Directory
当前工作目录。
例如:
CWD =
C:\Projects\sample-app-agent
Agent 执行:
git status
实际含义是:
在 C:\Projects\sample-app-agent
运行 git status
如果 Runtime 错误地变成:
CWD =
C:\Projects\sample-app
即使执行完全相同:
git status
得到的 branch、diff、文件都可能不同。
所以以后调 Agent,一定要问:
模型生成了什么命令?
↓
Runtime在哪个cwd执行?
↓
使用哪个shell?
↓
使用什么env?
↓
返回什么exit code?
这是非常重要的四连问。
Windows / PowerShell 实验
今天实验大约 10 分钟。
找一个不重要的 Git 测试项目。
先执行:
git status
git branch --show-current
git rev-parse --show-toplevel
分别观察:
repository状态
当前branch
repository根目录
然后:
git worktree list
创建实验 worktree:
git worktree add ../agent-lab -b agent/lab
进入:
cd ../agent-lab
执行:
git branch --show-current
git rev-parse --show-toplevel
git status
应该看到 branch:
agent/lab
然后创建:
"hello agent" | Out-File agent-test.txt
再:
git status
git diff
这里会出现一个有意思的现象:
git status 能看到:
agent-test.txt
但普通:
git diff
可能看不到这个文件内容。
为什么?
因为它还是:
untracked file
这就是下一步 Git 知识:
untracked
working tree
index/staging
HEAD
一个非常重要的 Agent 安全规则
以后自己的 Agent 不应该简单实现:
run("git add .")
run("git commit -m 'done'")
因为 git add . 可能把:
.env
API Key
临时数据库
测试数据
大型模型文件
用户隐私文件
一起加入 repository。
企业 Agent 更合理的是:
Agent修改
↓
git status
↓
确定changed files
↓
安全规则检查
↓
git diff
↓
test
↓
人工/策略审批
↓
选择性stage
↓
commit
以后讲 Secret、供应链安全和 CI/CD 时会再次回来。
今天第一次接触 .gitignore
假设项目:
.env
node_modules/
bin/
obj/
通常不应该提交。
于是 .gitignore:
.env
node_modules/
bin/
obj/
Coding Agent 必须尊重这些规则。
但请记住:
.gitignore是 Git 的版本控制规则,不是安全边界。
Agent 仍然可能通过:
cat .env
读取 .env。
真正阻止读取,需要:
Sandbox
Permission
Container isolation
Secret management
这就是:
.gitignore ≠ security
非常常见的面试/实际工程问题。
Agent 安全修改代码的最小工作流
今天开始建议形成这个习惯:
① git status
↓
② 确认当前branch
↓
③ Agent开始修改
↓
④ git status
↓
⑤ git diff
↓
⑥ build/test
↓
⑦ 再看git diff
↓
⑧ review
↓
⑨ commit
并行任务则升级成:
main
│
├── worktree Agent-A
│ ↓
│ diff
│ ↓
│ test
│
└── worktree Agent-B
↓
diff
↓
test
这就是后面企业 Agent 平台的最初雏形。
今天的故障排查案例
如果 Agent 明明运行在:
D:\sample-app-feature
UI 却显示:
branch = main
不要马上重新启动模型。
依次检查:
Get-Location
git rev-parse --show-toplevel
git branch --show-current
git rev-parse --git-dir
git rev-parse --git-common-dir
git worktree list
2026 年 OpenCode 就有公开 issue:打开 worktree 后 UI 显示主仓库 branch,而实际在 worktree 执行 git rev-parse --abbrev-ref HEAD 得到的 branch 是正确的。citeturn0search8
这就是标准的:
UI state
≠
Git真实状态
排错时应优先相信可验证的底层事实。
企业岗位能力映射
今天实际上已经开始训练 Git、workspace isolation、CWD、branch、diff、worktree、Agent 并发和故障定位。
企业 Agent 平台的很多高级能力,本质都是今天这个概念继续扩展:
Git worktree
↓
独立workspace
↓
Docker container
↓
独立filesystem/process/network
↓
Kubernetes Pod
↓
企业级Agent workload isolation
所以后面讲 Docker 时,你不会突然面对一个毫无关系的新技术,而会发现:
Git worktree 主要解决代码状态隔离;Container 进一步解决运行环境隔离。
今日检查题
- 为什么两个并行 Coding Agent 只创建不同 branch,还不一定足够?
git status和git diff分别解决什么问题?- Agent 位于 worktree,但 Runtime 的 CWD 错误指向主 repository,会发生什么?
.gitignore里写了.env,为什么仍不能认为 API Key 安全?- Worktree 与 Docker 最大的区别是什么?
参考答案核心是:worktree 给每个 Agent 独立 working directory;status 看状态、diff 看具体修改;CWD 错会操作错误工作区;gitignore 不阻止 Agent 读取文件;worktree 隔离代码工作区,而容器进一步隔离进程、依赖、文件系统、网络和资源。
下一课沿着今天的真实操作继续进入 Git staging / commit / branch / merge / conflict + Agent 自动修改安全机制,并开始解释为什么 Agent 特别容易制造 merge conflict,以及 Codex/OpenCode 如何围绕 Git 状态建立执行环境。