在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?
广告
将在 10 秒后关闭
bannerAds