在 Git Pull 上自动安装 NPM 依赖项

2025-05-28

在 Git Pull 上自动安装 NPM 依赖项

更新:我为该脚本发布了一个 npm 包:git-pull-run。如有任何问题或改进建议,请在GitHub上报告。

我和我的团队一直在一个包含多个包的项目存储库上工作 - 一个monorepo。当然,我们使用的是 Git 和分支,所以我们之间几乎没有摩擦。除了依赖项 - 在我们的例子中是 npm 依赖项 - 但我想这也适用于其他环境。当我在当前分支上拉取最新更改或在不同的分支之间切换时,我必须知道package-lock.json(锁定文件)是否已更改。如果是这样,我必须运行npm install以确保我的依赖项已更新到最新更改。否则,我可能会遇到难以发现的错误,由于依赖项过时,当前开发在某些机器上运行,但在另一台机器上运行不正常。

钩子救援

我们已经在使用预提交钩子来自动运行 linting 和格式化。使用Git Hooks和Husky之类的工具,git commit这很容易实现。幸运的是,Git 还支持合并后钩子,该钩子在本地存储库上完成 之后运行。这正是我们需要更新依赖项以查看它们是否已更改的时间点。有关如何开始使用钩子的详细步骤,我建议您遵循本指南git pull

检测变化

当我们获取git pull最新的更改时,我们需要所有已更改文件的列表。如果此列表包含package-lock.json,则需要运行npm install来更新依赖项。如果我们像我的情况一样处理包含多个包的 monorepo,则需要为每个更改的包运行它。以下代码git diff打印已更改文件的列表:

git diff --name-only HEAD@{1} HEAD
Enter fullscreen mode Exit fullscreen mode

使用一个简单的正则表达式,我们可以过滤所有包含package-lock.json文件的路径。我将正则表达式放入PACKAGE_LOCK_REGEX变量中,因为这部分必须根据实际项目结构进行更改。它包含一个以 开头的匹配组(即第一对括号)packages/,因为在我们的 monorepo 中,所有包都位于此目录下(开发依赖项除外,它们位于项目根目录中)。正则表达式过滤的结果以数组形式保存到PACKAGES变量中。

IFS=$'\n'
PACKAGE_LOCK_REGEX="(^packages\/.*\/package-lock\.json)|(^package-lock\.json)"
PACKAGES=("$(git diff --name-only HEAD@{1} HEAD | grep -E "$PACKAGE_LOCK_REGEX")")
Enter fullscreen mode Exit fullscreen mode

运行安装

最后,我们需要npm install对每个更改的包运行一次。由于 Git 在项目根目录下运行,而更改的文件实际上是锁定文件的路径,因此我们必须在运行 install 之前更改目录。这样,$(dirname package)我们就可以轻松地从路径中提取目录。

if [[ ${PACKAGES[@]} ]]; then
  for package in $PACKAGES; do
    echo "📦 $package was changed. Running npm install to update your dependencies..."
    DIR=$(dirname package)
    cd "$DIR" && npm install
  done
fi
Enter fullscreen mode Exit fullscreen mode

合并后挂钩

所有上述代码片段都可以组合成以下 shell 脚本,该脚本将由 Husky 作为合并后钩子执行。

#!/bin/zsh
. "$(dirname "$0")/_/husky.sh"
IFS=$'\n'
# regex supports mono-repos with a package.json at root-level and at package-level
PACKAGE_LOCK_REGEX="(^packages\/.*\/package-lock\.json)|(^package-lock\.json)"
# extract all paths to package-lock.json files
PACKAGES=("$(git diff --name-only HEAD@{1} HEAD | grep -E "$PACKAGE_LOCK_REGEX")")
if [[ ${PACKAGES[@]} ]]; then
for package in $PACKAGES; do
echo "📦 $package was changed. Running npm install to update your dependencies..."
DIR=$(dirname package)
cd "$DIR" && npm install
done
fi
view raw post-merge.sh hosted with ❤ by GitHub

post-merge该文件必须以.sh 格式保存在.husky文件夹中。我在 macOS 上运行,默认 shell 为zsh#!/bin/zsh (参见 shebang ),并且运行正常。不过,我没有用bash测试过,所以如果你运行其他 shell,可能需要进行一些更改。

测试一下

为了验证钩子是否有效,我们可以将当前本地分支重置为之前的状态(例如倒回 20 次提交),然后将更改拉回。

git reset --hard HEAD~20 && git pull
Enter fullscreen mode Exit fullscreen mode

如果package-lock.json某个提交中的内容发生了更改,钩子会为每个锁定文件打印一条简短的提示信息,并自动npm install为我们运行。如果您使用 VSCode 等集成 Git 的编辑器,则需要检查 Git 日志的输出以了解发生了什么。

文章来源:https://dev.to/zirkelc/automatically-install-npm-dependencies-on-git-pull-bg0
PREV
CodeSandbox Black,有史以来最好的 VSCode 主题!
NEXT
最好的 Node JS 免费托管服务