使用 Git Hooks 自动化开发任务的 3 个技巧

2025-06-07

使用 Git Hooks 自动化开发任务的 3 个技巧

Git 版本控制系统与许多其他版本控制系统一样,也有一些使其能够通过编程方式扩展的技巧。在本文中,我们将学习其中之一——钩子,它允许在执行许多典型的 Git 命令的同时,实现自动操作。

钩子是在某些重要的 Git 事件之前或之后运行的程序。例如,在完成 git commit 之前、更改分支之后或在 git push 期间发送更改之前。

它们存储在每个克隆项目的 .git/hooks/ 目录中,并且必须是可执行脚本或程序(在类 Unix 系统上必须具有执行权限)。

要将钩子添加到您的项目,只需将您想要使用“事件”名称自动运行的程序复制或链接到该目录(例如,预提交,所有可能的名称都可以在 Git 文档中找到)。

如果程序是一个脚本,并且您希望其他合作者能够使用它,则可以方便地将其包含在项目的根目录中,并在 .git/hooks/ 中创建对它的直接访问:

ln -s ../../pre-commit.sh .git/hooks/pre-commit

让我们看看 Git hooks 的一些实际应用。

1. 提交之前检查代码质量

在确认提交之前执行的钩子很有用,因为它们允许我们在存储库的版本树中反映这些更改之前对添加或删除的代码执行检查。

如果钩子失败或返回错误代码,则不会进行提交。

在以下示例中(适用于 Unix 系统,例如 Linux 或 macOS),我们使用 Node.js 中的 jslint 包在完成提交之前检查 JavaScript 应用程序代码的质量:

#!/bin/bash
# pre-commit.sh

# Save unconfirmed changes
STASH_NAME="pre-commit-$(date +%s)"
git stash save -q --keep-index $STASH_NAME

# Checks and tests
jslint my_application.js || exit 1

# Recover saved changes
STASHES=$(git stash list)
if [[ $STASHES == "$STASH_NAME" ]]; then
  git stash pop -q
fi

您可以采用相同的策略对应用程序启动一系列测试或其他必要的检查,例如搜索密钥或秘密令牌以避免将它们输入存储库。

2. 上传变更后生成文档

如果我们的项目中有一个来自代码的文档生成器,我们可以在开发时使用预推类型的钩子定期执行它。

我们只需启动必要的命令来编写某个目录(例如,docs /)中的所有文档并将其添加到新的提交中。

在下面的列表中,我向您展示了可用于此目的的几个可能的命令的示例:

#!/bin/bash
# pre-push.sh

# Generate the documentation
doxygen Doxyfile

# Another example, with Python:
pydoc3 -w docs/

# Another example, with R:
Rscript -e 'pkgdown::build_site()'

# Add and confirm the changes related to the documentation
git add docs/
git commit -m "Update documentation ($(date +%F@%R))"

这样做的好处是,如果您使用 GitHub Pages 或类似服务来提供您的在线文档,您将始终了解代码的变化,并且它不会过时。

3. 更改分支时检查依赖关系

最后,钩子的一个非常有趣的应用是在项目中更改分支时更新已安装的依赖项。

如果您使用开发语言的包管理器和依赖项(Python 中的 Pip、Node.js 中的 npm、.NET 中的 Nuget、Ruby 中的 Bundler、Rust 中的 Cargo 等),则以下示例会非常有用。

下面的代码清单对应于一个后签出钩子,它的作用是检查前一个分支和新分支之间的依赖文件是否发生了变化(在本例中为 Ruby 的 Gem 文件),在这种情况下,它会方便地执行安装程序(在本例中为 bundle)。

#!/bin/bash
# post-checkout.sh

if [ $1 = 0000000000000000000000000000000000000000 ]; then
  # If we are in a recently cloned project, compare with the empty directory
  old=$(git hash-object -t tree /dev/null)
else
  # The first argument is the hash of the previous HEAD
  old=$1
fi
if [ -f Gemfile ] &&
  git diff --name-only $old $2 | egrep -q '^Gemfile|\.gemspec$'
then
  # Empty $ GIT DIR prevents problems if bundle calls git
  (unset GIT_DIR; exec bundle)
  # Checkout is completed even if the bundler fails
  true
fi

您可以通过将 Gemfile 更改为您使用的依赖项文件(例如 package.json 或 requirements.txt)并将 bundle 更改为相应的命令(npm install 或 pip install -r requirements.txt),来将此代码调整为您自己的用途。

文章来源:https://dev.to/shameemreza/3-tricks-to-automate-development-tasks-with-git-hooks-2dah
PREV
使用 Nginx 作为反向代理缓存来加速您的网站
NEXT
JavaScript 中的事件循环是什么?