深入解读 VS Code 内置 merge 技能:让 Agent 安全地把会话分支合并回基准分支
导读
在 VS Code 的 Agent 会话(Sessions / Agents Window)机制中,AI Agent 常常在独立的"主题分支(topic branch)"上完成一次会话的开发工作,最终需要把这些成果合并回代表项目主干状态的"基准分支(merge base branch)"。仓库内置的 merge 技能说明 就是为这一场景量身定制的可执行工作流:它定义了 Agent 从"检查并提交未暂存改动"、"跨工作树执行合并"到"冲突裁决与结果校验"的完整操作协议,同时以明确的红线条款约束 Agent 绝不擅自强推、跳过钩子或改写提交历史。读完本文,你将掌握这套内置于 VS Code 会话体系中的 merge 技能的设计意图、完整命令流程、冲突处理约定,以及如何在 Agent 提示词工程中复用它保证合并操作安全可控。
SKILL.md 是什么:会话体系中可执行的工作流
在 src/vs/sessions 这一实现了 Agents Window 的源码目录下,skills/*/SKILL.md 是一类非常特殊的文件。根据 vs/sessions 的 README 中的说明,这些 skills/*/SKILL.md 文件是"可执行的产品工作流(executable product workflows)",它们并不属于架构设计文档,而是被直接喂给会话 Agent、指导其完成某个具体任务的指令模板。
merge 技能就是这套工作流家族中的一员。当前仓库中与其并列的兄弟技能还包括:
- commit/SKILL.md:把工作树改动以符合仓库惯例的提交信息提交;
- sync/SKILL.md:让当前会话分支与上游分支同步或发布新分支;
- create-pr/SKILL.md:为当前会话的改动创建 Pull Request;
- 以及
code-review、fix-ci、update-pr、sync-upstream、troubleshoot等其它同名目录。
从文件结构看(skills 目录),每个工作流都以同名目录 + SKILL.md 的形式组织,目录名即技能名。merge 技能目录 merge/SKILL.md 的文件本体十分精炼,包含 YAML front-matter、一段行为覆盖注释、Guidelines(准则)与 Workflow(工作流)四大部分,下面逐一展开。
front-matter:技能的"可被调起"声明
与 VS Code 会话体系中的其它技能一致,merge 技能的文档开头是一段 YAML front-matter:
name: merge
description: Merge changes from the topic branch to the merge base branch. Use when the user wants to merge their session's work back to the base branch.
name: merge声明技能标识,Agent 上下文中的斜杠命令(如/commit、/merge)通常即按此名称索引。description承担"何时调用本技能"的语义描述:当用户希望把会话的工作成果合并回基准分支时使用。它同时界定了本技能的操作对象——**topic branch(当前工作树中检出的主题分支)**与 merge base branch(主工作树中检出的基准分支)。
行为覆盖注释:内置技能如何被个性化
文件第 5 行有一段对运维实践非常关键的注释:
Customize this skill and select save to override its behavior. Delete that copy to restore the built-in behavior.
其含义是:这份 SKILL.md 是"内置(built-in)"版本。用户可以在界面中把该技能另存为自定义副本以覆盖默认行为;删除自定义副本后,将恢复使用这份内置行为。这一"内置可覆盖、删除即还原"的机制与 AI_CUSTOMIZATIONS.md 中描述的 AI 定制化管理模型相互呼应——在该架构说明中,skills、instructions、prompts 等定制项可在 workspace、user、extension、built-in 等不同来源间发现与覆盖,而"过滤只影响呈现、不修改底层定制项"的管线原则同样适用于 merge 技能。
Guidelines:合并操作不可逾越的红线
技能开头先用四条加粗的准则(Guidelines)圈定 Agent 的安全边界,任何后续工作流步骤都不得突破:
- 未经用户明确批准,绝不强推(force-push),明确点名
--force、--force-with-lease均在禁止之列; - 绝不跳过 pre-push 钩子,即不得使用
--no-verify; - 未经用户询问,绝不改写或丢弃提交(rewrite or drop commits);
- 对冲突如何解决没有把握时,询问用户。
从源码结构看,这些红线并非 merge 独有。对比 commit/SKILL.md 中的"绝不 amend 既有提交"、"绝不未经批准 force-push / push"、"绝不跳过 pre-commit / 签名钩子",以及 sync/SKILL.md 中同样禁止 force-push、禁止 --no-verify、禁止擅自改写提交的条款,可以推断:"不擅自强推、不绕过钩子、不丢提交、存疑即询问"是这套会话工作流的通用安全宪法。它们共同保证 Agent 的 git 操作对用户完全透明、可中止、可回退。
工作流全景:从提交未暂存改动到干净地合并
merge 技能把整个合并任务拆为"提交现场 → 合并 → 解决冲突 → 校验"四个环节,全程通过 git -C <main-worktree-path> 把命令定向到主工作树,而 Agent 自身停留在当前(会话)工作树中,这正体现了会话机制的分支/工作树模型。
第 1 步:先提交当前工作树的未暂存改动
合并的前提是当前工作树"干净"。因此第一步先做检查:
git status --porcelain
- 若输出为空,说明当前工作树干净,可直接进入合并;
- 若存在未提交改动,则应先调用
/commit技能(即 commit/SKILL.md 定义的工作流)将其提交,再继续合并。
这一"先提交、后合并"的顺序非常重要:话题分支上的工作成果只有先固化为提交,后续才能被合并、被 merge-base --is-ancestor 校验;同时避免把未完成的半成品带入合并结果。
第 2 步:把 topic 分支合并进主工作树的基准分支
合并动作指向的是主工作树中检出的基准分支,因此技能特意强调使用 git -C 而非切换目录——-C <path> 会让 git 把指定路径当作工作目录来执行命令,而 Agent 不需要离开当前工作树、也不改变会话上下文:
git -C <main-worktree-path> merge <topic-branch>
需要说明的是,<main-worktree-path> 与 <topic-branch> 是占位符:技能正文明确写道"追加到提示词中的上下文块(context block)包含源分支、目标分支以及主工作树路径",即这两个取值由会话环境在运行时注入 Agent 的 prompt 中,技能本身只定义抽象步骤。从整体设计推断,这一"分支隔离在不同工作树 + 上下文注入分支信息"的模型,正是为了让多个 Agent 会话可在互不干扰的工作树中并行开发,最终统一汇入基准分支。
第 3 步:冲突处理四部曲
若第 2 步的 merge 报告冲突,按以下顺序处理:
3.1. 列出冲突文件,利用 diff-filter=U(Unmerged)只筛选处于"未合并"状态的文件:
git -C <main-worktree-path> diff --name-only --diff-filter=U
3.2. 逐一读取冲突文件内容,以"保留双方意图(preserving the intent of both sides)"为原则手动解决冲突,并将已解决文件暂存:
git -C <main-worktree-path> add <resolved-file>
3.3. 存疑即问,可整体中止。当无法确定如何解决某个冲突时,必须向用户征询指引;若用户希望放弃本次合并,则执行:
git -C <main-worktree-path> merge --abort
merge --abort 会把仓库恢复到合并开始前的状态,是技能为"用户反悔/Agent 陷入僵局"预留的明确逃生通道。
3.4. 全部解决并暂存后,以默认信息提交合并。--no-edit 表示直接采用 git 自动生成的合并提交信息而不打开编辑器——这是无交互 Agent 场景下的必要选项:
git -C <main-worktree-path> commit --no-edit
校验:合并真的完成了吗
合并提交完成后,不能直接宣告成功,必须执行两条显式校验:
- 确认主工作树干净:
git -C <main-worktree-path> status --porcelain
- 确认 topic 分支已是基准分支 HEAD 的祖先——即 topic 上所有提交都确实进入了基准分支:
git -C <main-worktree-path> merge-base --is-ancestor <topic-branch> HEAD
其中第二条命令的语义值得展开:git merge-base --is-ancestor A B 在 A 是 B 的祖先时返回退出码 0(真),否则返回非 0。因此该命令相当于一条程序化的包含性断言——只有当返回值表明 <topic-branch> 的全部提交都已并入 HEAD(基准分支)时,合并才算真正闭环。这种"用 git 自身的图论关系做校验、而非仅凭肉眼看过文件"的验证手法,与 sync/SKILL.md 结尾用 git rev-list --left-right --count HEAD...@{u} 校验 ahead/behind 均为 0 的做法如出一辙,可以推断**"显式命令 + 退出码断言"是本套工作流标准的结果验证范式**。
与兄弟技能的协作关系:一条完整的分支生命周期
把 merge 技能放入它周围的技能网络中,可以还原出 Agent 处理一次会话改动的完整生命周期(均为仓库内真实存在的技能目录,可对照查看原文):
| 阶段 | 技能 | 对应 SKILL.md |
|---|---|---|
| 收尾未提交改动 | /commit |
commit/SKILL.md |
| 与上游同步 / 发布分支 | /sync |
sync/SKILL.md |
| 将会话成果合并回基准分支 | /merge(本文主题) |
merge/SKILL.md |
| 把会话改动对外提交为 PR | /create-pr |
create-pr/SKILL.md |
值得注意的是,merge 技能第 1 步明确委托 /commit 技能,而 create-pr/SKILL.md 的第 2 步同样写着"若存在未提交改动,先用 /commit 技能提交"。这说明技能之间以明确的委托关系互相组合:commit 是一切下游 git 操作的公共前置依赖。merge 则承接 commit 之后、create-pr 发布之前的"并入主干"环节——当用户希望把会话成果合并回基准分支时触发;若用户希望以 PR 形式把改动对外发布,则由 create-pr 接手。这份依赖设计使每个技能保持单薄、聚焦、可独立验证,符合 vs/sessions README 对"可执行产品工作流"的定位。
实际使用中的适用前提与限制
综合技能正文与仓库证据,使用 merge 技能需要注意以下前提,它们也是该技能适用边界的事实说明:
- 面向双工作树/多分支模型:技能假设当前(会话)工作树检出了 topic branch、主工作树检出了 merge base branch。如果仓库实际并未使用
git worktree拆分的多工作树布局,则<main-worktree-path>与当前路径指向同一仓库,命令仍然成立,但"隔离合并现场"的设计收益会减弱。 - 依赖运行时注入上下文:源分支、目标分支、主工作树路径均来自追加进 prompt 的 context block,而非技能文件内置。也就是说,技能只规定"做什么与按什么顺序做",实际参数由会话运行时提供。
- 冲突解决依赖 Agent 判断力:"保留双方意图"是原则而非算法,最终是否冲突收敛依赖 Agent 对代码上下文的理解;技能为不确定场景预留的标准动作是询问用户或
merge --abort整体放弃。 - 红线不可突破:即便某个环节看似需要强推或绕过钩子才能推进,Guidelines 也已预先封死这些选项——唯一的合法出口是向用户申请明确批准。
若内置行为不完全符合你的团队约定(例如希望默认采用 --no-ff 合并或更严格的校验),可按照该文件开头的注释说明,将技能另存为自定义副本后按需改写;删除自定义副本即可恢复本仓库这份内置的默认行为。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0627
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00