一、什么是预提交(Pre-Commit)?
Pre-commit 是一个 Python 软件包,能够帮助我们更容易创建预提交钩子(pre-commit hook)。钩子是 git 原生的东西,是在执行特定 git 命令前运行的脚本。
可以在仓库的 .git/hooks 目录中找到钩子,该目录由 git 自动创建。在这个目录中,可以找到类似下面这样的文件:
.sample 扩展名会阻止执行这些钩子。要启用钩子,请删除 .sample 扩展名并编辑文件。
不过这么做既繁琐又对用户不友好,而且很难通过版本控制进行管理,这就有 pre-commit 的用武之地了,它为 commit 命令创建钩子,可以自动检测代码中的任何问题,并使脚本的创建工作天衣无缝。
它会创建一个在调用 git commit 命令时自动执行的配置文件。配置文件中的任何检查失败,都会终止提交,从而始终确保代码库的质量和一致性。
二、数据科学为什么需要 pre-commit 钩子?
作为数据科学家,为什么也需要学习 git 钩子?现在社区中出现了一种趋势,认为精通软件工程越来越重要,而能够将自己的模型部署到生产中是非常有价值的事情。
而利用 git 钩子和 pre-commit 是确保稳健部署机器学习模型,同时保证代码质量的一种技术。机器学习模型比较繁琐,因此任何能让工作流程自动化并在模型投入生产前捕捉潜在错误的方法都是有价值的。
三、使用方法
1. 安装
安装 pre-commit 非常简单,和通过 pip 安装其他 Python 库一样。我个人是用 Poetry,但都能正常工作。
运行该程序即可确认已安装。
2. 配置文件
进入代码仓库根目录,在项目中创建 .pre-commit-config.yaml。运行以下命令即可完成创建:
该文件将定义在提交代码前要运行的内容。示例如下:
这里 repos 表示包含要运行的钩子的仓库列表。第一个是包含钩子的 pre-commit-hooks 仓库:
- id: check-yaml
- id: end-of-file-fixer
- id: trailing-whitespace
在这个例子里,id 是执行的特定预提交钩子的唯一标识符。
然后,我们对 black 和 flake8 代码包采用相同的流程。
3. 执行
定义配置文件后,需要执行 pre-commit install,让 pre-commit 知道你想使用指定的脚本在该仓库上执行预提交检查。
然后,修改代码并尝试提交,应该会看到预提交钩子开始工作。
也可以执行命令 pre-commit run --all-files 来查看 pre-commit 正在做什么。
如果想在不运行钩子的情况下提交代码,可以执行 git commit --no-verify 绕过钩子。
好了,我们举个例子!
四、示例
我在 Medium-Articles 仓库中安装了 pre-commit,用它来展示一个例子。
在仓库中,有以下 Makefile 文件:
其中定义了两个命令 install 和 lint 来设置环境,确保代码没有问题。
该仓库的 .pre-commit-config.yaml 如下所示,与之前展示的模板略有不同。
在本例中,钩子所在的仓库是本地的,即在我的项目中。该钩子将执行 entry 里定义的 make lint 命令,作为钩子的一部分,该命令已在 makefile 文件中定义。
仓库里有一个代码文件是这样的(relu.py):
我们尝试提交这段代码,看看会发生什么。
钩子失败了,它重新格式化了 relu.py。现在这个文件是这样的:
可以看到,预提交钩子成功运行了!
五、总结和进一步思考
Pre-commit 是一个实用的 Python 软件包,能改善 git 钩子的工作流程并简化脚本。它旨在通过自动化代码检查流程来保持软件的高质量并消除错误风险。作为数据科学家,越来越多参与到模型部署中,可以通过 git 钩子和 pre-commit 等技术来确保模型安全部署到生产环境。