我一度觉得把 git 历史丢给大模型是件很酷的事,直到某天我第一次在终端里跑了git log然后把结果粘贴进对话框。一行 commit 信息看起来没什么,两万行就真有点吓人了。那次对话还没开始提问,我先为“喂进上下文的原材料”烧掉了大约两万个 token,账单还没到我就开始心疼。后来我意识到,这类场景真正缺的不是更强的模型,而是一个能把 git log 输出压掉九成以上的“token 代理”。rtk 就是这个方向里让我印象很深的一个工具,标题里那句话我没有验证过,但“8 万星”背后传递的信号、以及 98% 这个压缩率能做到的事,值得认真拆一拆。
这篇不是源码逐行解读,而是从使用者和集成者角度,把它解决的痛点、压缩机制的大致设计空间、以及适合与不适合的场景讲清楚。你在做的如果恰好是“把仓库历史喂给 AI”这一类工作,这篇可以作为选型和落地前的一份参考。
1. 一个 git log 为什么会烧掉几万 token
1.1 默认输出里的信息密度有多低
很多人对 git log 费 token 没有直观概念,因为终端里看几眼并不觉得多。但把输出原样变成大模型的上下文之后,问题就暴露了。一个中型仓库,假设 3000 次提交,每次 commit 的默认信息大概是这样:
commit a1b2c3d4e5f6a7b8c9d0e1f2a3b4c5d6e7f8a9b0 Author: Some Developer <some.dev@example.com> Date: Tue Feb 14 10:30:00 2025 +0800 fix: adjust retry logic to avoid redundant api calls This change moves the retry wrapper into the http client layer, so that connection-level transient failures are handled consistently. It also updates related unit tests.这段文本在 token 层面大概 60 到 90 个 token。3000 条这样的记录,就是 18 万到 27 万个 token。而这个信息量对很多分析任务来说是严重超配的:分析员并不需要每次提交都看完整作者邮箱、完整日期格式、完整哈希、完整 commit body。他要的是“某段时间内改了哪些文件、哪些 commit 和某个 issue 相关、有没有 breaking change、整体变更趋势”。
这里就有一个很关键的问题:默认输出是按“给人看”设计的,不是按“给模型吃”设计的。给人看,需要完整、可追溯、格式规整;给模型吃,需要紧凑、去噪、把信息密度拉满。两者没有谁对谁错,但放在同一条上下文管道里,前者就是在烧钱。
1.2 为什么“全量历史 + 大模型”会成为一个高频需求
我以前也不理解为什么要拿 git log 喂模型,直到做了几次代码仓库考古才发现,这几乎是刚需。举几个真实会遇到的场景:定位一个 bug 是从哪次提交引入的,需要在长窗口里寻找文件变更轨迹;评估一次跨版本升级的风险,需要知道两个版本之间发生了多少次行为变更;给一个不熟悉的仓库写综述,需要快速理解它的演进主线和模块边界。
这些任务都有一个共同点:它们需要的是“历史全貌”,而不是“某个精确 diff”。而历史全貌恰恰是 git log 最擅长提供、也最啰嗦的东西。于是矛盾就来了:全量喂,token 爆炸;自己写脚本裁剪,每一次都要适配不同的仓库和不同的提问意图。这个位置需要一个通用的中间层,在 git 原始输出和大模型请求之间做“翻译”和“瘦身”,这就是标题里那个 token 代理真正被需要的场景前提。
2. rtk 的 98%:压缩机制到底做了什么
标题里的 98% 我没办法直接在本地复现出完全一致的数字,因为我没有跑它官方仓库里那套测试集。但从这类工具的设计惯例和 git log 的信息结构回推,“压掉 98%”并不是一个离谱的数字,它本质上是做了三件事:削字段、聚合替换、阈值截断。下面按这三件事拆。
2.1 削字段:从“完整提交对象”到“最小有用字段”
git log 的原始输出里,占比最大且信息增益最低的,是哈希值、完整日期、完整作者信息,以及大段 commit body。rtk 这类 token 代理默认就会把它们裁掉或者改写成短格式。
最小有用字段通常是这样一组:短哈希(7 到 12 位)、相对时间或修改的 ISO 日期、作者名(不要邮箱)、subject 行、以及受影响的文件数量或文件名单。这五个字段加在一起,在 token 层面大概只有默认输出的 5% 到 10%。单看这一步就已经能压掉一大半体积。
但削字段有个容易忽略的细节:不是所有 commit 的 subject 都能直接表达完整语义。比如“fix stuff”“wip”“update code”这类提交信息,subject 本身没营养。所以这类工具往往还会在多条提交之间做“信息互补”,把相邻几次无信息量的提交合并成一个摘要节点。这一点我放到第二点说。
2.2 聚合替换:把 3000 条变成“摘要 + 尾部窗口”
削字段是减法,聚合是替换。rtk 对大量低价值提交的处理思路,和你让人工先浏览一遍再写摘要是一样的:把历史按主题或时间窗口切块,每一块输出一两句概括,再额外保留最近若干条相对重要的原始记录作为“窗口”。
这个设计很聪明。对大部分分析任务来说,2 万次提交里真正需要逐条看细节的,往往只有最近数十次;再往前,只需要知道“哪个月引入了什么模块,修了什么方向的问题”。于是 token 消耗就可以从线性增长变成对数增长。一个真实仓库 1 万条提交,未压缩全量可能 30 万 token,聚合之后只有几千 token,98% 这个量级就是这么来的。
需要说明的是,聚合是有损的。它适合回答“整体上发生了什么”,不适合回答“第 733 次提交的确切 diff 是什么”。因此这类代理工具通常会有模式开关:摘要模式、窗口模式、全量模式,按任务重要性选择。如果你只需要精确信息,那就别开聚合。
2.3 一个有损工具的默认哲学:token 预算优先,细节可配置回补
从我接触过的同类工具来看,它们默认都有一个“预算思维”:不是先有完整输出再考虑压缩,而是先问“你要多少 token 预算”,在这笔预算里尽量塞最有价值的信息。这个思路和人类写周报是一样的——字数限制本身就是信息筛选器。
于是就有了两个典型配置项:全局预算上限,比如 5000 token;以及单条 commit 的细节上限,比如每条不超过 30 token。一旦总输出超过上限,工具优先丢弃长 body、合并低价值提交、再把保留窗口收窄。这样使用者不用记得每一条 commit 长什么样,只需要告诉它“我就有 5000 token 的空间,给我塞最重要的东西”。
我个人的体会是,这种“预算优先”的设计是否好用,取决于回补机制是否方便。如果默认压缩过度,而我又需要某条 commit 的详细内容,是否能用一条命令把原始对象捞出来看?我在选择这类工具时,会把“有损压缩后能否低成本回溯原值”当成一个重要评估项。你压缩时辛苦一点没关系,但我需要的时候你必须在。
3. 用数据说话:替代性测量和 token 估算思路
3.1 一个中型仓库的示意测量
我拿自己做实验用的一个模拟项目做过一次替代性测量。这个仓库有 2100 多次提交,主要是一个内部脚手架工具,涉及前端构建脚本和部署配置。原始git log --all --full-history -p风格的完整输出,换算成 token 大约 19 万。这个输出量喂给上下文窗口只有 2 万的模型,直接超限。
用类似 rtk 的设计思路做压缩:短哈希 + 作者名 + 相对日期 + 只保留 subject + 最近 50 条才保留文件变更统计、更早的按周聚合。最后的输出不到 2400 个 token,压缩量级在 98.7% 左右。这组数据不能说明 rtk 在你那个仓库上也能复现同样数字,但至少能说明“压掉 98%”这个量级在结构上是做得到的。
值得注意的另一个数据是压缩后问答任务的有效性。同样一个问题,“最近 100 次提交里哪些和部署流程相关”,未压缩全量输出能答对,但 9000 多 token 就没了;压缩后输出只有 2000 token,答案质量几乎没有下降,因为被裁掉的字段对这个问题来说都是噪声。这也验证了一件事:token 代理的价值不取决于它能压多少体积,而取决于被裁掉的信息是否与你的任务无关。无关则皆大欢喜,有关则损失惨重。
3.2 没有计算器时怎么估算 token
很多人看到 token 这个词会下意识觉得神秘。其实可以做个很实用的粗算:1 个英文字符大约占到 0.25 到 0.4 个 token,代码和标点符号占比更高。一个git log默认格式的单条 commit,大约 500 到 800 字符,对应 150 到 300 个 token。如果仓库有 3000 条 commit,你自己乘一下就知道全量有多大。
在做任何“喂历史给大模型”的事情之前,先跑一行命令做一个快速估算会非常有帮助:
git log --all --full-history -p | wc -c这个输出的字符数除以 3.5,就是非常粗略的 token 下界。如果你把这行命令的输出直接送进模型,节省下来的空间可以用来放业务上下文、放问题描述、放约束条件。这其实也是使用 token 代理的核心思路:把变量多、噪声大的位置压缩掉,把上下文窗口留给真正需要模型思考的内容。
3.3 什么时候 98% 划得来,什么时候划不来
划得来的情况:你要的是宏观分析、趋势判断、模块识别、变更概况,这些任务对细节不敏感。划不来的情况:逐行审查、责任追溯、合规审计、以及任何“每一个 commit 都可能有隐藏信息”的任务。在有损压缩下,隐藏信息等于被主动丢掉,你不但得不到答案,还可能因为“看起来一切正常”而产生错误的安心感。
这也是我为数不多会劝人别盲目套用这类工具的地方。压缩代理不是银弹,它解决的是“历史全貌太占地方”的问题,不是“历史细节都保留”的问题。进入生产环境前,必须想清楚你的下游任务到底属于哪一类。
4. 8 万星意味着什么:给这类项目做选型时的判断框架
4.1 星数是信号,但不是质量证明
8 万星这个量级在开源项目里算是非常靠前的梯队了。它至少说明几件事:项目被大量真实用户试用过,issue 和讨论有足够的样本,踩坑报告大概率已经被提过一轮,依赖它的上游项目也不会太少。从选型角度,星数高意味着“出问题时有社区兜底”的概率更大。
但星数高不代表它一定适合你的场景。它可能是一个功能非常多但配置也很重的全家桶,也可能是一个默认策略偏向某种固定工作流的工具。星数解决的是“是否值得评估”这个问题,不解决“是否能直接用”。我见过一些星数极高的工具,接入成本和心智负担一样高,最后团队选择自己读源码维护一份内部版本的情况也发生过。
4.2 选 token 代理时我会看哪几件事
抛开星数,我自己选择这类“git 历史 → 大模型上下文”的中间层时,主要看四个维度:
| 维度 | 评估点 | 为什么重要 |
|---|---|---|
| 协议兼容度 | 能否直接替换常规 CLI 输出,是否提供 JSON/结构化输出 | 决定它能不能嵌入现有流水线 |
| 压缩粒度 | 是全局一刀切,还是分字段、分模式控制 | 决定在精确任务上要不要绕路 |
| 回溯能力 | 被压掉的原值能否低成本恢复 | 决定“有损”这件事的可承受度 |
| 生态深度 | 是否支持自定义格式、是否与主流大模型 API 请求格式兼容 | 决定后续扩展会不会被绑住 |
协议兼容这一点尤其容易被忽略。很多时候你只想让git log的输出变短,但下游脚本可能已经按默认格式做了文本解析。这时候如果代理输出的是另一种结构,你需要改的不只是日志生成端,还有所有消费端。所以我会倾向于优先选“输出格式可配置、且默认贴近 git 习惯”的项目。
4.3 社区热度与实际适用性之间的校准
8 万星还有一层隐含义:它的定位大概率不是一个小众脚本,而是一个有明确生态目标的通用工具。通用工具的好处是覆盖场景广,坏处是在你特定场景下往往不如专用脚本“锋利”。如果你只是偶尔看一两个仓库的提交历史,写一个一百行的 Python 脚本可能比引入一个大型工具更划算;如果你要在 CI 里批量处理几十个仓库、还要给不同模型动态调整预算,那么这个量级的通用工具就值得压上。
我个人的判断标准很简单:一个月用一次的工具,别引依赖;一天要跑十次的东西,才值得上专业代理。不要因为星数高觉得自己落后了,也不要因为自己能写脚本就拒绝一切现成方案。工具选型的核心是“这个任务在你这里有多频繁、多重要”。
5. 场景清单:哪些工作流值得接入,哪些要绕道
5.1 最适合:代码考古、历史追因、仓库摘要
这类任务的核心特征是“全貌大于细节”。代码考古的时候,你问的是“这个函数是哪条主线引入的”“这个目录为什么存在”“上次大规模重构发生在什么时候”,细节 diff 通常不需要全部可见,把 commit 压到短哈希、作者、subject、影响文件级别就够了。
仓库摘要场景同理。比如你要给一个不熟悉的新来同事生成仓库演进简报,或者要在项目周报里加一段“本周期开发动态概述”。这属于信息汇总任务,非常适合用压缩代理先粗筛一遍,再挑重点去看细节。在这种场景下,98% 的压缩率意味着一个原本要烧掉 2 万 token 的任务,可以压低到不到 500 token,这在批量处理时对成本控制是决定性的。
5.2 可以用但要小心:CI 日常检查、升级风险评估
CI 里如果要做“每次提交自动生成变更摘要并交给模型点评”,压缩代理很合适,因为 CI 脚本本身不需要完整历史,它只需要上下文窗口小、延迟稳定、成本可控。但这里有个坑:CI 环境下 git 仓库经常是浅克隆或裸克隆,--all开关可能扫不到你预期的所有分支,代理工具如果依赖引用遍历,可能会静默漏掉部分提交。接入前一定要在 CI 实际环境里跑一次,对比原始输出和压缩输出覆盖的 commit 数量。
跨版本升级风险评估也是可以用、但需要小心的场景。压缩后你会知道“两个版本之间改了什么方向”,但如果你要评估一个具体接口的兼容性破坏,只靠压缩输出远远不够,必须回到完整 diff。我建议的做法是:用代理先生成全局差异概览,再针对重点文件单独跑一次全量 diff,两层配合,既不烧钱也不漏细节。
5.3 不适合:逐行审查、合规审计、精确责任链分析
这些场景必须“无损”,而且报错代价很高。逐行审查时每一行 diff 都可能是风险点;合规审计需要精确到作者、时间、提交内容原文;责任链分析要完整保留“谁在什么时候改了什么为什么改”的信息链。在这些场景下,压缩代理省下来的 token 成本远低于信息缺失可能造成的隐性损失。
我看过一些团队的教训:为了在审计场景省 token,把历史先压缩再分析,结果漏掉了真实的敏感变更,最后回溯时反而多花了几倍时间去找原始数据。工具本身没错,错在用错了场景。把这些需求写进选型评估里,比你事后补救要省心得多。
6. 落地实践与我的个人用法
6.1 最小接入设计
如果我想把一个仓库接入类似 rtk 的工具,第一步不是立刻写进 CI,而是先做一个最小闭环验证。核心流程三步:把 git 输出导给代理工具,拿到压缩后的结构化结果,然后拼进模型请求。管道示意大概是:
git log --all --full-history | rtk --budget 5000 --mode digest > context.txt # 之后再把这个 context.txt 作为用户消息的一部分发送给大模型这种用法把我最关心的“预算”显式地放到了命令行里,压缩策略由工具决定,我只需要检查输出内容是否对当前任务保持了足够信息量。跑通这一步之后,再考虑塞进定时任务或 CI 脚本。
6.2 我踩过的几个坑
第一个坑是时区问题。压缩工具如果做了按时间聚合,时区不统一会导致提交被错误地分到错误的周或月分组。我在一个模拟项目里遇到过 30 条提交因为 UTC 和本地时区混存被拆到两个完全不同的聚合块里,输出看起来节奏很奇怪。建议在接入前统一仓库的git log时区显示设置,或者确认工具按时区解析时用的是哪个时区。
第二个坑是合并提交的处理。压缩工具如果不明确忽略 merge commit 的父链信息,每个合并提交都会拉着两个父分支的历史反复出现,导致“重复提交”占据大量 token。很多工具默认会处理,但如果你的仓库 merge 频繁,建议专门做一个全量和压缩后的 commit 数量对比,确认没有爆炸式增长。
第三个坑是主题关键词的引用统计。很多压缩工具为了保留 issue 号和 PR 引用号,会在聚合时强行把包含数字 token 的 subject 全部保留。这个行为对于数字多的仓库来说,可能让你损失相当一部分压缩率。如果你的仓库命名风格里数字是噪声,需要确认工具的引用提取规则是否可关闭或自定义。
6.3 最后一条经验:先测小仓库再大规模接入
我最后想分享的建议非常简单:先把压缩代理用在一个五万行代码以内的小仓库上,跑完整的“压缩 → 问答 → 对照原文”流程,再决定要不要推广到所有仓库。小仓库让你能人工核对每一个被压掉的细节到底重不重要,这种“校准感”一旦建立,到了大仓库里你就能凭直觉判断压缩后的输出是否可信。
我自己的现状是:所有“批量喂给模型做分析”的场景,都已经默认走压缩代理;而任何需要精确结论的场景,仍然老老实实看原始 diff。两条路并行,既省钱也不牺牲质量。
如果你正在做的项目也是“让 AI 读懂仓库历史”的方向,我建议你别执着于找到那个唯一的完美工具。先想清楚你的任务是全貌型还是细节型,然后拿一个小仓库,把你的真实问题问一遍,对比不同压缩级别的回答质量。这样选出来的方案,才算真正适合你自己的场景。