返回博客

并行 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 不属于任何一方独占。

时序上发生了这件事:

  1. Session A 执行 git add packages/ui/src/accordion/,Accordion 文件进入 index。
  2. Session B 执行 git add -A(或 git add .git commit -a),重新扫描整个工作树——你刚刚暂存的文件也被它纳入自己的暂存区
  3. Session B git commit 成功,把 Accordion 文件写进了自己的 commit,然后清空 index。
  4. Session A 执行 git commit,index 此刻为空 → "nothing added"。
坑:pathspec 暂存不能阻止兄弟 session 的 add -A

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"

正解

正解:每个并行 session 用独立的 git worktree

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