本文由 简悦SimpRead 转码,原文地址 www.tygertec.com
什么是 Git 钩子?你能用它们做一些有用的事情吗?另外,由于Git钩子来自于Linux,那么t......
什么是Git钩子?你能用它们做任何有用的事情吗?另外,由于Git钩子来自Linux,你需要做什么特别的事情来让它们在Windows上工作吗?
什么是Git钩子?
Git 钩子允许你在 Git 生命周期中的某些重要事件发生时运行自定义脚本,比如提交、合并和推送。Git在repo\.git\hooks目录下提供了一些钩子脚本的样本,但它们默认是禁用的。例如,如果你打开那个文件夹,你会发现一个叫做pre-commit.sample的文件。要启用它,只需将其重命名为pre-commit,去掉.sample扩展名,并使该脚本可执行(如果你在Linux上,chmod +x pre-commit,或者如果你在Windows上,只需检查你的NTFS执行权限)。当你试图用git commit提交时,该脚本会被找到并执行。如果你的预提交脚本以0(零)退出,你就提交成功,否则提交失败。
如果你看一下默认的预提交脚本样本,它默认做了一些有用的事情,比如不允许非ascii文件名,因为它们在某些平台上会导致问题,并检查是否有空格错误。这意味着,如果你启用了这个脚本,并且出现了 "空格错误",比如以空格或制表符结尾的行,你就会提交失败,必须在提交前删除空格。
用Git钩子能做什么酷事?
既然你是在用脚本工作,你几乎可以用 Git 钩子做任何事情。尽管如此,只是因为你可以做一些事情......是的,你知道。Git 钩子会让提交、推送和拉取等常见的 Git 任务的行为变得不标准,这可能会惹恼人们,尤其是当他们刚刚尝试适应 Git 的辉煌时。但这里有几个例子可以说明用Git钩子可以完成什么。
用预提交钩子确保你的名字和电子邮件设置得当
当你推送到像GitHub这样的公共仓库托管服务时,如果你的Git配置中出现了错误的名字或电子邮件,那就真的很恼火了。
# (pre-commit or pre-push)
# Make sure my email is set properly
useremail=$(git config user.email)
if [ "$useremail" != "tygerbytes@users.noreply.github.com" ]
then
cat <<\EOF
Error: user.email not set to "tygerbytes@users.noreply.github.com"
EOF
exit 1
fi
下面是同样的脚本,但这次它在让我推送我的东西之前确保Git知道我的名字。
# (pre-commit or pre-push)
# Make sure my name is set properly
username=$(git config user.name)
if [ "$username" != "Ty Walls" ]
then
cat <<\EOF
Error: user.name not set to "Ty Walls"
EOF
exit 1
fi
你可以把这些代码片段添加到 "pre-commit "或 "pre-push "中,但在这种情况下,我推荐 "pre-commit"。否则,你可能不得不编辑你的提交历史来纠正你的名字和电子邮件。
不要推送你会后悔的东西到公开的Git repo上
你一定听说过有人不小心把密码、电子邮件地址、API 密钥等敏感信息推送到公共仓库的恐怖故事。Ryan Hellyer不小心泄露了他的亚马逊AWS访问密钥到GitHub上,第二天早上被6000美元的账单吓醒了。下面是一个简单的 "预提交 "或 "预推送 "脚本片段,如果传出的差异与黑名单中的一个关键词相匹配,则提交或推送失败。
# (pre-commit or pre-push)
# Fail if any matching words are present in the diff
matches=$(git diff-index --patch HEAD | grep '^+' | grep -Pi 'Word1|Word2|Word3')
if [ ! -z "$matches" ]
then
cat <<\EOT
Error: Words from the blacklist were present in the diff:
EOT
echo $matches
exit 1
fi
当然,如果你在这里加入这些话,你必须确保钩子脚本不会以某种方式被推送到你的 repo 中。也许你可以不把黑名单以纯文本形式保存在脚本中,而是以另一种加密的格式保存在你的电脑上的某个地方。脚本可以被调整为解析该文件以获得黑名单中的词。
使用pre-push来只推送绿色的构建
你可能已经读过我的文章编写Psake构建脚本,以促进项目的持续集成和一般的可怕性。如果你的Psake脚本已经构建并测试了一切,为什么不在pre-push钩子中运行它呢?这样你就可以省去推送错误构建的尴尬了。
# (pre-push)
# Make sure we can build and all tests are passing
exec powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".\build.ps1" Tests
Git钩子有什么限制吗?
好吧,如果你认为可以利用Git钩子将一些马基雅维利式的工作流程强加给你的团队,你可能要重新考虑一下。客户端钩子通常可以绕过,要么使用低级的 "管道 "命令,而不是高级的 "瓷器 "命令,而且通常在命令中传递--no-verify选项即可。例如,git commit --no-verify就不会运行pre-commit钩。在服务器端,你可能会有更多的成功,因为你有严厉的计划。但你已经被警告过了:)
分享你的钩子
另一个限制是,客户端的 Git 钩子不会被检查到 repo 中,因此不会在团队成员之间共享。如果你想和你的同事分享方便的钩子,你必须想出一些分发方案。有些人在他们的 repo 中创建了一个包含 Git 钩子的目录,并且是在源代码控制之下。然后他们从.git\hooks\*创建一个链接到这个文件夹,也许是通过某种共享更新脚本。
利用Git新的hooksPath选项
[2016年6月18日更新]。从Git 2.9.0开始,现在可以用一个配置选项来指定Git钩子的位置 - hooksPath !
如果你有一些Git钩子想默认用于你的所有仓库,怎么办?除了安装Git 2.9或更高版本外,你只需要把它们复制到一个中心位置,并配置Git在那里寻找你的钩子。例如,在你的主目录下创建一个名为".githooks "的文件夹。然后运行下面的 Git 命令。
git config --global core.hooksPath '~/.githooks'
(如果你不熟悉类Unix系统,~代表你的主目录。在Windows中,它将评估为%userprofile%)。
但如果你不想为某个特定的 repo 使用这些全局钩子呢?只需将Git配置为使用该 repo的默认位置,像这样。
git config core.hooksPath '.git/hooks'
注意没有--global选项,表明你在为当前的仓库设置配置选项。
注意事项
Git 钩子给你的仓库增加了一层复杂性,使其行为变得不标准。这就是为什么许多专家建议首先不要使用git hooks。我不是专家,但我同意。避免使用 Git 钩子,除非它们能提供一些真正可量化的价值。
为什么Git钩子不能在windows上使用?
我第一次尝试在 Windows 上使用 Git 钩子,它们完全没有作用。他们甚至没有出现错误。我确定它们的名字是正确的,没有.sample扩展名,并且验证了我的账户对钩子脚本有执行权限。
问题就潜伏在脚本的第一行,即 "shebang "声明。
#!/bin/sh
在类似Unix的操作系统上,#!告诉程序加载器这是一个要被解释的脚本,/bin/sh是你要使用的解释器的路径,在这个例子中是sh。Windows绝对不是一个类似Unix的操作系统。Git for Windows 通过 Cygwin 支持 Bash 命令和 shell 脚本。默认情况下,当它在"/bin/sh "寻找 "sh.exe "时,会发现什么?是的,什么都没有;什么都没有。通过提供你系统中sh可执行文件的路径来解决这个问题。我使用的是64位的Windows版Git,所以我的shebang行是这样的。
#!C:/Program\ Files/Git/usr/bin/sh.exe
不要忘了用反斜杠转义空格(" ")。在纠正了sh.exe的路径后,你的脚本应该可以运行了。
不过你会意识到一件事:Bash和Windows并不超级兼容。所以,只要你坚持基本的操作,你的钩子脚本就能正常运行,但如果你需要更高级的东西,而且你使用的是Windows,你就需要使用PowerShell而不是sh。幸运的是,这并不困难,实际上我已经在 "pre-push "钩中运行你的Psake脚本的部分向你展示了如何做。你所要做的就是在你的bash脚本中调用PowerShell脚本。例如,要在PowerShell中写一个漂亮的预提交钩子,创建一个包含所有可爱的预提交逻辑的PowerShell脚本,并将其称为pre-commit.ps1。然后在你的pre-commit脚本中添加以下内容。
#!C:/Program\ Files/Git/usr/bin/sh.exe
exec powershell.exe -NoProfile -ExecutionPolicy Bypass -File ".\.git\hooks\pre-commit.ps1"
如果你想阻止提交,确保pre-commit.ps1退出时的值不是零。
你是否发现了Git钩子的一些方便的用途?请在下面发表您的意见。