首页 / 课程 / D12 深挖
Part 3: 扩展集成 · 第 24 讲

24 讲路线 · 与 S12 配对

D12: Git Integration 深挖 · Git 集成

本讲在 S12 主线之上,聚焦实现细节、边界条件与自测;导图与主线相同模块,便于对照。

建议:先读完 S12,再按下方顺序走读源码与练习。

📌 S 与 D 的分工(为何答案在 D12?)

S 线(如 S12):讲清楚「是什么、典型流程、配置长什么样」,篇幅尽量短,一般不铺长篇标答,避免主线臃肿。

D 线(如本页):同一主题的深挖 + 边界 + 自测参考答案刻意放在这里——你可以先闭卷想,再展开下文对照。这不是「S 只出题、D 只给答案」的硬性协议,而是本站的排版约定S 轻、D 重

不建议去掉 D 里的答案:去掉后 D 与 S 的差异被抹平,深挖页失去「对答案」这一用途;若你希望某讲在 S 侧多一句提示,更合适的是像 S12 那样链到对应的 D,而不是删掉 D 的解析。

模块导图(与 S12 同源,便于对照):diff/merge 策略与自动化边界

🔬 深挖目标

Git 集成是「自动化刀锋」:何时只读、何时写索引、何时提交、冲突由谁解决。本讲对齐宿主命令与 git 状态机,避免静默破坏仓库。

🌳 操作分级

级别示例权限建议
只读status、diff、log可默认 auto
索引变更add、restoreask 或项目策略
历史改写commit --amend、push --force强确认 + 日志

🔀 合并与冲突

  • 模型生成 patch 与 git 冲突 marker 同时出现时,优先让人类看清「三方」。
  • 自动化 merge 失败必须非零退出并把冲突路径喂回上下文。
  • 与 D09:IDE buffer 未保存 vs git checkout 冲突检测。

📖 走读顺序

  1. 搜索 git 封装层(spawn 包装),列出所有子命令白名单。
  2. 确认是否过滤 --forceupdate-ref 等高危参数。
  3. 走读一次「自动 commit」:默认 message 规则、是否 GPG、是否 hook。

✏️ 自测 1 · 参考答案:git commit 放行、git push 禁止

题干

设计策略:允许模型 git commit 但禁止 git push,在权限层如何实现?

思路概览

权限函数(如 canUseTool)必须在真正 spawn 之前看到结构化或可解析的调用意图。实现上有三条常见路线,可叠加:

  1. 专用 Git 工具:不把「任意 shell」暴露给模型,而是 git 工具参数里带 subcommand(或等价枚举)。策略表:commit / add / status → auto 或 ask;pushfetch、含 remote 的网络写 → 一律 deny 或未开放该枚举值。
  2. Bash 工具 + 命令解析:若仍走通用 Bash,必须在权限层对整行命令做 token 化(注意引号、git -C pathenv GIT_DIR=…):识别首个 git 子命令;pushpush --forceremote set-url 等命中高危规则 → deny;commit 在允许列表 → 继续走工作区与路径校验。
  3. PreToolUse Hook(辅助):对 Bash 的 command 字符串做二次审计(正则 / 小型解析器),命中 git push 返回 deny 或 blockingError。Hook 不能替代权限门,只做纵深防御。

务必兜住的坑

  • git -C ../outside-repo push:除子命令外还要校验 -C 与当前工作目录是否落在允许的工作区根内。
  • git 的别名、脚本包装:alias gp=git push —— 若无法静态解析,应对「未列入白名单的任意 git 调用」默认 ask/deny。
  • gh pr create 等间接 push:若策略是「禁止出网写远程」,需在网络类工具另表约束,与 git 子命令策略合并考虑
// 权限层伪代码:仅示意「在 spawn 之前」如何分支
function gitPolicyFromArgv(argv: string[]): 'allow' | 'deny' | 'ask' {
  // 1. 归一化:去掉 env 赋值、取到 git 与其子命令(需真实解析器,勿只靠 split)
  const sub = extractGitSubcommand(argv) // e.g. 'commit' | 'push' | null
  if (sub === 'push') return 'deny'
  if (sub === 'commit') return 'allow' // 还可再检查 -C、文件路径
  return 'ask'
}

✏️ 自测(题干回顾)

  • commit 放行、push 禁止如何实现?→ 自测 1
  • .git 在外或 symlink?→ 自测 2