首页
/ VS Code Sessions /update-pr 技能解析:内置 PR 同步技能的完整工作流与源码实现

VS Code Sessions /update-pr 技能解析:内置 PR 同步技能的完整工作流与源码实现

2026-09-07 14:42:23作者:庞眉杨Will

在 VS Code 的 Sessions(Agents Window)子系统中,update-pr 是一个内置的 agent 技能(skill):当用户希望在已有的 Pull Request 上推送新的会话改动时,它定义了从"拉取上游变更、跑编译与卫生检查、提交、刷新 PR 标题描述"到"最终推送更新 PR"的完整五步工作流。读完本文,你将掌握 /update-pr 技能的逐步执行逻辑、它在 Changes 工具栏中的触发链路(源码级)、以及内置技能如何被覆盖定制与恢复的机制,并理解它与 create-prmergecommit 等技能共同构成的 PR 生命周期闭环。

update-pr 技能文件结构与定位

技能定义位于 src/vs/sessions/skills/update-pr/SKILL.md,与仓库内其它内置技能(create-prcreate-draft-prmergesyncfix-cicommit 等)并列存放在 src/vs/sessions/skills/ 目录下。文件由两部分组成:

YAML frontmatter——技能的身份与触发描述:

---
name: update-pr
description: Update the pull request for the current session. Use when the user wants to push new changes to an existing PR.
---
  • name 字段即斜杠命令名(/update-pr),按照同目录 update-skills 技能中给出的约定,name 必须与技能所在目录名完全一致;
  • description 是 agent 判断"何时该用这个技能"的唯一依据,这里明确限定了使用场景:当前会话已存在一个 PR,用户想把新改动推上去

正文——技能的行为说明:

Update the existing pull request for the current session. The context block appended to the prompt contains the pull request information.

正文点明了一个关键前提:执行上下文由平台自动注入。当技能被触发时,提示词末尾会附加一个 context block,其中携带当前会话对应的 PR 信息(PR 归属、分支等),agent 无需自行探查"这是哪个 PR",可直接围绕该 PR 执行后续步骤。

此外,文件头部的 HTML 注释声明了定制机制:

<!-- Customize this skill and select save to override its behavior. Delete that copy to restore the built-in behavior. -->

即:该技能是可覆盖的内置技能——把副本保存出去即可改写其行为,删除副本即恢复内置行为(详见后文"内置技能的定制与恢复"一节)。

核心工作流:五步同步 PR

技能正文定义了严格有序的五步流程。下面完整继承原文档的步骤,并结合其引用的相邻技能对每一步做深入说明。

第 1 步:拉取 PR 上的"外来"变更并解决冲突

Check whether the pull request has any commits that are not yet present on the current branch (incoming changes). If there are any incoming changes, pull them into the current branch and resolve any merge conflicts

这一步对应"远端有别人(或 CI bot、协作者)推到这个 PR 分支上的提交,而本地当前分支还没有"的场景。处理策略是:先检出/拉取这些 incoming changes 到当前分支,若有 merge conflict 则解决后再继续。之所以必须先做这一步,是因为若不先同步远端,后续的 push 可能被拒绝,或覆盖他人的提交。

仓库中另一个内置技能 sync 给出了与"分支与上游对齐"直接相关的标准 Git 手法,可作为理解本步的参照:

# 判断 ahead/behind 数量(0 ahead, 0 behind 即已同步)
git rev-list --left-right --count HEAD...@{u}

# 落后时 rebase 到上游跟踪分支
git rebase @{u}

# 冲突解决后继续 rebase
git add <resolved-files>
git rebase --continue

/sync 技能同时确立了贯穿整个 PR 技能族的安全红线update-pr 隐含遵循同一基调):未经用户明确批准绝不 --force / --force-with-lease、绝不使用 --no-verify 跳过 hooks、冲突拿不准时询问用户、必要时 git rebase --abort 回退。

第 2 步:运行编译与卫生检查并修复错误

Run the compile and hygiene tasks (fixing any errors)

在推送之前,agent 必须在本地把编译(compile)与仓库既定的 hygiene 任务(lint、格式化、类型检查等)跑通,并修复暴露出的任何错误。这一步保证推到 PR 上的提交不会直接打红 CI。这一要求与同目录的 fix-ci 技能形成互补:/fix-ci 针对的是已经跑完并失败的 CI 检查(读取检查名称、结论、annotations 与输出,定位根因后修复);而 update-pr 第 2 步是推送前的本地预防性验证

第 3 步:存在未提交改动时用 /commit 技能提交

If there are any uncommitted changes, use the /commit skill to commit them

这里体现了技能之间的组合调用设计:update-pr 不自己实现提交逻辑,而是委托 commit 技能处理。/commit 技能自身是一套完整的提交规程:

  1. 发现仓库提交约定git log --oneline -20 采样仓库风格、git log --oneline --author="$(git config user.name)" -10 采样个人风格,生成的提交信息必须遵循检测到的约定(Conventional Commits、ticket 前缀、自由格式等);
  2. 检查状态git status --short——有暂存改动只提交暂存的,只有未暂存改动则 git add -A 全部暂存;
  3. 基于 diff 生成提交信息git diff --cached --statgit diff --cached,主题行不超过 72 字符,仅在 diff 非平凡时写 body,聚焦变更意图而非逐文件罗列;
  4. 执行并确认git commit -m "<subject>" -m "<body>" 后用 git status --shortgit log --oneline -1 验证;hooks 若改写文件或拦截提交,只做汇报不自动 amend。

/commit 还设定了硬性禁令:不擅自 amend 既有提交、不跳过 pre-commit hooks(禁用 --no-verify)、不跳过签名(禁用 --no-gpg-sign)、不 revert/reset 用户改动、发现疑似密钥或生成产物先询问用户。这意味着 update-pr 推送到 PR 的每一个提交都经过了"符合仓库风格 + 通过 hooks"的双重把关。

第 4 步:改动重大时更新 PR 标题与描述

If the outgoing changes introduce significant changes to the pull request, update the pull request title and description to reflect those changes

这步的"重大性"判断由 agent 依据 outgoing changes 的内容做出。标题与描述的写作规范可从同族的 create-pr 技能中获得一致标准:

  • 标题要求清晰、简洁,并带短小的 area 前缀(如 "sessions: …""editor: …")——update-pr 场景下若改动仍属同一 area,可沿用前缀,若改动重心漂移则应修正;
  • 描述应覆盖 what changed、why、以及 reviewers 需要知道的事项

第 5 步:以新提交与信息更新 PR

Update the pull request with the new commits and information

收尾步骤:把第 1~3 步产生的新提交推送到 PR 对应分支,并应用第 4 步可能的标题/描述更新。至此,本地分支与远端 PR 重新收敛为一致状态(ahead/behind 归零),进入等待 CI 与评审的阶段。

源码印证:Changes 工具栏按钮如何触发 /update-pr

技能文本只是"剧本",真正把它接入产品的是 Sessions 子系统的 UI 集成。从源码结构看,agent-host 会话的 Changes 视图工具栏由 agentHostSkillButtons.ts 注册,其中 update-pr 按钮的定义为:

{
    id: `${AGENT_HOST_SKILL_BUTTON_ID_PREFIX}updatePR`,        // workbench.action.agentSessions.runSkill.updatePR
    title: localize2('agentSessions.runSkill.updatePR', "Sync Pull Request"),
    skill: 'update-pr',
    icon: Codicon.repoPush,
    group: 'pull_request',
    order: 1,
    extraWhen: ContextKeyExpr.and(
        ContextKeyExpr.false(),
        ActiveSessionContextKeys.IsolationMode.isEqualTo(IsolationMode.Worktree),
        ActiveSessionContextKeys.HasGitHubRemote,
        ActiveSessionContextKeys.HasPullRequest,
        ActiveSessionContextKeys.HasOpenPullRequest,
        ContextKeyExpr.or(
            ActiveSessionContextKeys.HasIncomingChanges,
            ActiveSessionContextKeys.HasOutgoingChanges,
            ActiveSessionContextKeys.HasUncommittedChanges,
        ),
    ),
},

从中可以确认几个产品层面的事实:

  1. 按钮标题为 "Sync Pull Request",图标为 repoPush,排在 Changes 工具栏的 pull_request 组第一位,与 create-pr("Create PR")、create-draft-pr("Create Draft PR")、merge("Merge Changes")四枚技能按钮并列;
  2. 可见条件严格对应技能的使用前提:处于 Sessions 窗口、活动会话是 agent-host 会话、存在 Git 仓库、隔离模式为 Worktree、存在 GitHub 远端、且会话已有一个打开状态的 PR,并且三者至少满足其一——有 incoming 变更、有 outgoing 变更、有未提交改动。这与 SKILL.md 中"description: Use when the user wants to push new changes to an existing PR" 的触发语义完全吻合:没有 PR 时按钮不出现(此时应走 create-pr 路径),没有任何可推送的东西时按钮也不出现
  3. 触发方式是发送斜杠命令:按钮的 run() 逻辑从活动会话的 resource scheme 推导出 agent id,然后向 chat service 发送 prompt = "/update-pr",并等待 responseCompletePromise 完成。也就是说,点击工具栏按钮与用户手输 /update-pr 走的是同一条链路,技能正文中提到的 "context block appended to the prompt" 正是这条链路附加会话/PR 上下文的地方;
  4. 徽标复用:源码注释说明 update-pr 按钮会套用与 Copilot CLI 扩展 Sync PR 按钮相同的"outgoing 变更数量"徽标样式(AGENT_HOST_SKILL_BUTTON_UPDATE_PR_ID 导出即为此供 Changes 视图识别),用户在 PR 分支上有几个待推送提交会直接显示在按钮上。

另外,aiCustomizationWorkspaceService.ts 中的 _skillUIIntegrations 映射表把 update-pr 与 UI 集成点显式登记为:"Used by the Update Pull Request button in the Changes toolbar"。该表在 AI 定制管理界面中向用户解释每个内置技能"被哪个按钮使用",帮助使用者理解为什么不该随意删除这些技能。

技能如何进入每个 agent-host 会话

agentHostSkillButtons.ts 顶部的模块注释说明:这些按钮驱动的技能"通过 synced customization bundler 收集带 BUILTIN_STORAGE 标记的 PromptsType.skill 条目,捆绑进每一个 agent-host 会话"。换言之,src/vs/sessions/skills/ 下的 SKILL.md 文件是内置技能的唯一事实来源,随产品构建打包;运行时由定制捆绑器注入会话,斜杠命令补全(如 agentHost 的 skill completion provider 测试所覆盖的 file:///skills/<name>/SKILL.md 形式条目)与工具栏按钮都基于同一份技能清单。

内置技能的定制与恢复

SKILL.md 头部的定制注释对应 Sessions 的 AI 定制机制(可参考 AI_CUSTOMIZATIONS.md 与技能目录约定 update-skills/SKILL.md):

  • 覆盖:将 update-pr 技能副本保存(Copy and save)到可定制位置后,副本取代内置行为生效。项目级/agent 级技能的约定存放路径为 .github/skills/{name}/SKILL.md.agents/skills/{name}/SKILL.md,副本 frontmatter 的 name 必须与目录名一致;
  • 恢复:删除该副本即恢复内置行为——因为内置技能始终随产品存在,副本只是"影子覆盖"。

update-pr 而言,合理的定制方向是:调整第 4 步的"重大改动"判定标准、改用团队惯用的 PR 描述模板,或在第 2 步加入仓库特有的校验命令。定制时建议保留原文五步骨架,仅替换具体细节,避免破坏第 1 步(同步 incoming)与第 3 步(经 /commit 提交)带来的正确性保证。

与其他内置技能的协作关系

update-pr 不是孤立命令,而是 Sessions 内置 PR 生命周期技能族中的一环。从 skills 目录 的技能清单与各 SKILL.md 的 description 可以梳理出完整闭环:

技能 阶段 职责(摘自对应 SKILL.md)
create-pr PR 诞生 会话首次建 PR:跑编译/hygiene → /commit 提交 → 撰写带 area 前缀的标题与描述 → 优先用 GitHub MCP server、否则用 gh CLI 建 PR(show_ui=false
update-pr(本文) PR 存续 已有 PR 上的增量推送:同步 incoming → 本地验证 → 提交 → 刷新标题描述 → 推送
create-draft-pr PR 诞生(草稿) 创建 draft 形态的 PR
merge PR 之后 把 worktree 中的 topic 分支合回主 worktree 的 merge base 分支,用 git -C <main-worktree> 跨 worktree 操作并验证 merge-base --is-ancestor
sync 分支对齐 拉取/发布会话分支:fetch → ahead/behind 计数 → rebase → push,含完整验证步骤
fix-ci PR 存续 针对已失败的 CI 检查定位根因并修复,对应 Changes 工具栏的 "Fix Checks" 按钮
commit 横切 上述多个技能共用的提交子流程

其中 mergecreate-pr 的技能文本同样提到"context block":merge 的 context block 携带 source 分支、target 分支与主 worktree 路径。这与 update-pr 的"context block 携带 PR 信息"是同一种机制——平台在提示词中注入该技能所需的全部环境事实,让技能文本本身保持简短、稳定、可移植。

从安全设计看,整个技能族共享一组不变式:推送/强推需用户显式批准、hooks 不可跳过、冲突解决拿不准就问用户、每次工作流结束都有显式的验证命令(如 git status --porcelaingit rev-list --left-right --count)。update-pr 的第 1 步(先收 incoming 再推 outgoing)正是这些不变式在"双向有差异"场景下的具体落实。

参考与延伸阅读

适用前提说明:以上技能均属于 Sessions/Agents Window 的 agent-host 会话内置技能,按钮可见性以仓库存在 GitHub 远端、会话处于 worktree 隔离模式且已有打开的 PR 为前提;技能的实际执行由所选 agent 依据 SKILL.md 文本完成,因此覆盖定制副本后行为以副本为准。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.13 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
897
5.8 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
529
593
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
916
1.83 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.58 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.35 K
1.46 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.01 K
515
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
547
388