在Git中使用Git Hooks来钩取git clone操作
我想做的事情
可以说,这就像是一个“后克隆钩子”。我只想在执行git clone之后针对存储库目录执行特定的操作。在这种情况下,我希望根据克隆目标目录进行分支处理。也就是说,使用git clone –template无法很好地解决这个问题。
總結
以一种类似解决办法为例,与其他脚本不同,它不仅仅是一个脚本文件而已。虽然这是一个Bash的例子,但我认为其他shell也可以借鉴这种思路。
trap DEBUGでgit cloneを叩いたことを検知して、コマンド実行前にフラグを立てる。
post-checkoutスクリプト内でフラグが立っているときだけ処理を行い、処理後フラグを倒す。
今回の記事の本筋ではないが、注意点として、GitHooksは標準入力を利用しないので、処理の中で入力を待ちたい場合はターミナルからリダイレクションする必要あり。
背景 – 背景资料
在上一篇文章中,我需要在git clone之前执行一些处理以实现自动切换git帐户,所以我创建了cd和git的包装函数,并通过别名覆盖了原始的cd和git命令,以便在cd命令上设置一个变量来切换git命令使用的帐户。然而,考虑到一些使用插件在cd以外进行目录切换的情况,我发现这种方法缺乏普适性,并且从根本上说并不是一个好的解决方案,所以我决定直接在git clone上设置钩子来解决问题。
由于意外地没有看到关于仅钩取git clone的方法的文章,所以我写下了这篇文章。或许没有这样的文章是因为它完全不被需要吧。
顺便提一下,关于GitHooks的话题,请参考下面的链接。
Git hook的初步入门
Git hook可以实现的功能
請問有什麼問題嗎?
当您想要通过Git Hooks钩子来触发git clone时,需要使用post-checkout方法,但是这也会在执行git checkout时被触发。
另外,由于克隆目录的不同,无法仅通过设定通用模板来实现处理的分岐。
解决办法 (jiě jué cè fǎ)
环境
苹果操作系统
sw_vers
ProductName: Mac OS X
ProductVersion: 10.14.5
BuildVersion: 18F132
Git
Git 是一种分布式版本控制系统,用于跟踪和管理项目代码的变化。
git --version
git version 2.23.0
Bash (终端命令行界面)
bash --version
GNU bash, version 5.0.11(1)-release (x86_64-apple-darwin18.6.0)
检测到git clone的执行
要点:我以.bash_hooks的形式存放在Gist上。使用方法在Gist开头有写明。这个Gist中包含了检测目录移动以及在命令执行之前和之后执行的处理。但是,涉及本篇文章的要点有以下三个。
- 各コマンドの実行前に__hooks__before_each_commandが実行されるようにする
trap '__hooks__before_each_command' DEBUG
__hooks__before_each_command内でBASH_COMMANDで直前のコマンド名(=叩かれたコマンド名)を取得
フックがアクティベートされていたら(この上記Gistの最後でアクティベートしてます)__hooks__set_git_clone_flagに直前のコマンド名を渡して実行
function __hooks__before_each_command() {
local last_command=( $BASH_COMMAND )
if [ -z "$__HOOKS__ACTIVATED" ]; then
return
fi
# before each command
__hooks__set_git_clone_flag "${last_command[@]}";
if [ -z "$__HOOKS__EXECUTING_LINE" ]; then
return
fi
unset __HOOKS__EXECUTING_LINE
# before each first command of a comamnd line
}
- 直前に叩かれたコマンド名がgit cloneだった場合、__hooks__set_git_clone_flag内で__HOOKS__ON_GIT_CLONEフラグを立てる
function __hooks__set_git_clone_flag() {
if [ 'git' = "$1" ] && [ 'clone' = "$2" ]; then
echo "Setting __HOOKS__ON_GIT_CLONE=true in $filename"
export __HOOKS__ON_GIT_CLONE=true
fi
}
在“post-checkout”期间检查标志并进行处理。
大意:我将一个名为.gitvariables的文件放在post-checkout位置上,以加载git帐户的信息,并将该文件本身注册到~/.gitignore中,以便不进行跟踪。
- ここでフラグをチェックして、フラグが立ってなかったらexitしてます。
if [ -z "$__HOOKS__ON_GIT_CLONE" ]; then
exit
fi
- 処理の最後にフラグを倒します。
unset __HOOKS__ON_GIT_CLONE
当使用GitHooks时,需要注意等待用户输入的问题。
虽然离题了,但作为注意事项,GitHooks不使用标准输入,所以如果希望在处理过程中等待输入,需要从终端进行重定向。我有点困惑了。
read -rp 'Type anything you like:' < /dev/tty
总结
在使用中需要特别注意的是,为了避免代码散落和隐式连接,虽然需要更加谨慎地使用,但相较于使用cd和git进行覆写,更具通用性和易于扩展的感觉。
顺便提一下,关于如何在Bash中挂钩命令执行前后的解释,可以看一下Chuan Ji的文章:Bash中的DEBUG陷阱和PROMPT_COMMAND方法解析,非常易懂。
请提供下列内容的中文释义:
Reference
-
- Chuan Ji: DEBUG trap and PROMPT_COMMAND in Bash
- stackoverflow: How to ask for user input in a Git hook?