ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

RTK 的 Git/VCS 命令过滤模块:让 git、gh、glab 与 diff 输出对 LLM 友好

RTK 的 Git/VCS 命令过滤模块:让 git、gh、glab 与 diff 输出对 LLM 友好 RTK 的 Git/VCS 命令过滤模块让 git、gh、glab 与 diff 输出对 LLM 友好【免费下载链接】rtkCLI proxy that reduces LLM token consumption by 60-90% on common dev commands. Single Rust binary, zero dependencies项目地址: https://gitcode.com/GitHub_Trending/rtk4/rtk本文以 RTK 仓库中src/cmds/git/模块的模块说明文档为主线拆解该模块如何把git、ghGitHub CLI、glabGitLab CLI以及独立diff的高噪声输出压缩成 LLM 可消费的紧凑形式包括原生 git 参数如何原样透传、git status/git log/git diff的默认压缩策略、退出码如何在 CI/CD 管道中正确传播以及 gh 与 glab 在 JSON 模式上的差异处理。读完本文你可以掌握该模块的过滤链路参数透传 → 捕获 → 压缩 →never_worse兜底 → 退出码回传并能依据源码定位每个压缩行为的具体实现。模块构成与职责划分src/cmds/git/目录由五个 Rust 源文件组成每个文件对应一类命令族见 模块文档 与 src/cmds/git/mod.rs文件职责git.rsgit本体的 14 个子命令过滤diff/log/status/show/add/commit/checkout/push/pull/branch/fetch/stash/worktree 及透传gh_cmd.rsGitHub CLI 的 PR/issue 列表与视图压缩定义 markdown 正文过滤助手glab_cmd.rsGitLab CLI 的 MR/issue/pipeline/release 压缩模式上镜像 gh_cmd.rsgt_cmd.rsgit-town 透传命令diff_cmd.rs独立的双文件超精简 diff与git diff完全独立git.rs 中的GitCommand枚举定义了被过滤的子命令集合pub enum GitCommand { Diff, Log, Status, Show, Add, Commit, Checkout, Push, Pull, Branch, Fetch, Stash { subcommand: OptionString }, Worktree, }未被枚举覆盖的任意 git 子命令走run_passthroughgit.rs#L2236-L2257直接以std::process::Command::status()执行原生 git不捕获输出仅记录跟踪指标。模块文档还明确了三处跨命令共享关系README “Cross-command” 一节gh_cmd.rs从git.rs导入compact_diff()复用 diff 压缩markdown 助手filter_markdown_body、filter_markdown_segment定义在gh_cmd.rs自身glab_cmd.rs同样复用git.rs的compact_diff()处理mr diff其filter_markdown_body目前是从gh_cmd.rs复制而来模块文档注明“shared-module refactor deferred”即共享模块重构被推迟diff_cmd.rs是一个独立实现不依赖git diff。参数透传trailing_var_arg allow_hyphen_values模块文档的第一条要点是git 子命令在 src/main.rs 的 clap 定义中统一使用#[arg(trailing_var_arg true, allow_hyphen_values true)]。全仓库搜索可确认这一属性被 git 的所有子命令变体一致声明如 main.rs#L93 等处大量出现。这两个属性的组合解决了一个典型问题clap 默认会把--oneline、--cached、-sb这类以连字符开头的 token 当作自己的选项解析而报错。allow_hyphen_values允许带连字符的值进入参数列表trailing_var_arg则把子命令之后的所有 token 原封不动地塞进一个变长参数交给过滤层自行解释。这里有一个 clap 的陷阱--分隔符会被trailing_var_arg吃掉。RTK 用 src/core/args_utils.rs 中的restore_double_dash()在运行前把丢失的--重新插回。git.rs 中两处调用并标注了对应 issue// Re-insert -- when claps trailing_var_arg consumed it (issue #1215) let args args_utils::restore_double_dash(args);git log路径的注释更具体地说明了后果不恢复--的话rtk git log -- -p中的-p会被误判为 patch 开关而实际上它只是名为-p的 pathspec。全局 git 选项-C、--git-dir、--work-tree、--no-pager则在子命令之前前置拼接见 git.rs#L38-L44fn git_cmd(global_args: [String]) - Command { let mut cmd resolved_command(git); for arg in global_args { cmd.arg(arg); } cmd }模块文档还提到一个 locale 细节内部解析依赖 git 英文措辞的命令例如从状态输出中识别 rebase/merge 状态行使用LC_ALLC变体git_cmd_c_locale()git.rs#L51-L55而用户可见的输出仍保留其本地 locale。git statusporcelain 紧凑路径与状态保真模块文档说明默认git status使用--porcelain -b保证紧凑输出永远不超过原生git status的体量一个未跟踪目录会折叠为单行与 git 默认行为一致只有“分支/短格式”类参数复用紧凑路径其他显式参数则原样透传。实现上uses_compact_status_path 判定哪些参数允许走紧凑路径fn uses_compact_status_path(args: [String]) - bool { if args.is_empty() { return true; } let mut saw_branch false; for arg in args { match arg.as_str() { -b | --branch saw_branch true, -sb | -bs return true, -s | --short {} _ return false, } } saw_branch }即无参数、或仅带-b/--branch/-sb/-bs/-s/--short组合时build_status_command 注入--porcelain -b任何其它显式参数则整组原样传给 git。紧凑路径run_status随后做三件保真工作porcelain 格式化format_status_inner 把## branch...首行渲染为* branch空仓库输出Clean working tree干净状态追加clean — nothing to commitdetached HEAD 还原porcelain-b会把 detached HEAD 折叠成晦涩的## HEAD (no branch)RTK 从已捕获的 plain 输出中提取HEAD detached at ref行extract_detached_head用真实 ref 覆盖显示进行中状态不丢失--porcelain会省略 rebase/merge/cherry-pick/bisect/am/sparse-checkout 的状态头。源码注释明确说“Hiding that block is a correctness bug”——交互式 rebase 编辑期间用户会误以为工作区干净。extract_state_header 扫描 plain 输出到 “Changes to be committed:” 等停止行之前识别出如rebase in progress、merge in progress. unresolved conflicts等摘要枚举见 GitStatusState并前插到格式化结果之前。走非紧凑路径时用户带了复杂参数则只施加最小过滤 filter_status_with_args去空行、去(use git add ...)类提示行保留其余内容。git diffstat compact_diff 两段式run_diffgit.rs#L112-L216的策略分三条路用户要--stat/--numstat/--shortstat或显式--no-compact→ 直接透传原样打印--no-compact是 RTK 自有 flag执行前被剔除默认路径 → 先跑一次git diff --stat得到变更概览再跑一次git diff得到完整 diff交给compact_diff()压缩后以Changes:段落拼接在 stat 之后任一步失败 → 原样回传 stderr 与退出码。核心压缩函数 compact_diff 是一个逐行状态机规则如下遇到diff --git行刷新上一 hunk 的截断标记输出文件路径取b/后的部分遇到hunk 头完整保留包括第二个后的函数上下文hunk 内的/-行计入该文件的增删计数且每个 hunk 最多展示 100 行max_hunk_lines 100超出的部分累计为... (N lines truncated)上下文行只在 hunk 已开始展示后跟随输出每个文件结束时输出added -removed汇总行整体输出受max_lines默认 500来自调用处max_lines.unwrap_or(500)上限截断时追加提示[full diff: rtk git diff --no-compact]告诉用户/Agent 如何取回全量。该函数被git diff、git show、glab mr diff与git stash show -p四处复用后者上限为 100 行是模块文档中“cross-command 共享”的主要载体。git showrun_show类似地走三步一行 commit 摘要--prettyformat:%h %s (%ar) %an→--stat汇总 → 压缩 diff而git show rev:path这类打印 blob 的调用、或用户自带--stat/--pretty/--format时直接透传避免重复输出。git log格式注入、限额解析与输出整形run_loggit.rs#L428-L531是模块中参数解析最复杂的一条路径原始形态透传若参数中出现会改变输出形态的 flag-p、--stat、--name-status、--numstat等见 requests_raw_diff_shape整组参数走run_passthrough不注入任何 RTK 格式tokenizelog_arg_tokens 把参数切分为 flag 与被消费的 value 两类遇到--即停止其后的 token 是路径而非 flag。consumes_next_token_as_value 列出了--grep、--author、-n等约 40 个“下一 token 是值”的选项——这保证--grep --pretty中的--pretty不会被误认为格式 flag格式注入用户未提供--oneline/--pretty/--format时RTK 注入--prettyformat:%h %s (%ar) %an%n%b%n---END---。源码注释说明保留%bcommit body 首段是为了给 Agent 留下BREAKING CHANGE、Closes #xxx等上下文---END---作为 commit 块分隔符限额用户显式-N/-n N/--max-count(N)时尊重用户值仅给了格式 flag 时默认 50 条什么都没有则默认 10 条并自动追加--no-merges除非用户显式要 merge commit后处理filter_log_output 按---END---切块每块只保留头行 至多 3 行非 trailer 正文剔除Signed-off-by:、Co-authored-by:超长行按 80 字符用户显式限额时为 120 字符注释说明更宽的阈值是保留 rebase/squash 所需的 commit 上下文截断并追加...。写操作族一行式结果与退出码传播模块文档强调“Exit code propagation is critical for CI/CD pipelines”。从源码看所有写操作都遵循同一契约成功 → stdout 输出一行紧凑结果失败 → stderr 回传原生错误并return Ok(result.exit_code)把 git 的退出码原样交给上层。逐个来看git addrun_add无参时补.成功后追加跑git diff --cached --stat --shortstat输出ok 2 files changed, 5 insertions()。源码注释指出无变化的git add必须保持静默镜像 git 自身行为因为若对 Agent 统一打印ok它无法区分“暂存了 N 个文件”和“什么都没暂存”git commitrun_commit用exec_capture_stdin继承 stdin保证交互式编辑器、GPG 口令提示、credential helper 仍能到达终端parse_commit_output 从首行方括号中提取短 hashok abc1234并用find定位括号以避免在 hook 前置输出、多字节字符开头的行上按字节切片导致 panic。失败时通过 CommitOutcome::Failed 回传退出码git pushrun_push这是唯一走流式过滤的子命令——GitPushLineHandler 逐行丢弃Enumerating objects:、Counting objects:、Writing objects:等进度噪声前缀并监听Everything up-to-date与- refs/...行结束后输出ok (up-to-date)或ok origin/branchgit pullrun_pull解析N files changed, X insertions(), Y deletions(-)汇总行输出ok 3 files 10 -2git branchrun_branch按“写操作 flag-d/-D/-m/-M/-c/-u/--set-upstream-to等→ 透传--show-current→ 透传原样 stdout列表模式 → 过滤”三分支。filter_branch_output 把remotes/remote/branch去前缀、去重并把与本地重名的远端分支折叠进remote-only (N):分组超过CAP_WARNINGS上限的以... N more收尾git fetch / stash / worktreefetch 统计 stderr 中-与[new行得到ok fetched (N new refs)stash 对push/save输出ok stashed但把No local changes to save原样透出同样的“no-op 不得伪装成成功”原则见 format_stash_message 注释stash show的 patch 模式复用compact_diffstat 模式用 compact_stash_stat 把 diffstat 压成path N -形式worktree 的add/remove/prune/...透传list则把 home 前缀换成~并规整为path hash [branch]单行。never_worse压缩不得劣化的兜底几乎每条读路径在打印前都套一层never_worse(raw, filtered)来自 src/core/guard.rs如果压缩后的输出反而比原始输出“更长或更差”则回退打印原始输出。例如 run_diff 的收尾let raw format!({}\n{}, result.stdout, diff_result.stdout); let shown never_worse(raw, printed);这保证了模块文档第一条承诺——git status的紧凑输出“never exceeds rawgit status”——在实现层面有硬性约束而非仅靠代码审查。glab 命令族与 gh 的差异适配glab_cmd.rs 的模块头注释与 glab vs gh JSON schema quick-ref 表 给出了同一份事实。glab 输出适配必须遵守的 JSON 模式差异如下表格完整继承自模块文档AspectghglabNotation#42!42StatesOPEN/MERGED/CLOSEDopened/merged/closedAuthorauthor.loginauthor.usernameURL fieldurlweb_urlBody fieldbodydescriptionMerge checkmergeablemerge_status(can_be_merged/cannot_be_merged)CI statusstatusCheckRolluphead_pipeline.statusLabelslabels(array of objects)labels(array of strings)ReviewersreviewRequests/reviewsreviewers(array of objects withusername)源码印证了表中每一项glab_cmd.rs#L1-L12 的文档注释逐条列出state_icon 按小写opened/merged/closed映射[open]/[merged]/[closed]超紧凑模式退化为单字母O/M/Cpipeline_icon 从head_pipeline.status取值非紧凑模式输出文本标签[ok]、[fail]、[cancel]、[run]、[pend]、[skip]——模块文档解释了原因文本标签与gh_cmd.rs保持一致同时避免多字节emoji图标在终端中的渲染怪癖。其余 glab 特有行为均出自模块文档并在源码中可查clap 层全局 flag 追加-R/--repo与-g/--group在 clap 层声明但执行时追加append到 glab 参数末尾而非前置避免破坏 glab 的子命令分发输出 flag 短路has_output_flag()检测到用户显式请求-F/--output/--json时直接透传避免 RTK 再注入一次 JSON 造成双重注入view 短路should_passthrough_view()在mr view/issue view带--web或--comments时转向透传JSON 助手各 JSON 子命令统一走本地run_glab_jsonF()包装runner::run_filtered与RunOptions::stdout_only().early_exit_on_failure().no_trailing_newline()JSON 解析失败时回退打印原始 stdoutglab 在空结果时可能输出纯文本ci status 关键词解析glab 该子命令不支持-F json因此用英文状态关键词解析文本输出若未识别到任何英文状态词非英文 locale原样返回 raw 输出不做猜测ci trace 纯文本过滤ANSI 剥离 GitLab section 标记过滤 runner/git/artifact 样板行剔除保持文本过滤而非转 JSON。源码中对应两条正则SECTION_MARKER_RE 匹配section_start/end:timestamp:name及裸的[0K序列release list 双格式兼容优先按 glab 1.82 的新格式解析不匹配时回退到旧的制表符分隔解析再不行则回退 raw。markdown 正文过滤filter_markdown_body按代码围栏 或 ~~~切段围栏内原样保留围栏外经 filter_markdown_segment 剔除 HTML 注释、badge 行、纯图片行、水平分割线并把连续 3 个以上空行折叠为一个。独立 diff 命令与 git diff 无关的超精简比较模块文档指出diff_cmd.rs是“standalone ultra-condensed diff (separate fromgit diff)”。diff_cmd.rs 的run(file1, file2)直接读两个文件做行级比较输出file1 → file2、N added, -M removed, ~K modified汇总和仅含变更行的明细行号/-行号/~行号 old → new并遵守 diff 惯例退出码相同为 0不同为 1render_diff。另有 run_stdin 从管道读取 unified diff 并压缩同样套never_worse兜底。小结一个可验证的设计模式把模块文档的要点与源码对照后可以归纳出该模块统一遵循的四层模式透传优先任何“用户已显式改变输出形态”的信号--stat、--pretty、-F json、--web、未枚举的 git 子命令都让位于原样透传压缩只发生在默认形态上有损压缩 逃生门compact_diff的 hunk 级截断、filter_log_output的 body 行上限、filter_branch_output的 remote-only 上限全部伴随可执行的恢复提示如[full diff: rtk git diff --no-compact]、... N more正确性护栏never_worse保证输出不劣化、LC_ALLC内部解析与用户 locale 分离、detached HEAD 与 rebase 状态头主动还原、no-op 不伪装成功、退出码全程传播跨命令复用compact_diff与 markdown 过滤助手在 git/gh/glab 间共享glab 侧以一张 JSON schema 差异表约束适配面。如需进一步深入建议按 模块文档 → git.rs 的过滤实现 → glab_cmd.rs 的适配实现 的顺序对照阅读git.rs 文件尾部内置的#[cfg(test)] mod tests自 git.rs#L2259 起覆盖了git_cmd全局参数拼接、log 参数 tokenize、限额解析等关键分支的单测可直接作为行为规格的参考。【免费下载链接】rtkCLI proxy that reduces LLM token consumption by 60-90% on common dev commands. Single Rust binary, zero dependencies项目地址: https://gitcode.com/GitHub_Trending/rtk4/rtk创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表