Rerun 项目 Git 钩子完整指南:从安装 pre-push 到 fast-lint 自动检查
2026/9/17 20:06:56 网站建设 项目流程

Rerun 项目 Git 钩子完整指南:从安装 pre-push 到 fast-lint 自动检查

【免费下载链接】rerunVisualize, query, and stream to train on multimodal robotics data.项目地址: https://gitcode.com/GitHub_Trending/re/rerun

本文以 Rerun 仓库的 hooks/README.md 为骨架,系统讲解该项目官方 Git 钩子(githooks)的设计思路、两种安装方式、以及pre-push钩子从 Git 触发到pixi run fast-lint的完整执行链路。读完本文,你将掌握如何在本地开发环境中快速启用 Rerun 的提交前检查,理解钩子脚本的薄壳转发(shim)架构,并能够按需跳过或定制 fast-lint 的检查项,在推送代码前拦截低质量问题、节省 CI 时间。

一、hooks 目录是什么:官方钩子与薄壳设计

Rerun 仓库在根目录下维护了一个名为hooks的目录,其中存放的是官方 githooks(见 hooks/README.md)。与直接在每个钩子文件里写满逻辑的做法不同,这里的每个钩子都被设计为转发器(shim):它只负责定位仓库根目录,然后通过exec把控制权转交给scripts目录中对应的托管脚本:

  • pre-push→ scripts/pre-push.sh

当前仓库实际只提供了一个pre-push钩子,它对应的是 scripts/pre-push.sh 这个管理脚本。这种"钩子文件 = 薄壳、真实逻辑 = 脚本"的结构有以下好处:

  • 钩子本身保持极短,便于复制到.git/hooks目录后与仓库后续更新解耦;
  • 真实逻辑放在版本控制下的scripts目录中,升级检查规则时只需更新脚本,无需重新安装钩子;
  • 脚本可以借助仓库内的 Pixi 环境来固定依赖与工具版本。

这一设计在 CONTRIBUTING.md 的 "Hooks" 一节中也被推荐给所有贡献者:在推送之前始终运行pixi run fast-lint,它会在重复运行时于数秒内完成,能在浪费 CI 时间之前拦截琐碎问题

二、安装钩子:两种方式任选

根据 hooks/README.md 的 Installation 一节,安装方式有两种,效果等价。

方式一:复制到本地.git/hooks目录

这是 Git 的传统做法,把钩子文件复制到当前检出目录的.git/hooks中并赋予可执行权限:

cp hooks/pre-push .git/hooks/pre-push chmod +x .git/hooks/pre-push

需要注意的是,.git目录本身不受版本控制,这种方式意味着钩子只会作用于当前这一份本地检出;如果你重新 clone 仓库,需要重新执行上述命令。

方式二:将hooks目录配置为 Git 钩子目录

如果你更希望让 Git 直接使用仓库中的这个目录作为钩子来源,可以配置core.hooksPath

git config core.hooksPath hooks

设置之后,Git 会从仓库根目录下的hooks/目录读取钩子脚本。这种方式下钩子文件始终与仓库源码保持同步——仓库更新hooks/pre-push后,本地无需任何手动操作即可生效。如果你将来想回到默认行为,可以执行git config --unset core.hooksPath取消该配置。

两种方式都要求仓库根目录下存在scripts/pre-push.sh,钩子才能正常工作;若脚本缺失,钩子会打印提示并静默跳过(见下文 shim 分析),不会阻断推送。

三、pre-push 执行链路:从 Git 事件到 fast-lint

理解整条链路需要依次阅读三个文件:钩子薄壳 hooks/pre-push、托管脚本 scripts/pre-push.sh、以及最终的 lint 入口fast-lint任务(定义于 pixi.toml)。

3.1 薄壳:hooks/pre-push

hooks/pre-push 是一个极简的 POSIX shell 脚本,核心逻辑只有几步:

repo_root=$(git rev-parse --show-toplevel) pre_push_hook=$repo_root/scripts/pre-push.sh if [ -f "$pre_push_hook" ]; then exec $pre_push_hook # --skip lint-codegen else echo "The pre-push hook appears to be missing from: $pre_push_hook -- Skipping." exit 0 fi
  • 通过git rev-parse --show-toplevel定位仓库根目录,从而保证无论从哪个子目录执行 push,都能找到托管脚本;
  • scripts/pre-push.sh存在,则用exec直接替换当前进程执行它;
  • 若缺失,则打印提示并以退出码0跳过(不会阻塞推送);
  • 第 8 行注释掉的--skip lint-codegen是一个预留示例:你可以通过给scripts/pre-push.sh追加参数的方式跳过特定检查(参数会一路透传给fast-lint)。

3.2 托管脚本:scripts/pre-push.sh

scripts/pre-push.sh 是真正的决策层,包含两层逻辑:

第一层:环境前置检查。脚本要求本机已安装 Pixi(Rerun 的包管理 / 任务运行工具):

if ! command -v "pixi" > /dev/null 2>&1; then echo "The rerun hooks require 'pixi', which is not installed or not in your PATH. Please run: 'cargo install pixi'." exit 1 fi

pixi不在 PATH 中,钩子会以退出码1失败并提示通过cargo install pixi安装。仓库的 pixi.toml 对 Pixi 版本有明确要求:requires-pixi = ">=0.71.3",建议安装满足该约束的版本。

第二层:分支匹配决策。Git 的pre-push钩子会从标准输入读取待推送的引用列表,每行格式为<local_ref> <local_sha> <remote_ref> <remote_sha>。脚本逐行读取并对每个本地引用做处理:

while read -r local_ref _local_sha _remote_ref _remote_sha; do branch_name=$(echo "$local_ref" | sed 's/^refs\/heads\///') active_branch=$(git symbolic-ref --short HEAD) if [ "$branch_name" = "$active_branch" ]; then exec pixi run fast-lint "$@" else echo "Skipping fast-lint because the pushed branch ($branch_name) does not match the active branch ($active_branch)." fi done

关键行为说明:

  • 只有当被推送的分支名与当前检出的活动分支一致时,才执行pixi run fast-lint "$@""$@"会把用户在 push 命令行之后附加的参数(例如--skip)原样透传给 fast-lint;
  • 若推送的是非活动分支(例如git push origin other-branch而当前在main),脚本会打印跳过信息——这是为了避免在开发分支上重复做与当前工作区无关的检查;
  • 使用exec意味着一旦匹配,后续分支不会再被处理,检查结果直接决定 push 的成败(非零退出码会终止推送)。

3.3 fast-lint 任务定义

在 pixi.toml 中,fast-lint被定义为:

fast-lint = "python scripts/fast_lint.py"

Pixi 在执行任务前会确保所有依赖已安装(仓库在 pixi.toml 顶部注释中对此有明确说明),因此钩子运行时无需手动准备 Python 环境。

四、fast-lint 到底检查什么

scripts/fast_lint.py 的模块文档将其定位为:"对相对main分支发生变更的文件运行常用 linters"。它的核心价值在于只检查变更文件,因此重复运行时只需数秒,适合放在 pre-push 这种高频路径上。

4.1 变更文件检测

changed_files()函数(见 scripts/fast_lint.py)使用 GitPython 打开当前仓库,计算当前分支与main的合并基点(merge_base),再通过repo.index.diff(common_ancestor)得到相对main变更且仍然存在的文件列表。也就是说:默认只 lint 你本次分支改动涉及的文件,未修改的存量代码不会被重复检查。

4.2 内置的检查任务清单

main()中通过LintJob定义了九个检查任务(见 scripts/fast_lint.py),每个任务都可以声明接受的文件扩展名、无变更时的兜底命令、以及是否支持"无变更过滤":

任务命令适用文件说明
lint-codegen不接受文件参数校验代码生成结果是否与当前源码一致(对应 pixi.toml 中的cargo run --package re_types_builder -- --check
lint-rerun全部运行自定义 lint 脚本 scripts/lint.py,对 Rust、文档等执行项目专属规则检查(支持NOLINT/NOLINT_START/NOLINT_END注释忽略机制)
lint-rs-files.rs对变更的 Rust 文件运行rustfmt --edition 2024 --check;无变更文件时回退到全量lint-rs-all(即cargo fmt --check);同时用正则^crates/store/re_sdk_types(_core)?/排除生成代码目录
py-fmt-check.py对变更的 Python 文件运行uv run ruff check . && uv run ruff format --check .;无变更时检查整个PY_FOLDERS(即仓库根目录.
py-lint.py运行 mypy 类型检查,accepts_files=False,即始终对全项目执行(避免按文件运行 mypy 结果不一致)
toml-fmt-check.toml对变更的 TOML 文件运行taplo fmt --check --diff
lint-typos --force-exclude全部运行typos拼写检查
check-large-files全部调用 scripts/ci/check_large_files.py 检查是否存在过大的仓库文件
nb-strip-check不接受文件参数校验 notebook 输出是否已被清理(accepts_files=False

各任务通过concurrent.futures.ThreadPoolExecutor并行执行(默认 8 个线程),任何一个任务失败都会导致最终退出码非零,从而中断 git push

4.3 fast-lint 的命令行参数

scripts/fast_lint.py 提供了以下参数,供手动运行或钩子透传使用:

  • --log-level:日志级别,默认INFO,可选DEBUG/INFO/WARNING/ERROR/CRITICAL
  • --num-threads:并行线程数,默认8
  • --skip:逗号分隔的待跳过任务列表,默认值来自环境变量RERUN_LINT_SKIP;如果传入了清单中不存在的任务名,脚本会报错并退出(见 scripts/fast_lint.py);
  • --no-change-filter:不做变更过滤,对所有文件全量运行;
  • 位置参数files:指定文件路径,空则递归检查全部文件。

手动运行示例(无需等待 push 触发):

pixi run fast-lint # 仅检查相对 main 的变更文件 pixi run fast-lint -- --skip lint-codegen,nb-strip-check # 跳过指定任务 pixi run fast-lint -- --no-change-filter # 全量检查

注意:pixi run会把--之后的参数透传给任务脚本,因此上述写法在命令行上是安全的。

五、使用建议与常见问题

5.1 与 CONTRIBUTING 中的推荐流程结合

CONTRIBUTING.md 将"推送前运行 fast-lint"列为贡献者的常规动作,并推荐通过安装 pre-push 钩子来自动化这一流程。由于钩子内部已经包含分支匹配逻辑,日常在活动分支上git push时它就会自动生效,无需额外记忆。

5.2 常见问题排查

  • 推送被钩子拦截,如何定位是哪项检查失败?查看终端输出的FAIL: <command>日志(见 scripts/fast_lint.py),它会打印失败命令、完整命令行与被检查文件。修复问题后重新 push 即可。
  • 临时想跳过某项检查?在 push 命令后透传--skip参数:git push origin main --skip lint-codegen(参数会经 scripts/pre-push.sh 的"$@"透传给 fast-lint);也可以设置环境变量RERUN_LINT_SKIP。注意:跳过检查只是绕过本地门禁,CI 上仍可能执行全量检查。
  • 没有安装 Pixi 会怎样?钩子会以退出码1失败并提示先执行cargo install pixi,避免在缺失依赖的情况下给出误导性的"通过"结论。
  • 不想使用钩子了?若采用core.hooksPath方式,执行git config --unset core.hooksPath恢复默认;若采用复制方式,把.git/hooks/pre-push移除即可。

5.3 进阶:钩子只做转发,逻辑都在 scripts

如果你想了解或扩展检查规则,重点应关注 scripts/fast_lint.py(任务编排)与 scripts/lint.py(自定义规则),以及 pixi.toml 的[tasks]一节中lint-*/*-fmt-check系列任务的具体命令定义。钩子目录本身保持最小化,这正是该项目钩子体系的可维护性所在:仓库升级检查规则后,重新拉取代码即自动获得新逻辑,无需重装钩子

小结

Rerun 的 git 钩子体系围绕"薄壳转发 + 托管脚本 + Pixi 任务"三层结构展开:hooks/README.md给出了安装入口(复制到.git/hooks或配置core.hooksPath),hooks/pre-push负责定位并转发,scripts/pre-push.sh负责环境检查与分支匹配,最终由pixi run fast-lint驱动 scripts/fast_lint.py 并行执行九类检查任务。这套设计让贡献者只需一行配置即可在推送前自动获得轻量、快速、可跳过的质量门禁,是理解并参与 Rerun 开发协作流程的实用起点。

【免费下载链接】rerunVisualize, query, and stream to train on multimodal robotics data.项目地址: https://gitcode.com/GitHub_Trending/re/rerun

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询