您正和 Claude Code 一起制作语言区域索引:列表搜索功能正在开发,刚做到一半。这时却发现,已保存版本的页面中,标题下方的说明文字有误。修正只需两分钟,但您想单独检查它,不想和未完成的搜索混在一起。
本文将介绍如何在同一个 repository 中为第二项任务准备独立的工作目录,在其中启动单独的 Claude Code 会话,并在最后妥善保存成果。单独多一个目录本身不会加快工作;它的作用只有一个:避免两项任务的文件改动混在一起。
何时一个工作目录不够用
示例项目 locale-guide 是一个列出各语言区域的浏览器页面。目前目录中正在进行任务 A:搜索功能,分支是 feature/search,还有一处未完成的改动:
git status --short
M app.js这处改动不能丢,但现在还不能算完成。此时又来了任务 B,和搜索无关:修改 main 中已保存版本的 index.html 里的说明文字。
您可能会先想到:再开一个终端,在同一个目录中启动另一个 claude。两个会话的对话虽然不同,看到的却是同一批文件。如果它们同时修改相同区域,改动就可能混在一起。这个简单例子里,说明文字和搜索暂时位于不同文件中,但两个会话看到的都是同一个未完成项目。切换分支也得先处理当前改动。
解决办法是给任务 B 单独安排一个工作位置。Git 可以为同一个 repository 创建另一个工作目录,也就是 worktree;Claude Code 则提供 --worktree 标志,可以准备这样的目录并立即在其中启动会话。我们先看原理,再看这个标志。

先说明一点:这不是处理每项任务都必须采用的方式。如果工作区干净,而且改动很小,另开一个目录反而增加麻烦。在同一个目录里交替处理任务也完全没问题。
分支、工作目录与会话
这三者很容易混淆,因为您经常同时使用它们:
| 概念 | 保存的内容 | 所在位置 |
|---|---|---|
| 分支 | 指向某个 commit 和一条历史线的指针 | 位于 repository 中,所有工作目录共享 |
| 工作目录(worktree) | 您当前正在处理的文件,以及已暂存、准备提交的内容 | 位于磁盘上,每个目录各自独立 |
| 会话 | 与智能体的对话及其上下文 | 位于 Claude Code 中 |
因此,第二个终端的问题也就有了答案:新会话能隔开对话,却不能隔开文件。要让文件彼此独立,就需要第二个工作目录。
历史记录和分支是共享的:两个目录都连接到同一个 repository。Git 设置默认也共享,不过 Git 支持为 worktree 单独设置。工作文件和已暂存、准备提交的改动则各自独立。第一个目录里未提交的搜索改动不会自动出现在第二个目录中。
通常不能在两个目录中同时检出同一个分支。Git 会拒绝,并指出已经占用该分支的目录:
fatal: 'fix/label' is already used by worktree at '/projects/locale-guide-label'选择起始状态
示例中已经创建好 repository,至少有一个 commit,以及本地分支 main 和 feature/search。目前两个分支都指向同一个 commit,搜索功能仅作为未提交的改动存在。我们在主目录中用三条命令查看当前状态:
git status --short # 当前有哪些改动尚未保存
git branch --show-current # 主目录当前所在的分支
git log -1 --oneline main # main 上的最新 commit M app.js
feature/search
d5ec405 add locale guide page要独立修改说明文字,我们选择 main:任务 B 需要的是页面的已保存版本,而不是搜索功能当前的状态。请注意,这是您电脑上的本地 main。它不一定与远程同名分支一致,而且这条命令不会从远程拉取任何内容。
如果第二项任务需要第一项任务的成果,请先确定它需要哪个已保存的 commit,再以此创建目录。普通的 git worktree add 不会自动带入未提交的改动。单独复制文件或使用额外的环境准备工具,则是另外的操作。
创建第二个工作目录
在 locale-guide 目录中运行:
git worktree add -b fix/label ../locale-guide-label main从左到右理解这条命令:创建新分支 fix/label,在旁边的 ../locale-guide-label 路径创建工作目录,并以 main 作为起点。最后一个参数明确指定了基准。省略它时,Git 会采用 feature/search 分支当前的 HEAD commit,但不会包含未提交的改动。在这个例子里,两个分支目前还指向同一个 commit,所以文件会完全相同;搜索功能一旦有了 commit,基准选择就会影响结果。Git 的回复大致如下:
Preparing worktree (new branch 'fix/label')
HEAD is now at d5ec405 add locale guide page接下来检查结果。-C 标志会让 Git 在指定目录中执行命令,而不必切换到该目录:
git worktree list
git -C ../locale-guide-label branch --show-current
git -C ../locale-guide-label status --short以下是示例输出,路径为假设值,您的路径会有所不同:
/projects/locale-guide d5ec405 [feature/search]
/projects/locale-guide-label d5ec405 [fix/label]
fix/label列表显示了两个目录及各自的分支。主目录仍在 feature/search,未完成的搜索改动也还在;新目录则位于 fix/label。第二个目录中的 status 没有输出任何内容,说明工作区干净,正是我们想要的结果。
如果指定的路径或分支名称不可用,Git 会拒绝操作并说明原因,例如 already exists 或 is already used by worktree。请检查 worktree 列表、分支和指定目录中的内容。它们可能来自您先前的操作,也可能属于另一项任务。不要随手加上 --force:先查清已经存在什么,以及是否还需要它。
在 Claude Code 中打开第二项任务
您可以在单独的 IDE 窗口中打开 locale-guide-label,也可以在新终端中切换到该目录,再从那里启动 claude。新会话不了解任务 A,这很正常;它只需要自己的上下文:
预期目录:locale-guide-label,分支:fix/label。
先检查实际目录和分支。如果不符,请停止。
阅读 index.html。
将标题下方的说明改为"语言区域列表:代码、语言和国家/地区"。
不要更改文件中的其他内容,并向我展示改动。请 Claude Code 在修改文件前先报告工作目录和当前分支,再核对结果是否符合您的预期。在错误目录中启动的智能体,工作起来也会和在正确目录中一样有把握。
修改后,请分别在两个终端中运行 git status 和 git diff:第二个目录中只有 index.html 的说明文字发生了变化,第一个目录里原有的 app.js 改动仍在。单看 status 只能看到文件名,无法证明文件内容保持完好。要准确对比,检查期间请先暂停搜索任务。在主目录中检查时,请使用它自己的终端,不要让隔离会话中的智能体切换过去。也请从第二个目录打开页面,否则看到的还是旧说明。
还有一个更快捷的办法:claude --worktree label-fix 会自动创建工作目录,并在其中启动会话。根据当前文档,目录会创建在 repository 内的 .claude/worktrees/label-fix/,分支名为 worktree-label-fix,起点则是远程 repository 的默认分支(通常为 main),而不是您当前的 commit。如果没有配置远程 repository,起点会是当前的本地 commit。因此,它和上面命令中明确指定 main 并不相同,不过在简单项目中结果往往一致。默认行为可以通过设置修改,具体细节请查阅您所用版本的文档。
如果您认可默认基准,而且想快速为任务准备独立位置,这个标志就很方便。如果已经用上面的命令创建了目录,就不必再运行它,否则会多出一个目录。还应将 .claude/worktrees/ 加入 .gitignore,否则新目录中的内容会作为未跟踪文件出现在主目录中。
哪些内容仍然共享
单独的目录能隔开的东西,比乍看起来要少:
| 彼此独立 | 共享 | 完全没有隔离 |
|---|---|---|
| 工作文件、暂存内容、目录当前所在的分支 | 历史记录、所有分支、repository 设置、远程 repository 地址 | 本地服务器端口、外部数据库、云服务、进程对磁盘其他区域的访问 |
第三列最容易被忽略。Worktree 隔离的是 Git 文件,不是整台机器。两个本地服务器无法同时占用同一个端口;如果设置指向同一个外部数据库,两个目录发出的请求也会访问同一数据库。Claude Code 在单独目录中执行的检查,同样不会让它成为整个系统的隔离沙箱。
第二个目录包含所选 commit 中的文件。如果依赖和本地设置没有存入 Git,通常还需要单独准备运行环境;额外工具可以自动完成这项准备。不要盲目复制 .env:相同的凭据可能让两个进程都连接到同一个服务。这个静态索引不需要服务器或密钥,直接打开页面文件即可。
保存并转移成果
在目录 B 中用浏览器检查说明文字,查看 git diff,然后只提交需要的文件:
git add index.html
git diff --cached
git commit -m "fix: correct locale list label"提交前,请确认暂存的只有所需改动。如果 git diff --cached 中还有其他改动,请先弄清楚它们的情况。
这个 commit 已进入共享的 repository,因此从主目录也能看到。但它并不会自动进入 main 或 feature/search:它仍在自己的分支中,等待您决定是否合并。
只有在任务 A 已完成或至少已保存,而且主目录干净时,才适合转移成果。搜索尚未完成时,不要切换到 main;先处理好搜索任务。主目录干净后:
git checkout main
git merge fix/labelFast-forward
index.html | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)以上输出对应的情况是:创建 fix/label 后,main 没有发生变化。如果 Git 提示存在冲突,请停下来按合并规则处理。这是另一个主题,详见文章 "Git 分支与合并"。合并后再次打开页面:说明文字应已更新,语言区域列表则保持原样。feature/search 分支并没有因此更新;继续搜索前,请另行决定是否要把 main 中的修正合并到该分支。
移除不再需要的目录
先关闭第二个目录中的会话,以及在那里启动的所有程序。然后检查目录中是否还有需要保留的内容:
git -C ../locale-guide-label status --short --ignored修改过和新建的文件会直接显示;--ignored 标志则会列出被忽略的文件,其中经常包含本地设置和笔记。确认成果已保存到正确分支后,就可以从主目录移除该目录:
git worktree remove ../locale-guide-label
git worktree list如果目录中有已跟踪文件被修改,或存在未被忽略的新文件,Git 通常会拒绝移除目录:
fatal: '../locale-guide-label' contains modified or untracked files, use --force to delete it不要把错误提示中的建议当作第一步执行。先检查文件并保存需要的内容。目录删除后,未提交的数据可能无法通过 Git 恢复。也不要把 Git 的拒绝当成全面保护:即使不使用 --force,被忽略的文件也可能被删除,所以我们刚才单独检查了它们。
还有一点很容易弄错:Git 命令会删除工作目录,但不会删除分支;执行后,fix/label 仍会出现在 git branch 列表中。这很方便,成果并没有消失。等到确实不再需要该分支,而且其中需要的改动都已合并后,再单独删除分支。
退出使用 --worktree 启动的会话时,Claude Code 会检查目录。如果其中没有改动和新 commit,而且会话没有名称,它会直接删除目录和分支,不会询问。如果有工作成果,它会询问您是保留还是删除目录。在这个对话框中选择删除,会同时移除目录和 Claude Code 创建的分支,以及其中的所有内容。这和上面的 Git 命令不是一回事。如果要保留成果,请选择"保留",然后自行转移。
不要绕过 Git,直接通过文件管理器删除目录:repository 仍会认为该目录存在,worktree 列表中也会留下指向已不存在目录的记录。
在 Claude Code 中处理第二项任务
整个流程可以归纳为六步:
- 把第二项任务和第一项任务区分开,并决定它以哪个已保存状态为起点;
- 明确指定基准来创建工作目录;如果您接受默认设置,也可以运行
claude --worktree; - 在新目录中先核对路径和分支,再开始修改;
- 只向会话提供当前任务所需的上下文,不要带上其他任务的历史;
- 在实际修改文件的目录中检查改动,并保存成果;
- 决定是否合并,之后再移除目录。
单独的目录不会替您检查代码,也不会替您验收工作。它让每项任务都有自己的工作文件。示例中的好处很直观:说明文字在独立目录中修改并检查,未完成的搜索则留在第一个目录中。
自测
第二个目录中没有未提交的搜索改动。出问题了吗?
没有,这正是预期结果。该目录是从 main 上的 commit 创建的,而不是从任务 A 当前的文件创建。未提交的改动仍留在各自的目录中。
两个会话在同一个目录中打开。任务彼此独立吗?
对话是分开的,文件却是共享的。如果两项任务修改同一区域,改动就可能混在一起。
已经在任务 B 的分支中创建了 commit,但 main 中看不到新的说明文字。
这是正常的:commit 仍在自己的分支中,不会修改其他分支。要让改动进入其他分支,需要进行合并。
第二个本地服务器无法使用相同端口启动。
单独的目录不会隔离端口。请改用另一个端口。
Git 拒绝移除工作目录。
请阅读拒绝原因:除了尚未保存的文件,目录也可能被锁定,或本身就是主工作目录。保存需要保留的内容,并弄清当前状态。不要随手添加 --force。
如果您想亲手练习,可以使用一个只有几个 commit 的独立示例 repository:创建两个目录,只在第二个目录中修改文本,分别检查两个目录,再移除不需要的目录。整个练习不需要任何服务或账号。
GO TO FULL VERSION