Gemini CLI Git Worktree 实战:并行会话的独立工作目录指南
【免费下载链接】awesome-design-systems💅🏻 ⚒ A collection of awesome design systems项目地址: https://gitcode.com/GitHub_Trending/aw/awesome-design-systems
你同时开着两个 Gemini CLI 会话处理同一个仓库:A 会话在修登录 bug,刚写入一半的未提交改动;B 会话却在开发搜索功能,把 A 改到一半的文件当基准读取,又把自己的改动写回同一份工作区。两边的修改互相污染上下文,连构建结果都不可信。Gemini CLI 的实验性功能Git Worktree就是为这类冲突设计的:它为每个会话自动分配一个独立的 Git worktree 工作目录——文件与分支各自独立、共享同一份仓库历史(worktree 可以理解为同一仓库的第二份检出,只是文件状态和分支互不干扰)。
三步跑通:如何开启 Worktrees 配置并启动隔离会话
先建立整体印象,最小可用路径只有三步;每一步的机制细节后文再拆。
第 1 步:打开实验性开关。Worktrees 默认关闭,两种开启方式:在 CLI 里执行/settings,搜索Enable Git Worktrees置为true;或直接写入settings.json:
{ "experimental": { "worktrees": true } }该配置项定义在 packages/cli/src/config/settingsSchema.ts(约 2234-2243 行):归属Experimental分类、默认false、requiresRestart: true。也就是说,这是实验性功能,且修改开关后必须重启 CLI 才生效,改完记得重开进程。
第 2 步:用--worktree启动隔离会话。
gemini --worktree feature-search # 显式命名 gemini -w # 不传名称,自动随机生成注意:每个新 worktree 都是全新的代码副本,进入后需按项目规范初始化环境——npm install、yarn、虚拟环境或标准构建流程。另外,开关未启用时传--worktree会直接报错,校验逻辑在 packages/cli/src/config/config.ts 第 269-270 行。
第 3 步:退出后按打印的命令恢复。
cd .gemini/worktrees/feature-search gemini --resume <session_id><session_id>就是退出页打印的那串 ID,逐字复制即可。
--worktree 命名规则解析:目录落盘、分支约定与随机名生成
跑通只是第一步,接下来拆开看启动时到底发生了什么。
目录位置与分支命名约定
packages/core/src/services/worktreeService.ts 中createWorktree()(第 121-134 行)完成核心动作:
const worktreePath = getWorktreePath(projectRoot, name); // <项目根>/.gemini/worktrees/<名称> const branchName = `worktree-${name}`; await execa('git', ['worktree', 'add', worktreePath, '-b', branchName], { cwd: projectRoot, env: getSafeGitEnv(), });即目录固定落在<项目根>/.gemini/worktrees/<名称>,分支名固定为worktree-<名称>——后文手动清理命令里的worktree-feature-search正是这个来源。项目根由getProjectRootForWorktree()(第 96-115 行)解析:执行git rev-parse --git-common-dir,取.git目录的父目录作为根;解析失败则退化为当前工作目录。
不传名称时的随机名生成
省略名称时,setup()用 ISO 时间戳加 4 位随机后缀拼装(第 33-42 行):
if (!worktreeName) { const timestamp = new Date().toISOString() .replace(/[:.]/g, '-').replace('T', '-').replace('Z', ''); const randomSuffix = Math.random().toString(36).substring(2, 6); worktreeName = `${timestamp}-${randomSuffix}`; }基准 SHA 记录与防重入守卫
创建前会先用git rev-parse HEAD抓取基准提交baseSha,与名称、路径一起组成WorktreeInfo { name, path, baseSha }返回——这是后续判断"worktree 里有没有产生过改动"的依据。
CLI 入口侧,packages/cli/src/gemini.tsx(第 380-388 行)在启动早期调用 packages/cli/src/utils/worktreeSetup.ts 的setupWorktree(),并用性能分析器打点setup_worktree。该函数内部有防重入守卫:
if (process.env['GEMINI_CLI_WORKTREE_HANDLED'] === '1') { return undefined; } ... process.chdir(worktreeInfo.path); process.env['GEMINI_CLI_WORKTREE_HANDLED'] = '1';worktree 创建成功后立即chdir切入新目录并置位环境变量,确保 CLI 因自身目的重新拉起进程时,不会在 worktree 里再嵌套创建一层。对应测试见 packages/cli/src/utils/worktreeSetup.test.ts。
Worktree 会话退出策略:现场完整保留与 --resume 恢复
那会话结束后呢?Gemini 会把目录清掉保持干净吗?当前版本的答案是全部保留。
- worktree 不删除:修改过的文件、已暂存改动、未跟踪文件,以及新分支上的提交原样留存;
- 分支不自动删除:worktree 与分支都由你自行清理;
- 退出时打印两条指令:如何恢复工作、如何手动删除。
提示语实现位于 packages/cli/src/ui/components/SessionSummaryDisplay.tsx(第 39-43 行),存在 worktree 信息时页脚被替换为:
footer = `To resume work in this worktree: cd ${escapeShellArg(worktreeSettings.path, shell)} && gemini --resume ${footerSessionId}\n` + `To remove manually: git worktree remove ${escapeShellArg(worktreeSettings.path, shell)}`;两条命令可直接复制执行,路径与会话 ID 会按当前 shell 转义;渲染验证见 packages/cli/src/ui/components/SessionSummaryDisplay.test.tsx(第 199-218 行)。
值得注意的是,核心层其实已具备更完整的条件清理能力:hasWorktreeChanges()(worktreeService.ts 第 151-184 行)先用git status --porcelain检查未提交改动,再比较HEAD是否偏离基准 SHA,任何 git 命令失败时保守判定为"有改动",防止误删用户工作;maybeCleanup()(第 62-84 行)在无改动时自动执行git worktree remove --force加git branch -D,有改动则保留。但在当前版本里,maybeCleanup的调用方主要是 packages/core/src/services/worktreeService.test.ts 中的单元测试(第 271-304 行),CLI 退出路径仍遵循"不自动删除"——条件自动清理属于该实验性功能的演进方向。
进阶控制:手动 git worktree 命令与自动托管边界
默认的落盘位置和命名不合意,或需要清理被保留的 worktree 时,可以直接用原生 Git 命令接管。
手动创建(任意目录、任意分支名):
git worktree add ../project-feature-search -b feature-search cd ../project-feature-search && gemini清理保留的 worktree(分支名遵循worktree-<名称>约定):
git worktree remove .gemini/worktrees/feature-search --force git branch -D worktree-feature-search两条路径的差异对比:
| 维度 | Gemini 托管 worktree | 手动创建 worktree |
|---|---|---|
| 目录位置 | 固定.gemini/worktrees/<名称> | 任意 |
| 分支名 | 固定worktree-<名称> | 任意 |
| 启动行为 | 自动 chdir、记录基准 SHA、退出提示 | 不介入,按普通项目使用 |
| 清理方式 | 退出提示 + 手动命令 | 手动命令 |
托管边界由 worktreeService.ts 中的isGeminiWorktree()(第 136-149 行)划定:通过realpath比对判断目录是否位于.gemini/worktrees/之下,只有 Gemini 托管的 worktree 才走自动管理逻辑,你手动放在别处的完全不受干预。此外,该功能的所有 git 子进程都经由getSafeGitEnv()(见 packages/core/src/utils/gitUtils.ts)构造安全环境变量执行,宿主机上异常的 git 配置不会干扰 worktree 操作。
速查表:Gemini CLI Git Worktree 场景 → 命令/配置
| 场景 | 命令 / 配置 |
|---|---|
| 开启功能(需重启) | /settings搜索 Enable Git Worktrees 置true;或settings.json写{"experimental": {"worktrees": true}} |
| 命名启动 | gemini --worktree feature-search(简写-w) |
| 随机名启动 | gemini --worktree |
| 确认目录与分支 | .gemini/worktrees/<名称>;分支worktree-<名称> |
| 退出后恢复会话 | cd .gemini/worktrees/<名称> && gemini --resume <session_id> |
| 清理 worktree | git worktree remove <路径> --force;git branch -D worktree-<名称> |
| 自定义 worktree | git worktree add <目录> -b <分支>;cd <目录> && gemini |
相关文档与源码路径
| 内容 | 路径 |
|---|---|
| 官方 worktree 文档 | docs/cli/git-worktrees.md |
| 核心服务(创建/改动检测/清理) | packages/core/src/services/worktreeService.ts |
| 核心服务单元测试 | packages/core/src/services/worktreeService.test.ts |
| CLI 启动期 worktree 装配 | packages/cli/src/utils/worktreeSetup.ts |
| 配置项定义 | packages/cli/src/config/settingsSchema.ts |
| 命令行参数解析与校验 | packages/cli/src/config/config.ts |
| 退出提示(恢复/清理指令) | packages/cli/src/ui/components/SessionSummaryDisplay.tsx |
| 设置参考 | docs/cli/settings.md |
| 会话管理 | docs/cli/session-management.md |
一句话收束:开关打开后--worktree起跑,退出时照着打印的两条命令恢复或清理——Gemini CLI Git Worktree 的并行会话隔离,就这么简单。
【免费下载链接】awesome-design-systems💅🏻 ⚒ A collection of awesome design systems项目地址: https://gitcode.com/GitHub_Trending/aw/awesome-design-systems
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考