登录/注册
六六六一啊
2378
占位
2
占位
0
浏览量
占位
粉丝
占位
关注
5.4-Git钩子
六六六一啊
2020-12-30 11:32:43 2020-12-30
307
0

Git 钩子:自定义你的工作流

Git 钩子是在 Git 仓库中特定事件发生时自动运行的脚本。它可以让你自定义 Git 内部的行为,在开发周期中的关键点触发自定义的行为。

enter image description here

Git 钩子最常见的使用场景包括推行提交规范,根据仓库状态改变项目环境,和接入持续集成工作流。但是,因为脚本可以完全定制,你可以用 Git 钩子来自动化或者优化你开发工作流中任意部分。

在这篇文章中,我们会先简要介绍 Git 钩子是如何工作的。然后,我们会审视一些本地和远端仓库使用最流行的钩子。

概述

Git 钩子是仓库中特定事件发生时 Git 自动运行的普通脚本。因此,Git 钩子安装和配置也非常容易。

钩子在本地或服务端仓库都可以部署,且只会在仓库中事件发生时被执行。在文章后面我们会具体地研究各种钩子。接下来所讲的配置对本地和服务端钩子都起作用。

安装钩子

钩子存在于每个 Git 仓库的 .git/hooks 目录中。当你初始化仓库时,Git 自动生成这个目录和一些示例脚本。当你观察 .git/hooks 时,你会看到下面这些文件:

applypatch-msg.sample       pre-push.sample
commit-msg.sample pre-rebase.sample
post-update.sample prepare-commit-msg.sample
pre-applypatch.sample update.sample
pre-commit.sample

这里已经包含了大部分可用的钩子了,但是 .sample 拓展名防止它们默认被执行。为了安装一个钩子,你只需要去掉 .sample 拓展名。或者你要写一个新的脚本,你只需添加一个文件名和上述匹配的新文件,去掉 .sample 拓展名。

比如说,试试安装一个 prepare-commit-msg 钩子。去掉脚本的 .sample 拓展名,在文件中加上下面这两行:

#!/bin/sh
echo "# Please include a useful commit message!" > $1

钩子需要能被执行,所以如果你创建了一个新的脚本文件,你需要修改它的文件权限。比如说,为了确保 prepare-commit-msg 可执行,运行下面这个命令:

chmod +x prepare-commit-msg

接下来你每次运行 git commit 时,你会看到默认的提交信息都被替换了。我们会在「准备提交信息」一节中细看它是如何工作的。现在我们已经可以定制 Git 的内部功能,你只需要坐和放宽。

内置的样例脚本是非常有用的参考资料,因为每个钩子传入的参数都有非常详细的说明(不同钩子不一样)。

脚本语言

内置的脚本大多是 shell和 PERL 语言的,但你可以使用任何脚本语言,只要它们最后能编译到可执行文件。每次脚本中的 #!/bin/sh 定义了你的文件将被如何解释。比如,使用其他语言时你只需要将 path 改为你的解释器的路径。

比如说,你可以在 prepare-commit-msg 中写一个可执行的 Python 脚本。下面这个钩子和上一节的 shell 脚本做的事完全一样。

#!/usr/bin/env python
import sys, os
commit_msg_filepath = sys.argv[1]
with open(commit_msg_filepath, 'w') as f:
f.write("# Please include a useful commit message!")

注意第一行改成了 Python 解释器的路径。此外,这里用 sys.argv[1] 而不是 $1 来获取第一个参数(这个也后面再讲)。

这个特性非常强大,因为你可以用任何你喜欢的语言来编写 Git 钩子。

钩子的作用域

对于任何 Git 仓库来说钩子都是本地的,而且它不会随着 git clone 一起复制到新的仓库。而且,因为钩子是本地的,任何能接触得到仓库的人都可以修改。

对于开发团队来说,这有很大的影响。首先,你要确保你们成员之间的钩子都是最新的。其次,你也不能强行让其他人用你喜欢的方式提交——你只能鼓励他们这样做。

在开发团队中维护钩子是比较复杂的,因为 .git/hooks 目录不随你的项目一起拷贝,也不受版本控制影响。一个简单的解决办法是把你的钩子存在项目的实际目录中(在 .git 外)。这样你就可以像其他文件一样进行版本控制。为了安装钩子,你可以在 .git/hooks 中创建一个符号链接,或者简单地在更新后把它们复制到 .git/hooks 目录下。

enter image description here

作为备选方案,Git 同样提供了一个模板目录机制来更简单地自动安装钩子。每次你使用 git initgit clone 时,模板目录文件夹下的所有文件和目录都会被复制到 .git 文件夹。

所有的下面讲到的本地钩子都可以被更改或者彻底删除,只要你是项目的参与者。这完全取决于你的团队成员想不想用这个钩子。所以记住,最好把 Git 钩子当成一个方便的开发者工具而不是一个严格强制的开发规范。

也就是说,用服务端钩子来拒绝没有遵守规范的提交是完全可行的。后面我们会再讨论这个问题。

本地钩子

本地钩子只影响它们所在的仓库。当你在读这一节的时候,记住开发者可以修改他们本地的钩子,所以不要用它们来推行强制的提交规范。不过,它们确实可以让开发者更易于接受这些规范。

在这一节中,我们会探讨 6 个最有用的本地钩子:

  • pre-commit
  • prepare-commit-msg
  • commit-msg
  • post-commit
  • post-checkout
  • pre-rebase

前四个钩子让你介入完整的提交生命周期,后两个允许你执行一些额外的操作,分别为 git checkoutgit rebase 的安全检查。

所有带 pre- 的钩子允许你修改即将发生的操作,而带 post- 的钩子只能用于通知。

我们也会看到处理钩子的参数和用底层 Git 命令获取仓库信息的实用技巧。

pre-commit

pre-commit 脚本在每次你运行 git commit 命令时,

暂无评论