跳到正文
DEV Community· Enjoy Kumawat·· 1 小時前AI 評分64

Git worktree 實際隔離甚麼,又不會隔離甚麼

What Git Worktrees Actually Isolate (and What They Don't)

AI 導讀

Git worktree 會隔離各工作目錄中的檔案變更,但不會隔離分支內容,因此多個分支合併時仍可能出現衝突。作者以兩個 worktree 同時修改 shared.py 並各自提交的測試,展示衝突會在合併時浮現。他建議並行安排 Agent 工作前先確認各工作預計修改的檔案;若涉及共用檔案,可將相關工作依序處理,或預留時間解決衝突。

正文

I run most of my agent sessions in a my-git-manager repo, and the harness I use has a built-in EnterWorktree tool: call it, and the session gets switched into a fresh git worktree under .claude/worktrees/, on a new branch, isolated from whatever else is happening in the main checkout. The pitch is obvious — two sessions, two worktrees, no stepping on each other's uncommitted changes. I'd been taking that at face value for weeks. Then a trending post on dev.to this week ("worktrees do not remove the collision, they move it to merge time") made me actually go check what "isolated" means here, instead of assuming it means "conflict-free."

It doesn't mean conflict-free. It means something much narrower, and the gap between those two is worth being precise about if you're going to run several agent sessions against the same repo in parallel.

What a worktree actually gives you

A git worktree is a second working directory backed by the same .git object database, checked out to its own branch. That's the whole mechanism. Two worktrees can have the same file open, with different uncommitted edits, and git will never complain, because nothing about editing files on disk touches git's index until you stage something. I checked this directly:

git init -q repo && cd repo
echo "line1" > shared.py
git add shared.py && git commit -qm "init"
git branch feature-a
git branch feature-b
git worktree add ../wt-a feature-a
git worktree add ../wt-b feature-b

# in wt-a:
sed -i '1s/.*/line1_CHANGED_BY_A/' shared.py
git add shared.py && git commit -qm "A: change line1"

# in wt-b, at the same time:
sed -i '1s/.*/line1_CHANGED_BY_B/' shared.py
git add shared.py && git commit -qm "B: change line1"

Both commits succeed. No warning, no lock contention, no conflict of any kind — because as far as git is concerned, these are two independent branches with independent commit histories. The working-tree isolation is real: an agent in wt-a can run a build, leave half-edited files lying around, blow away a node_modules, whatever — and wt-b never sees any of it, because it's a genuinely separate directory tree.

What it doesn't give you

The moment you try to bring both branches back together, the isolation is over, because it was never isolation from each other's content — just from each other's filesystem. Same repo, continuing from the commits above:

git checkout master
git merge feature-a     # clean
git merge feature-b
Auto-merging shared.py
CONFLICT (content): Merge conflict in shared.py
Automatic merge failed; fix conflicts and then commit the result.
<<<<<<< HEAD
line1_CHANGED_BY_A
=======
line1_CHANGED_BY_B
>>>>>>> feature-b

Exactly the conflict you'd get if two people had edited the same line in two normal clones. The worktree didn't prevent it, soften it, or even detect it early — it just delayed the moment you find out, from "while both edits were being made" to "whenever someone merges." For a human workflow that's usually fine, because a human merging two feature branches expects to resolve conflicts. For an agent workflow it's a sharper problem: an agent that successfully committed in its worktree has no signal that its change is about to collide with something else, because nothing it did locally touched the other worktree at all. The first the agent (or you) hears about it is a failed merge, possibly minutes or sessions later, with no context for why line 1 matters to two different branches.

Where this actually bites

The case I cared about wasn't two humans — it was two agent sessions I'd deliberately split with EnterWorktree so they could work on unrelated parts of the same repo without fighting over uncommitted state. That part worked exactly as advertised. What I hadn't thought through: if both sessions end up editing the same shared file — a config, a shared utility, docs/project_notes/key_facts.md, anything neither session "owns" — the worktree boundary gives zero warning that this is about to happen. You find out at merge time, same as the test above, except now it's an agent merging (or a human merging an agent's branch) with no idea which of two automated edits should win.

The practical fix isn't a git feature, it's a workflow one: worktrees are safe for genuinely disjoint work, and risky for anything that touches a small set of shared files, exactly in proportion to how often those files get touched. Before splitting agent sessions into worktrees on a real task, I now check which files each session is likely to touch (git log --name-only on the relevant area, or just asking the session what it plans to edit) rather than assuming "different worktree" implies "different files." If two sessions are both going to end up near the same file, I either serialize that part of the work or accept I'm going to resolve a conflict later and plan for it, rather than being surprised by it.

The one-line version

A git worktree isolates your working directory, not your merge. If you're relying on it to keep two lines of work from fighting, check whether they're actually touching different files — because git won't tell you they aren't until it's too late to matter.

來源:DEV Community · dev.to