Skip to content

Pinned Search and Reads ​

Source Graph answers each request at exactly one Git commit. It first turns the requested revision into a commit inside the repository's retention window, then searches the index or reads Git at that commit, and returns the commit with the result so the caller can keep using it. This page explains how revisions resolve, how versions are kept and indexed, what bounds a search or read, and why the approach is faster than running rg over a checkout.

mermaid
sequenceDiagram
  participant A as Agent
  participant S as Source Graph
  participant Z as Zoekt index
  participant G as Git mirror
  A->>S: search(repo, pattern) — no revision
  S->>S: resolve default branch to commit C
  S->>Z: generated query at C
  Z-->>S: bounded hits
  S-->>A: hits + Commit C + Partial / Truncated / Coverage
  A->>S: read(repo, revision C, path, lines)
  S->>G: blob at C
  S-->>A: numbered lines + Commit C + next range

How a revision resolves ​

Every operation accepts an optional revision and resolves it with the same rules:

You passSource Graph uses
NothingThe repository's discovered default branch when the policy follows it; otherwise the single configured main or master branch, at its last synchronized head
A monitored branch nameThat branch's last synchronized head
A full 40-character lowercase commit SHAThat commit, if it is inside the retention window
A short SHA, a tag, HEAD or another refRejected (SHORT_SHA_UNSUPPORTED, INVALID_REVISION)
An unmonitored branchRejected (BRANCH_NOT_MONITORED)

A commit outside the window returns REVISION_NOT_ELIGIBLE rather than a nearby substitute. Source Graph never silently replaces a requested baseline with another commit, so a caller that pins the returned commit gets the same snapshot on every later call.

Which versions exist ​

Each repository has a retention policy: one to eight monitored branches (optionally including the remote's default branch) and a window defined either by days (1–365) or by count (1–4096 first-parent commits per branch). Background synchronization fetches only the monitored branches — never tags — on the repository's sync interval, records each branch head and builds the set of eligible versions from the window. Many versions of one repository can therefore coexist.

Indexing is separate from eligibility. After a successful sync, the service queues an index job for each branch head that is not yet indexed, and stops retrying a head after three failures. Older commits in the window stay readable from Git but are searchable only after someone with permission asks for them with prepare; searching an unindexed commit returns INDEX_NOT_READY. Each index is stored as a separate generation, and generations no longer referenced by any retained version are removed in the background, at most one per collection pass.

Callers never send engine syntax. A search is a set of structured, rg-like fields — a line-oriented regular expression or literal, case folding, globs and directory paths — that the service compiles into an engine query at the resolved commit. The Query Syntax reference lists every field.

Results are a bounded first page. The first attempt returns up to 100 files and 1,000 matches with two lines of context; if the response would exceed its 2 MiB budget, the service retries with smaller pages and finally a file-only listing, all within a five-second deadline. The response metadata tells the caller what it got:

  • Commit and Repository identify the snapshot.
  • Partial means the engine stopped early, for example at its 10,000-match cap.
  • Truncated means more files or matches existed than were displayed.
  • Coverage describes what was indexed — text only, no symbol index, the registered paths and groups — so a zero-hit result is not proof that something is absent from the repository.

What bounds a read ​

A read returns an inclusive line range of one file at one commit, at most 500 lines and 256 KiB per call; when no range is given over MCP it starts at line 1 and covers up to 500 lines. The response says which lines were returned and where to continue, and flags truncation, binary content, unsupported encodings and Git LFS pointers instead of guessing.

In a full-repository registration, reads go straight to Git and do not wait for indexing. In a monorepo registration, the path group must already be prepared at that commit (CONTENT_NOT_READY otherwise). read_many reads one to ten known ranges at one commit in a single MCP call, sharing a budget of 1,000 lines, 256 KiB and 30 seconds; each item reports its own content and error.

Why it is faster than a checkout ​

rg and git grep scan files on every call; the trigram index does that work once per commit. The project's README reports this comparison against the public demo repository (context4ai/context, 2,359 indexed files) and a local checkout of the same commit:

QuerySource Graph (server)rg (local)git grep (local)grep -r (local)
Literal, 13 matching files0.7–0.9 ms61 ms——
Literal, ~100+ matching files3.6–5.2 ms61 ms39 ms3.6 s
Regex, no matches0.4 ms62 ms——

Server time is the search duration the engine reports. The local tools ran on an Apple M4 Pro with a warm page cache. Add the network round trip — a few milliseconds within one region — for end-to-end latency. The gap widens as repositories grow, and the service also removes the need to check out every repository at the right revision.

Speed depends on locality: each instance keeps its Git mirrors and indexes on its own disk, so deploy instances in the same region as the Agents that call them. How Context's own measurements compare answering with and without Source Graph is covered in Knowledge Retrieval.

固定版本的搜索与阅读 ​

Source Graph 对每个请求都只在一个确定的 Git 提交上作答。它先把请求的版本转换为仓库保留窗口内的一个提交,然后在该提交上搜索索引或读取 Git,并把这个提交随结果一起返回,方便调用方继续使用。本页说明版本如何解析、版本如何保留和建索引、搜索和读取受哪些限制,以及为什么这种方式比在检出目录上运行 rg 更快。

mermaid
sequenceDiagram
  participant A as Agent
  participant S as Source Graph
  participant Z as Zoekt 索引
  participant G as Git 镜像
  A->>S: search(repo, pattern),不指定版本
  S->>S: 将默认分支解析为提交 C
  S->>Z: 在 C 上执行生成的查询
  Z-->>S: 有上限的命中结果
  S-->>A: 命中结果 + Commit C + Partial / Truncated / Coverage
  A->>S: read(repo, revision C, path, lines)
  S->>G: C 上的 blob
  S-->>A: 带行号的内容 + Commit C + 下一段范围

版本如何解析 ​

每个操作都接受一个可选的版本参数,并按相同规则解析:

你传入Source Graph 使用
不传若保留策略跟随默认分支,则使用发现到的仓库默认分支;否则使用唯一配置的 main 或 master 分支,取其最近一次同步的最新提交
一个监控分支名该分支最近一次同步的最新提交
一个 40 位小写的完整提交 SHA该提交,前提是它在保留窗口内
短 SHA、标签、HEAD 或其他引用拒绝(SHORT_SHA_UNSUPPORTED、INVALID_REVISION)
未被监控的分支拒绝(BRANCH_NOT_MONITORED)

窗口之外的提交会返回 REVISION_NOT_ELIGIBLE,而不是用相近的提交代替。Source Graph 从不悄悄把请求的基线替换成另一个提交,因此调用方只要固定使用返回的提交,之后每次调用拿到的都是同一个快照。

有哪些版本 ​

每个仓库都有一个保留策略:一到八个监控分支(可选包含远端的默认分支),以及一个按天数(1–365)或按数量(每个分支 1–4096 个第一父提交)定义的窗口。后台同步按仓库的同步间隔只拉取监控分支——从不拉取标签——记录每个分支的最新提交,并根据窗口构建符合条件的版本集合。因此,同一仓库的多个版本可以并存。

建索引与版本是否符合条件相互独立。同步成功后,服务会为每个尚未建索引的分支最新提交排入一个索引任务;同一个最新提交失败三次后不再重试。窗口内较早的提交仍可从 Git 读取,但只有在有权限的人通过 prepare 请求后才能被搜索;搜索未建索引的提交会返回 INDEX_NOT_READY。每份索引都作为独立的一代(generation)存储,不再被任何保留版本引用的代会在后台删除,每轮回收最多删除一代。

搜索受哪些限制 ​

调用方从不发送引擎语法。一次搜索是一组结构化、类似 rg 的字段——按行匹配的正则表达式或字面量、大小写折叠、glob 和目录路径——由服务在解析出的提交上编译为引擎查询。搜索语法参考文档列出了所有字段。

结果是有上限的第一页。第一次尝试最多返回 100 个文件和 1,000 个匹配,并附带两行上下文;如果响应会超出 2 MiB 的预算,服务会改用更小的页重试,最后退化为只列文件,整个过程都在五秒期限内完成。响应元数据会告诉调用方拿到了什么:

  • Commit 和 Repository 标识快照。
  • Partial 表示引擎提前停止,例如达到其 10,000 个匹配的上限。
  • Truncated 表示实际存在的文件或匹配多于显示的数量。
  • Coverage 描述索引了哪些内容——仅文本、没有符号索引、已登记的路径和路径组——因此零命中并不能证明仓库中不存在某样东西。

读取受哪些限制 ​

read 返回某个提交上一个文件的闭区间行范围,每次调用最多 500 行、256 KiB;通过 MCP 调用且未指定范围时,从第 1 行开始,最多覆盖 500 行。响应会说明返回了哪些行以及从哪里继续,并明确标出截断、二进制内容、不支持的编码和 Git LFS 指针,而不是靠猜测处理。

在全量仓库登记下,读取直接访问 Git,无需等待建索引。在 Monorepo 登记下,该路径组必须已在该提交上准备好(否则返回 CONTENT_NOT_READY)。read_many 在一次 MCP 调用中读取同一提交上一到十个已知范围,共享 1,000 行、256 KiB 和 30 秒的预算;每一项分别报告自己的内容和错误。

为什么比检出目录更快 ​

rg 和 git grep 每次调用都要扫描文件;三元组索引则对每个提交只做一次这项工作。项目 README 给出了在公开演示仓库(context4ai/context,2,359 个已索引文件)与同一提交的本地检出目录上的对比:

查询Source Graph(服务端)rg(本地)git grep(本地)grep -r(本地)
字面量,13 个匹配文件0.7–0.9 ms61 ms——
字面量,约 100+ 个匹配文件3.6–5.2 ms61 ms39 ms3.6 s
正则,无匹配0.4 ms62 ms——

服务端时间是引擎报告的搜索耗时。本地工具运行在 Apple M4 Pro 上,页缓存已预热。端到端延迟还需加上网络往返——同一地域内为几毫秒。仓库越大,差距越明显;而且该服务还省去了把每个仓库按正确版本检出的需要。

速度取决于本地性:每个实例都把自己的 Git 镜像和索引保存在自己的磁盘上,因此应把实例部署在与调用它的 Agent 相同的地域。Context 自己关于使用与不使用 Source Graph 作答的对比测量,见知识检索。