并行 Agent 的 git add -A 会偷走你已暂存的文件
为了提速,我曾尝试让多个 Agent session 并行在同一个 git 仓库里工作——每个 session 负责一个独立组件。理论上互不干扰,实际上踩了一个「有人提交了你的文件,但你的 commit 报 nothing added」的诡异坑。
现象
我在 session A 里完成了某个组件,用 pathspec 精确暂存:
git add packages/ui/src/accordion/
git commit -m "feat(ui): Accordion 组件初版"commit 报错:
nothing added to commit but untracked files present (use "git add" to track)
去看 git log,这几个文件确实已经提交——但提交人是 session B,commit 信息是和 Accordion 毫无关系的「docs(spec+plan): Overlay 组件规格」。我自己的 commit 从未发生。
根因
git 仓库只有一个共享的 index(暂存区)。两个 session 共享同一个工作树时,index 不属于任何一方独占。
时序上发生了这件事:
- Session A 执行
git add packages/ui/src/accordion/,Accordion 文件进入 index。 - Session B 执行
git add -A(或git add .、git commit -a),重新扫描整个工作树——你刚刚暂存的文件也被它纳入自己的暂存区。 - Session B
git commit成功,把 Accordion 文件写进了自己的 commit,然后清空 index。 - Session A 执行
git commit,index 此刻为空 → "nothing added"。
git add <pathspec> 只能控制"你暂存了什么",它无法阻止其他进程同时对 index 执行写操作。git 的 index 没有进程级别的排他锁机制,任何人的 git add -A 都能把你已暂存的文件扫走并提交到别人的 commit 下。
排查信号
遇到以下任一迹象,基本可判定有并行 session 在同一仓库活跃:
git status的输出在你两次读取之间凭空改变(你没做任何操作)。git rev-parse HEAD在你两条命令之间悄悄变了,HEAD 被别人推进。ls -lt看到文件 mtime 是秒级新鲜,但那些文件你根本没碰过。git commit报 "nothing added",但紧接着git log -- <你的目录>显示文件已在某个不相关的 commit 里。
快速检测脚本:
h0=$(git rev-parse HEAD); sleep 20; h1=$(git rev-parse HEAD)
[ "$h0" != "$h1" ] && echo "LIVE sibling session committing"正解
git worktree add 为每个工作目录分配独立的 index,不同 worktree 的 git add -A 只影响自己的暂存区,彻底消除 index 竞争。
# 主 session(主工作树已有)
# Session B 新建独立 worktree
git worktree add ../repo-session-b -b feat/session-b
# 各自在自己的 worktree 目录下工作,index 互不干扰
cd ../repo-session-b
git add -A && git commit -m "..."这是唯一没有竞争的修法。在规划并行 Agent fan-out 时就确定 worktree 策略,不要等到碰撞后再补救。
如果文件已被兄弟 session 提交(事后补救),先确认完整性,再决定是否补一个 commit 修正归属:
git ls-files packages/ui/src/accordion/ # 是否已被追踪?
git log --oneline -- packages/ui/src/accordion/ # 在哪个 commit 里?
git diff HEAD -- packages/ui/src/accordion/ # 内容是否完整?(空 = 安全)文件内容完整但归属错误时,可视情况补一个 fix: commit 说明,或由人工协调 git commit --amend(注意 amend 在多 session 下同样有竞争风险,操作前确保兄弟 session 已静止)。
一句话外卖
并行 Agent 共跑一个 git 仓库时,
git add -A是共享 index 上的全局武器——任何一方用它都能把别人的 staged 文件一并提交,唯一安全隔离是git worktree,而不是 pathspec。