首页
/ graphify GitHub 仓库克隆与跨仓库图谱合并指南:clone、逐仓 extract 与 merge-graphs 全流程实战

graphify GitHub 仓库克隆与跨仓库图谱合并指南:clone、逐仓 extract 与 merge-graphs 全流程实战

2026-09-07 22:25:00作者:平淮齐Percy

本篇指南讲解 graphify 处理多代码源的核心工作流:当用户抛出一个或多个 https://github.com/... 地址,或点名要合并的多个本地子目录时,如何借助 graphify clone、逐仓抽取与 graphify merge-graphs,把彼此独立的仓库/服务折叠进同一张可查询知识图谱。读完你将掌握 graphify 的克隆缓存复用机制、graphify-out/ 输出目录约定、合并时节点前缀与 repo 归属的底层逻辑,以及合并完成后跳过重复抽取直接查询的"快速路径"用法。

本文内容主体源自仓库中由 skillgen 生成的技能参考文档 github-and-merge.md(其源片段位于 tools/skillgen/fragments/references/shared/github-and-merge.md,同一内容会被物化到 agents、amp、claude、codex、kiro、vscode 等各平台技能目录下),并结合 graphify 的 CLI 源码与测试做了实现级扩充。

什么时候用到这份指南

以下两类请求出现时,就进入了"GitHub 克隆 / 跨仓库合并"场景,应加载这份流程:

  • 用户传入了一个或多个 GitHub 仓库 URLhttps://github.com/...),期望针对这些外部仓库建图;
  • 用户点名了多个本地子目录(monorepo 的多个模块、多服务代码库等),期望合并为一张图。

无论哪种情况,最终产物都是同一个:在某个根位置生成一份 graphify-out/graph.json,让后续所有代码问题直接命中它,无需重复抽取。

先理解输出约定:graphify-out/ 与"快速路径"

graphify 的整套流水线(检测 → AST 抽取 → 语义抽取 → 合并 → 建图 → 聚类 → 落盘)会产出 graph.json 与各类辅助文件,统一存放在名为 graphify-out/ 的目录里。关键差异在于这个目录落在哪里

  • 技能(skill)流水线:把全部中间与最终产物写到当前工作目录下的 graphify-out/。因此在同一工作目录下对多个子目录分别运行技能,会互相覆盖同一个输出目录——这正是多子目录场景必须改走 CLI 的原因;
  • CLI 直接抽取graphify extract <path> 默认把 graphify-out/ 建在被扫描路径内部。源码中的约定写得非常明确:"The user-facing contract is <out>/graphify-out/",未显式传 --out 时输出根即目标路径本身(cli.py),因此 graphify extract ./core/ 产出的就是 ./core/graphify-out/graph.json

一旦 graphify-out/graph.json 存在,"快速路径"即刻接管:后续任何代码库问题直接以 graphify query 查询该图即可——不再重复抽取、不再受图规模门禁约束(这也是 always_on/agents-md.md 中给 Agent 的固定指引:graph.json 在则先 graphify query)。

Step 0 —— 克隆 GitHub 仓库(仅当拿到 GitHub URL 时)

单仓库克隆

LOCAL_PATH=$(graphify clone <github-url> [--branch <branch>])
# 之后所有步骤都以 LOCAL_PATH 作为目标路径

graphify clone 会做两件重要的事:把仓库克隆到本地缓存目录,并把最终路径打印到标准输出(因此可以直接用命令替换 $(...) 捕获)。如果只想复制裸命令形态,等价写法为:

graphify clone https://github.com/owner/repo

多仓库克隆(跨仓库图谱的前置)

# 逐仓克隆,每仓分别跑完整流水线,最后再合并
graphify clone <url1>   # → ~/.graphify/repos/<owner1>/<repo1>
graphify clone <url2>   # → ~/.graphify/repos/<owner2>/<repo2>
# 在每个本地路径上运行 /graphify,得到各自的 graph.json
# 然后合并:
graphify merge-graphs \
  ~/.graphify/repos/<owner1>/<repo1>/graphify-out/graph.json \
  ~/.graphify/repos/<owner2>/<repo2>/graphify-out/graph.json \
  --out graphify-out/cross-repo-graph.json

缓存目录与重复运行复用(源码级细节)

默认克隆位置是 ~/.graphify/repos/<owner>/<repo>,实现位于 cli.py_clone_repo

  • URL 规整:自动去掉末尾 /.git 后缀,统一补成 <url>.git 交给 git;只有匹配 github.com[:/]<owner>/<repo> 形态的 URL 才会被接受,否则报 error: not a recognised GitHub URL 并退出;
  • 重复运行复用:目标目录已存在时不再全量克隆,而是执行 git -C <dest> pull 拉取最新(配合 --branch 时拉取指定分支)。所以对同一 URL 反复执行 clone 是廉价的增量更新,而非重新下载整个仓库。首次克隆使用 git clone --depth 1(浅克隆,只取最新快照),兼顾速度与体积;
  • 分支安全校验--branch 值若以 - 开头会被判定非法并中止,避免分支名被误解析为 git 选项;
  • --out <dir>:可选自定义目标目录,跳过默认缓存位置;默认仍以 ~/ 下的缓存为准。

clone 命令的 CLI 入口在 cli.py,其用法即 graphify clone <github-url> [--branch <branch>] [--out <dir>],克隆完成后打印仓库路径(失败时非零退出)。

克隆参数速查

参数 含义 默认值 说明
<github-url> 待克隆的 GitHub 仓库地址 必填 须匹配 github.com[:/]owner/repo,自动容忍 .git 后缀
--branch <b> 指定拉取的分支 仓库默认分支 首次克隆时以 --branch 传 git;复用缓存时执行 git pull origin -- <b>;以 - 开头会报错
--out <dir> 自定义克隆目标 ~/.graphify/repos/<owner>/<repo> 显式给出后不再写入默认缓存目录

多仓库 / 多子目录:先逐仓建图,再统一合并

多仓库(跨仓库图)总览

对克隆下来的每个仓库,先分别产出各自的 graph.json,再把它们喂给 merge-graphsmerge-graphs 产出的合并图里,每个节点都带有一个 repo 属性,用于标识它来自哪个源仓库,方便后续按来源过滤。

本地多子目录:避开 skill 的输出目录冲突

monorepo 或多服务布局(例如根下有 core/service/platform/)是最容易踩坑的场景:如第一节所述,技能流水线把输出写进当前工作目录graphify-out/,若对每个子目录分别跑一次技能,会反复覆写同一个输出目录。正确做法是用 CLI 直接对每个子目录抽取,让每个子目录得到自己内部的 graphify-out/

graphify extract ./core/     # → ./core/graphify-out/graph.json
graphify extract ./service/  # → ./service/graphify-out/graph.json
graphify extract ./platform/ # → ./platform/graphify-out/graph.json
# 依据你配置了哪个 API Key 追加 --backend gemini|kimi|openai|deepseek|claude-cli

# 然后在项目根上合并:
graphify merge-graphs \
  ./core/graphify-out/graph.json \
  ./service/graphify-out/graph.json \
  ./platform/graphify-out/graph.json \
  --out graphify-out/graph.json

graphify extract:无头全流水线抽取

extract 是面向 CI/脚本的"一次到位"命令,内部依次执行检测 → 代码 AST 抽取 → 文档/PDF/图片的语义抽取 → 合并 → 建图 → 聚类并写出全部产物(cli.py)。这与走 Claude Code 子代理的技能路径不同:它直接调用并行抽取实现,使用当前已配置 API Key 的后端。

其完整用法(cli.py):

graphify extract <path> [--backend gemini|kimi|claude|openai|deepseek|ollama]
                     [--model M] [--mode deep] [--out DIR|--output DIR]
                     [--google-workspace] [--no-cluster] [--no-gitignore]
                     [--code-only] [--no-dedup] [--max-workers N]
                     [--token-budget N] [--max-concurrency N]
                     [--api-timeout S] [--postgres DSN] [--cargo]
                     [--allow-partial] [--timing]
参数 作用
--backend <name> 选择语义抽取的后端,按你已配置密钥/环境的供应商填写。graphify 的 LLM 后端注册表中至少包含 kimigeminiopenaideepseekclaude-cli(另处理 ollama/azure/bedrock),见 llm.pyllm.py;其中 claude-cli 走本机 Claude CLI,不依赖远程密钥
--out DIR / --output DIR 输出目录;不传则把 graphify-out/ 建在被扫描路径内部
--code-only 只跑代码 AST 通道,跳过语义抽取
--no-dedup 关闭实体去重(配合增量合并与建图收缩保护)
--no-cluster / --no-gitignore 跳过聚类 / 不读取 gitignore
--max-workers / --max-concurrency / --token-budget 性能与预算旋钮,缺省用库默认值
--google-workspace / --postgres DSN / --cargo 接入 Google Workspace 文档、Postgres 元数据、Cargo 工程内省等附加语料源

合并图谱:graphify merge-graphs 的语义与源码内幕

命令形态与默认输出

graphify merge-graphs <graph1.json> <graph2.json> [...] [--out merged.json]

--out 缺省为 graphify-out/merged-graph.json;需要至少两个输入图,否则打印用法并退出;任一输入路径不存在即报错中止(cli.py)。合并前每个输入文件都会经过 _enforce_graph_size_cap_or_exit 容量门禁校验(cli.py),与 query 等命令共用同一规模保护,避免无保护的超大图被装载。成功后会打印汇总:Merged N graphs -> X nodes, Y edges,并用原子写落盘(cli.py)。

输入兼容性:图的类型归一

逐仓生成的 graph.json 可能来自不同抽取路径、不同时刻,因此在 directed / multigraph 标志上未必一致。merge-graphs 会把每个输入归一为无向简单图nx.Graph)再组合——混合 DiGraph / MultiGraph / MultiDiGraph 输入不再触发 NetworkX 的 compose 崩溃。归一逻辑见 cli.py,并由 tests/test_merge_graphs_cli.py 中的 test_merge_graphs_mixed_directed_and_multigraph 专门覆盖。同时,旧版本可能把边写成 edges 键(新版是 links),读取时会做键名兼容;每条边的真实方向通过 _src/_tgt 标记保留,避免无向重载丢失方向(cli.py)。

节点前缀与 repo 标签:为什么必须"打标签"

合并的核心机制在 build.pyprefix_graph_for_global:每个输入图的节点 ID 都会被重写为 repo_tag::<原始ID>,同时:

  • 展示用 label 保持不变,便于阅读;
  • 每个节点新增 local_id 记录原始 ID,可以无损还原;
  • 每个节点被标记 repo = repo_tag,这正是文档所说"按来源过滤"的数据基础;
  • 边及 _src/_tgt 方向标记同步重写到带前缀的新 ID;
  • 图外挂的超边(hyperedges)成员 ID 与超边自身 ID 也会套用同一前缀映射表,避免跨仓库合并后超边悬空或同名碰撞;
  • 聚类 community 整型 ID 通过 community_offset 平移进共享编号空间,原划分保留在 local_community,防止两个仓库各自的 0 号社区在合并后被错误融合成一个元节点。

repo_tagbuild.pydistinct_repo_tags 生成:它不能简单取 graphify-out/ 的父目录名——src/graphify-outfrontend/src/graphify-out 会撞成同一个 src,同干同名节点(两个仓库里的 app)就会被 nx.compose 静默合并,制造出根本不存在的跨运行时调用。因此算法会先把撞名标签用其上层目录加宽(如 frontend_src),再以序号后缀兜底,保证每个输入图拥有唯一前缀。

跨仓库共享类型的打通:same_type_as

前缀策略保证了节点不串仓,代价是"同一个契约类型"在两个仓库里会以两个互不相连的节点出现——而消息总线代码里,恰好这段关系才是最有价值的跳转:生产者在一个仓库引用 SyncProductUpsertToSearchEvent,消费者在另一个仓库实现 IConsumer<SyncProductUpsertToSearchEvent>。为此 cross_repo_types.pylink_shared_type_declarations 会为命名空间与名称都相同、且来自不同仓库的类型声明节点之间补一条 same_type_as 边(关系上下文记为 cross_repo)。要求命名空间一致是为了只匹配"真正同声明"的类型,而不是撞了短名的两个无关类——源注释记录的真实案例中,两个 .NET 服务的 1440/262 个类型经此规则只命中 7 对,全部是共享的 EventManager.Models.*Event 契约。需要强调的是该阶段只加边、不合并节点:两个仓库持有的契约副本可能已经各自漂移,保留独立节点才不会掩盖分叉。合并入口会在 compose 完成后执行该步骤并打印 linked N type declaration(s) shared across reposcli.py)。

边与超边的完整性

每个输入图的超边会先被收集、随节点一起前缀化并去重,最后统一回挂到合并图上(避免 nx.compose 只保留最后一个输入超边列表的旧缺陷,见 cli.py);写盘时 hyperedges 同时写入 node_link_data 嵌套的 graph 槽与顶层槽,确保新旧读取方一致。

合并之后的"快速路径":直接查询

一旦根位置的 graphify-out/graph.json 就位(无论来自单仓库抽取还是上面的多图合并),后续代码问题就走快速路径——直接 graphify query 查询合并图,不再重新抽取、不再受规模门禁约束。技能侧的具体做法(如 references/query.md 所述)是:先检查 graphify-out/graph.json 是否存在,存在则直接读取并跑图遍历,而不是先跑一遍抽取。

由于合并图中的每个节点都带 repo 归属,跨仓库查询天然可以回答"这个符号分别在哪些仓库里出现""两个服务共享了哪些契约类型""一次跨仓库调用链长什么样"这类单一仓库图答不了的问题。

配套验证与延伸阅读

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

项目优选

收起
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++
915
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