ARTICLE DETAIL

资讯详情

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

prek Cookbook:用 Git 2.54 config-based hooks 搭建跨仓库的全局 Hook

prek Cookbook:用 Git 2.54 config-based hooks 搭建跨仓库的全局 Hook prek Cookbook用 Git 2.54 config-based hooks 搭建跨仓库的全局 Hook【免费下载链接】prek⚡ A fast Git hook manager written in Rust, designed as a drop-in alternative to pre-commit, reimagined.项目地址: https://gitcode.com/GitHub_Trending/pr/prek本指南是 prek 官方 Cookbook 的深度展开围绕一个超出「项目本地默认工作流」的典型场景如何让一个个人级prekhook 在所有仓库中生效。你会掌握 Git 2.54 引入的 config-based hooks 机制、git config与~/.gitconfig两种注册方式、prek hook-impl关键选项的底层原理以及一套兼顾安全与可维护性的全局 hook 落地方案。从项目本地到全局为什么要 config-based hooks默认情况下prek 通过prek install在单个仓库的.git/hooks目录中写入 Git shim 脚本hook 配置prek.toml或.pre-commit-config.yaml随项目版本库一起提交。这种「项目本地工作流」的好处是配置可审查、可复现但它有一个盲区你个人的检查规则无法跨仓库复用。每进入一个新仓库都要重新安装、重新配置。Git 2.54 引入了 config-based hooksGit 可以直接从配置而不是 hook 脚本运行 hook。prek 借助这一机制让你把prek挂到 Git 配置上从而「一个 hook 跑遍所有仓库」。前置条件确认 Git 版本config-based hooks 对 Git 版本有硬性要求先确认git --version版本必须是2.54 或更新。低于该版本时[hook …]配置节不会被 Git 识别需要改用 migration 指南 中的其他方案或升级 Git。注册一个全局 config-based hook选择你要监听的 Git hook 事件例如pre-commit然后注册一个全局的 config-based hook。下面两种写法完全等价任选其一。方式一git config命令git config --global hook.prek-pre-commit.event pre-commit git config --global hook.prek-pre-commit.command prek hook-impl --hook-type pre-commit --skip-on-missing-config --方式二直接编辑~/.gitconfig在全局 Git 配置如~/.gitconfig中写入[hook prek-pre-commit] event pre-commit command prek hook-impl --hook-type pre-commit --skip-on-missing-config --配置的三个要素无论用哪种方式注册这段配置都包含三个要素| 要素 | 含义 | 示例 | | -- | -- | -- | |hook.friendly-name.event| 要监听的 Git hook 事件 |pre-commit、pre-push、commit-msg| |hook.friendly-name.command| Git 为该事件执行的命令 |prek hook-impl --hook-type pre-commit …| |friendly-name| 该配置 hook 的用户自定义名称 |prek-pre-commit|friendly-name是你在 Git 配置中给这个 hook 起的唯一标识。它只在 Git 配置里出现与 hook 脚本文件名无关请保证它在你的 Git 配置中全局唯一避免多个[hook …]节互相覆盖。如果要同时挂多个事件比如既想检查提交又想检查推送就注册多个 friendly name每个对应一个event和command。两个必须保留的选项--skip-on-missing-config与尾随--原文档特别强调command 中的这两个成分务必保留它们分别解决「误伤普通 Git 操作」和「参数被错误解析」两个问题。--skip-on-missing-config没有配置的仓库不失败普通 Git 操作如git add、git commit在很多仓库中根本没有prek.toml或.pre-commit-config.yaml。如果没有这个选项prek 会报错并让提交失败干扰你在任意仓库中的日常操作。从 hook_impl.rs 的源码可以看到它的真实语义let allow_missing_config skip_on_missing_config || EnvVars.is_set(EnvVars::PREK_ALLOW_NO_CONFIG);即「跳过缺失配置」有两种触发方式命令行--skip-on-missing-config或环境变量PREK_ALLOW_NO_CONFIG。当配置缺失且允许跳过时hook_impl会返回 legacy code成功退出并交给 Git 继续正常流程反之则会打印错误并给出三条提示临时用PREK_ALLOW_NO_CONFIG1 git …静默、永久用prek install的--allow-missing-config标志、或用prek uninstall卸载。尾随--把 Git 参数转发给 hook-implGit 调用 config-based hook 时会把 hook 自身的参数追加到 command 后面。例如commit-msg会传提交信息文件名pre-push会传远端名称和 URL。没有--时这些参数会被 hook_impl.rs 当作 hook 选择器去解析从而报出类似「expected no arguments but received 1」的错误。而--之后的内容会被原样保留为参数并由to_run_args按 hook 类型正确消费。从源码看prek 对各类事件的参数处理相当完备pre-commit不接收参数0..0只基于暂存区运行commit-msg接收 1 个参数作为提交信息文件名run_args.extra.commit_msg_filenamepre-push接收 2 个参数远端名称、远端 URL还会读取 stdin 中的推送引用信息解析出 diff 范围parse_pre_push_info见 hook_impl.rs只对本次真正推送的提交做检查prepare-commit-msg接收 13 个参数文件名、来源、commit 对象名pre-rebase、post-checkout、post-merge、post-rewrite等也有各自的参数约定见 hook_num_args。所以请始终保留尾随--让 Git 提供的参数原样转发给prek hook-impl。两种发现模式自动发现仓库配置 vs 固定全局配置prek hook-impl默认会发现当前仓库的配置从当前目录向上寻找项目的prek.toml或.pre-commit-config.yaml并运行该配置中声明的 hooks对应源码中的Project::discover见 hook_impl.rs。这意味着同一份全局 hook 在不同仓库会跑不同的检查规则——这正是许多场景下想要的行为。如果你希望一个全局 hook 配置在所有仓库中运行完全相同的内容就把配置文件显式传给hook-implgit config --global hook.friendly-name.command prek hook-impl --hook-type event --config config-file --例如把 gitleaks密钥扫描工具做成全局配置先创建~/.config/prek/global-hooks.toml[[repos]] repo https://github.com/gitleaks/gitleaks rev v8.24.2 hooks [{ id gitleaks }]然后把它挂到全局 Git hook 上git config --global hook.gitleaks.event pre-commit git config --global hook.gitleaks.command prek hook-impl --hook-type pre-commit --config ~/.config/prek/global-hooks.toml --这样每次git commit时 gitleaks 都会在任意仓库中运行。注意~会被 prek 的配置解析器展开PathBufValueParser::new().map(expand_tilde)见 mod.rs因此可以直接写在命令里。另外需要说明prek hook-impl是一个面向内部调用被安装的 Git shim 调用的隐藏命令见 compatibility.md。它的行为等价于prek run --stage hook-type由 cli/run 加载配置、执行 hook并返回一致的退出码。手动在 shell 里调用它时请照抄上文命令格式不要擅自改动参数。移除全局 config-based hook卸载时删除该 friendly name 对应的两个配置键即可。以本页第一个示例为例git config --global --unset-all hook.prek-pre-commit.event git config --global --unset-all hook.prek-pre-commit.command如果使用的是其他 friendly name如gitleaks把两条命令中的prek-pre-commit换成对应名称即可。需要区分的是这只会修改全局 Git 配置不会删除prek install在具体项目.git/hooks中安装的项目本地 shim。两者是相互独立的机制——前者来自 Git config后者来自 hook 脚本文件。安全警告只在信任的仓库上启用自动发现config-based hooks 的「发现模式」有一个值得反复强调的安全属性。它读取当前仓库的配置并执行其中的 hooks而 hook 配置本质上是可执行的项目代码安装步骤、依赖下载、entry 命令都会以你的用户权限运行。因此一个仓库可以让项目控制的代码在你执行 Git 操作时以你的权限运行。请只在信任的仓库中使用此模式。这一点与 Security Guide 的建议完全一致把陌生的prek.toml或.pre-commit-config.yaml当作陌生的构建脚本来对待——审查远端仓库 URL、revision、hook 条目与额外依赖审查本地 hooks 和检入的脚本尤其是显式调用 shell 的条目并在本地运行前检查 PR 中的配置改动。对于不信任的仓库使用更严格的凭据与隔离或者干脆改用「固定全局配置」模式如上面的 gitleaks 示例让所有仓库执行你完全控制的同一个配置。更细致的隔离与凭据建议还可以参考 ci.md 的缓存与凭据小节以及 FAQ 中关于私有仓库的部分。延伸配方本指南只覆盖了「全局 hook」这一种超出项目本地默认工作流的模式更多实用配方见仓库其他文档运行一个已有的项目 linter 或 formatter用repo: local直接在当前项目配置中定义本地 hook适用于 ruff、cargo fmt 等工具在持续集成中运行 hooks用prek run --all-files让 CI 与本地运行同一份检入配置在迁移期间保留已有的 Git hook从 pre-commit 迁移到 prek 时如何保留原有的 legacy hook 平滑过渡。相关实现可以进一步阅读hook_impl.rshook-impl 的完整逻辑包括 legacy hook 兼容、stdin 读取与参数校验、install.rsGit shim 脚本版本CUR_SCRIPT_VERSION安装的 shim 会调用hook-impl以及 cli/mod.rs全局选项-c/--config与-C/--cd的定义。【免费下载链接】prek⚡ A fast Git hook manager written in Rust, designed as a drop-in alternative to pre-commit, reimagined.项目地址: https://gitcode.com/GitHub_Trending/pr/prek创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表