拓冰建站拓冰建站
首页 / 资讯中心 / 正文

prek 迁移指南:从 pre-commit、lint-staged、Husky 与 Lefthook 平滑切换到 Rust 版 Git Hook 管理器

prek 迁移指南从 pre-commit、lint-staged、Husky 与 Lefthook 平滑切换到 Rust 版 Git 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/prekprek 是一款用 Rust 编写的快速 Git Hook 管理器定位为 pre-commit 的 drop-in 替代品。本文基于仓库中的 docs/migration.md 展开系统讲解如何从 pre-commit、lint-staged、Husky 与 Lefthook 逐步迁移到 prek从配置与命令的等价映射到滚动切换期间新旧钩子并行运行的安全策略再到最终收尾的迁移检查清单帮助你以最小的风险完成替换并落地 CI。迁移的总体原则一次一个钩子渐进式替换prek迁移的核心策略不是一刀切式的整体替换而是一次只迁移一个 hook。在迁移旧工具时请保留旧 hook 可用直到等价的 prek hook 已在整个仓库和 CI上成功运行再移除旧钩子。这样做的好处显而易见每个 hook 的迁移都是独立可回滚的单元失败时只需处理当前这一项旧 hook 始终作为安全网存在即使新 hook 配置有误提交也不会失控CI 与本地同时验证通过后才确认迁移完成避免本地过了、CI 挂了的割裂状态。从 pre-commit 迁移两条命令即可完成如果仓库当前使用 pre-commitprek 几乎可以无缝接管将脚本或文档中的每个pre-commit命令替换为prek。你的现有.pre-commit-config.yaml无需改动即可继续工作若此前执行过pre-commit install需要执行一次prek install -f--force重新安装 Git shim。这是 docs/quickstart.md 中描述的两步路径。之所以要-f是因为旧 shim 属于 pre-commit 而非 prekprek 通过脚本内嵌的 hash 识别是否是自己管理的脚本见下文源码分析需要强制覆盖。pre-commit 兼容性边界迁移前建议先确认仓库依赖的行为是否落在兼容区间内现有.pre-commit-config.yaml与.pre-commit-config.yml文件可直接使用见 docs/configuration.md现有 hook 仓库与.pre-commit-hooks.yaml清单同样受支持主要面向用户的子命令保持上游命名install、run、sample-config、try-repo、uninstall、validate-config、validate-manifestpre-commit hazmat在 prek 中未实现docs/compatibility.md。完整的命令兼容映射见 docs/compatibility.md例如pre-commit autoupdate对应prek updatepre-commit gc/clean归入prek cache gc/prek cache cleanpre-commit migrate-config对应prek util yaml-to-toml。prek 采用更紧凑的命令树部分兼容拼写被隐藏在帮助输出之外但依旧可以调用。值得特别关注的两类差异docs/diff.mdprek 独有配置扩展如priority、shell、pass_filenames正整数形式、repo: builtin等完整清单见 docs/compatibility.md。如果同一份 YAML 配置还需要在上游 pre-commit 中运行请谨慎使用这些扩展若完全切换到 prek则不受限制严格上游可移植性上游 pre-commit 不读取prek.toml也不了解 workspace 模式。需要与上游共存的仓库应继续使用 YAML 格式。源码佐证shim 的识别与覆盖逻辑prek install --force之所以能安全覆盖旧 shim源于 crates/prek/src/cli/install.rs 中的install_hook_script逻辑安装时若目标路径已存在 hookprek 会先用is_our_script检查脚本内是否包含 prek 的标识 hash182c10f1...判断该脚本是否由自己生成不是自己的脚本才会被移动为hook-name.legacy。而--force则直接覆盖写入并删除遗留的 legacy 脚本。从 lint-staged 或 Husky 迁移lint-staged 的命令通常会改写为一个repo local的本地 hook。下面的例子运行项目自带的 ESLint并允许 prek 追加匹配的文件名 prek.tomltoml [[repos]] repo local [[repos.hooks]] id eslint name eslint language system entry npm exec -- eslint files \\.[cm]?[jt]sx?$ pass_filenames true .pre-commit-config.yamlyaml repos: - repo: local hooks: - id: eslint name: eslint language: system entry: npm exec -- eslint files: \.[cm]?[jt]sx?$ pass_filenames: true 注意该 hook 运行前项目必须已安装 Node 依赖language system意味着 prek 不负责安装命令entry 及其调用的解释器/包管理器必须已存在于PATH上详见 docs/local-hooks.md。lint-staged 概念到 prek 的映射| 现有概念 | prek 等价物 | | -- | -- | | lint-staged 文件 glob |files、types、types_or和exclude| | 追加到命令的文件名 |pass_filenames true这也是默认行为 | | 命令自行发现文件 |pass_filenames false| | Shell 管道或展开 | 优先使用直接命令否则显式设置shell| | Husky hook 脚本 | 一个 Git stage 加上prek install|关于表格中几项的关键细节pass_filenames默认为true匹配的文件名会追加到entry与args之后设为false适用于命令自行发现文件或总是检查整个工作区的场景如cargo fmt --all -- --check。prek 还支持正整数形式如pass_filenames 4将大匹配集分批调用这是 pre-commit 不具备的扩展见 docs/reference/configuration.md。prek 默认不通过 shell 执行entryentry会被拆分为参数并直接调用程序|、、重定向、变量与 glob 均不会被 shell 解释。复杂逻辑应放入仓库内的脚本并以该脚本作为 entry确需 shell 语法时再使用 prek 独有的 shell 选项显式声明docs/local-hooks.md。Husky 脚本的额外注意事项如果 Husky 脚本还顺带做了与 lint 无关的工作比如同步环境、生成文件等不要把这些逻辑塞进 Git shim。正确做法是将无关工作保留在项目脚本中再由本地 hook 调用该项目脚本。这样 Git shim 保持小巧命令也能在 Git 之外轻松手动运行。从 Lefthook 迁移Lefthook 与 prek 的抽象模型不同Lefthook 以命令为单位挂到各 Git hook 下prek 则以hook 定义 stages 已安装的 Git shim为模型。将每条 Lefthook 命令翻译为一个本地 hook| Lefthook 概念 | prek 等价物 | | -- | -- | |pre-commit、pre-push等 hook 名称 | Hookstages与已安装的 Git shim | |commands.name.run| 本地 hook 的entry与args| |{staged_files}| 默认的pass_filenames true行为 | |glob与exclude|files、types与exclude| | 并行命令组 | 具有相同priority的 hooks |一个关键心智模型安装 shim 与让 hook 在某个 stage 可运行是两件独立的事。安装决定 Git 在哪个阶段调用 prekstages决定哪些 hook 在该阶段被选中执行。例如default_install_hook_types [pre-commit, pre-push] [[repos]] repo local [[repos.hooks]] id tests name tests language system entry cargo test pass_filenames false stages [pre-push]这里default_install_hook_types声明安装pre-commit与pre-push两个 shim默认仅安装pre-commit见 docs/reference/configuration.mdtestshook 的stages [pre-push]使其只在 push 时运行且pass_filenames false让cargo test自行处理文件。而cargo test的执行结果只决定 push 是否放行。priority 与并行先确认独立性再开启Lefthook 的并行命令组在 prek 中对应相同priority的 hooks——省略priority时 hooks 保持串行执行。迁移并行时需格外谨慎只有在确认这些 hook 不会修改相同文件、不会争用共享状态后才为相互独立的 hook 显式设置相同prioritydocs/reference/configuration.md。priority 是 prek 调度器特有的配置上游 pre-commit 并不存在该字段。滚动迁移期间保留旧 hookprek 的迁移模式这是整个迁移方案中最具安全价值的一环。如果.git/hooks/hook-name已经属于另一个工具普通prek install不会贸然覆盖prek install执行时prek 会把旧 hook 移动到hook-name.legacy并以迁移模式安装自己的 shim。迁移模式下prek shim 会同时运行新旧两个 hook 实现。源码佐证迁移模式的完整实现链路安装阶段crates/prek/src/cli/install.rsinstall_hook_script检测到目标 hook 存在且不是 prek 的脚本时用fs_err::rename将其改名为hook-name.legacy并打印Hook already exists at ... moved it to ...随后若 legacy 文件已存在会提示Migration mode: prek will also run legacy hook ... Use --force to remove legacy hooks.。执行阶段crates/prek/src/cli/hook_impl.rsGit 触发 shim 后进入prek hook-impl其run_legacy会读取hook_dir/{hook_type}.legacy若存在且可执行则先运行 legacy 钩子记录退出码随后再运行 prek 侧配置的 hooks最终退出码取两者中更严重者status非成功则返回 prek 的失败状态否则返回 legacy 的退出码。这意味着迁移期间新旧检查必须全部通过提交才会放行。防递归保护run_legacy检测到环境变量PREK_RUNNING_LEGACY已设置时会直接报错防止 legacy hook 内部再次调用 prek shim 造成死循环。迁移完成后收尾当迁移完成、确认旧 hook 中的检查已全部被 prek 覆盖后用--force替换遗留钩子prek install --force使用--force之前务必确认旧 hook 里没有仍然需要的检查——因为 force 会删除 legacy 脚本。如果迁移尚未完成时决定放弃在迁移模式激活期间执行卸载prek uninstall会将 legacy hook 恢复到原路径完整还原现场源码中对应逻辑卸载时若hook-name.legacy存在则rename回原路径见 crates/prek/src/cli/install.rs 的uninstall函数。这一设计让装回去和退回去同样安全。另外需要说明core.hooksPath若被配置在仓库之外全局/系统级prek 会拒绝安装并提示把该配置移入仓库作用域或使用prek install --force显式安装到仓库默认 hooks 目录crates/prek/src/cli/install.rs。这也是迁移时值得提前排查的 Git 环境项。迁移检查清单原文档在结尾给出了完整的迁移清单逐项核对即可稳妥收尾将每一项现有检查放入本地或远程 hook——逐条翻译而不是整体重写配置确认文件过滤方式以及命令是否接受文件名参数——决定files/types/exclude的写法以及pass_filenames取true还是false配置旧工具处理过的每一个 Git stage——用stages覆盖并在需要时通过default_install_hook_types安装对应 shim暂存配置并运行prek run --all-files——对全仓库存量文件做一次完整验证注意默认prek run只检查暂存区快照改动配置后需先git add全量检查请用--all-files见 docs/quickstart.md将同样的命令加入 CI——本地与 CI 使用完全一致的验证命令参见 docs/ci.md安装 Git shims初期按需保留旧 hook——即利用上述迁移模式并行运行新旧实现仅当本地与 CI 结果一致后再移除旧工具及其依赖——这是最后一步也是唯一能保证零回退风险的时机。结语从任何一种主流 Git Hook 工具迁移到 prek核心都不是改写配置而是用可回滚的方式逐步替换、让新旧实现并行验证、最后再整体收尾。prek 在安装层面对 legacy hook 的保留与恢复机制、在运行层面对新旧双钩子的串联执行对应 crates/prek/src/cli/install.rs 与 crates/prek/src/cli/hook_impl.rs 的实现正是为这套渐进式迁移流程设计的。配合 docs/quickstart.md 的两步切换路径、docs/compatibility.md 的命令映射表以及 docs/diff.md 中 prek 独有能力的说明你可以在数十分钟内完成迁移并持续享受 Rust 原生实现带来的性能提升。【免费下载链接】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),仅供参考
分享:

看完干货,该让你的企业上线了

免费需求沟通 · 48 小时内出具建站方案 · 河南本地可上门