将git挂钩放入存储库

将git挂钩放入存储库,git,hook,githooks,Git,Hook,Githooks,是否认为将.git/hooks放入项目存储库(例如使用符号链接)是一种不好的做法。如果是,向不同的git用户提供相同的钩子的最佳方式是什么?否,将它们放入存储库是可以的,我甚至建议这样做(如果它们对其他人也有用的话)。用户必须显式地启用它们(如您所说,例如通过符号链接),这一方面有点麻烦,但另一方面可以保护用户在未经他们同意的情况下运行任意代码。我通常同意Scytale,并提供了一些额外的建议,足以让我们单独回答 首先,您应该编写一个脚本来创建适当的符号链接,特别是当这些挂钩是关于强制策略或创建

是否认为将
.git/hooks
放入项目存储库(例如使用符号链接)是一种不好的做法。如果是,向不同的git用户提供相同的钩子的最佳方式是什么?

否,将它们放入存储库是可以的,我甚至建议这样做(如果它们对其他人也有用的话)。用户必须显式地启用它们(如您所说,例如通过符号链接),这一方面有点麻烦,但另一方面可以保护用户在未经他们同意的情况下运行任意代码。

我通常同意Scytale,并提供了一些额外的建议,足以让我们单独回答

首先,您应该编写一个脚本来创建适当的符号链接,特别是当这些挂钩是关于强制策略或创建有用的通知时。如果人们只需要键入
bin/创建钩子符号链接,那么他们使用钩子的可能性要比自己使用钩子的可能性大得多

其次,直接符号链接钩子阻止用户添加他们自己的个人钩子。例如,我比较喜欢示例pre-commit钩子,它确保我没有任何空格错误。解决这个问题的一个好方法是在repo中插入一个钩子包装器脚本,并将所有钩子符号链接到它。然后,包装器可以检查
$0
(假设它是一个bash脚本;类似于
argv[0]
的等效脚本),找出调用它的钩子,然后在repo中调用相应的钩子,以及必须重命名的相应用户钩子,并将所有参数传递给每个钩子。内存中的快速示例:

#!/bin/bash
if [ -x $0.local ]; then
    $0.local "$@" || exit $?
fi
if [ -x tracked_hooks/$(basename $0) ]; then
    tracked_hooks/$(basename $0) "$@" || exit $?
fi
安装脚本会将所有预先存在的钩子移到一边(将
.local
附加到它们的名称中),并将所有已知的钩子名称符号链接到上述脚本:

#!/bin/bash
HOOK_NAMES="applypatch-msg pre-applypatch post-applypatch pre-commit prepare-commit-msg commit-msg post-commit pre-rebase post-checkout post-merge pre-receive update post-receive post-update pre-auto-gc"
# assuming the script is in a bin directory, one level into the repo
HOOK_DIR=$(git rev-parse --show-toplevel)/.git/hooks

for hook in $HOOK_NAMES; do
    # If the hook already exists, is executable, and is not a symlink
    if [ ! -h $HOOK_DIR/$hook -a -x $HOOK_DIR/$hook ]; then
        mv $HOOK_DIR/$hook $HOOK_DIR/$hook.local
    fi
    # create the symlink, overwriting the file if it exists
    # probably the only way this would happen is if you're using an old version of git
    # -- back when the sample hooks were not executable, instead of being named ____.sample
    ln -s -f ../../bin/hooks-wrapper $HOOK_DIR/$hook
done
从中,可以使用以下机制之一更新每个新创建的git repo的.git/hooks目录:

模板目录包含将被删除的文件和目录 创建$GIT_目录后将其复制到该目录

模板目录将是以下目录之一(按顺序):

  • 使用--template选项给出的参数

  • $GIT_TEMPLATE_DIR环境变量的内容

  • init.templateDir配置变量;或

  • 默认模板目录:/usr/share/git core/templates

npm包处理得很好,允许您在package.json中指定预提交挂钩。

存储在项目中,并在构建中安装 正如其他人在回答中所说,如果您的钩子是特定于您的特定项目的,那么就将它们包含在项目本身中,由git管理。我会更进一步地说,考虑到使用单个脚本或命令构建项目是一种很好的做法,应该在构建过程中安装钩子

我写了一篇关于,如果你有兴趣更深入地阅读这篇文章

Java&Maven 完整免责声明;我编写了下面描述的Maven插件。

如果您正在使用Maven为Java项目处理构建管理,下面的Maven插件将处理从项目中的某个位置安装挂钩的问题

将所有Git钩子放在项目的一个目录中,然后配置
pom.xml
以包含以下插件声明、目标和配置

<build>
  <plugins>
    <plugin>
      <groupId>com.rudikershaw.gitbuildhook</groupId>
      <artifactId>git-build-hook-maven-plugin</artifactId>
      <configuration>
        <gitConfig>
          <!-- The location of the directory you are using to store the Git hooks in your project. -->
          <core.hooksPath>hooks-directory/</core.hooksPath>
        </gitConfig>
      </configuration>
      <executions>
        <execution>
          <goals>       
            <!-- Sets git config specified under configuration > gitConfig. -->
            <goal>configure</goal>
          </goals>
        </execution>
      </executions>
    </plugin>
      <!-- ... etc ... -->
  </plugins>
</build>
其他
此外,对于Python项目、Ruby项目以及Ruby或Node项目,还有一个脚本add-git-hook.sh,您可以将它作为存储库中的常规文件发送,并可以执行它以将git钩子附加到脚本文件中。调整要使用的钩子(预提交、后提交、预推等)以及cat中钩子的定义

#!/usr/bin/bash
# Adds the git-hook described below. Appends to the hook file
# if it already exists or creates the file if it does not.
# Note: CWD must be inside target repository

HOOK_DIR=$(git rev-parse --show-toplevel)/.git/hooks
HOOK_FILE="$HOOK_DIR"/post-commit

# Create script file if doesn't exist
if [ ! -e "$HOOK_FILE" ] ; then
        echo '#!/usr/bin/bash' >> "$HOOK_FILE"
        chmod 700 "$HOOK_FILE"
fi

# Append hook code into script
cat >> "$HOOK_FILE" <<EOF

########################################
# ... post-commit hook script here ... #
########################################

EOF
#/usr/bin/bash
#添加下面描述的git钩子。附加到钩子文件
#如果该文件已存在,或者如果不存在,则创建该文件。
#注意:CWD必须位于目标存储库中
HOOK_DIR=$(git rev parse--show top level)/.git/hooks
HOOK_FILE=“$HOOK_DIR”/post commit
#如果不存在,则创建脚本文件
如果[!-e“$HOOK_文件”];然后
回音/usr/bin/bash'>>“$HOOK\u文件”
chmod 700“$HOOK_文件”
fi
#将钩子代码附加到脚本中

cat>>“$HOOK\u FILE”现在,您可以执行以下操作将受版本控制的目录设置为您的git hooks目录,例如,
MY\u REPO\u DIR/.githooks
将是

git config --local core.hooksPath .githooks/

仍然不能直接执行,但是,如果您在自述文件(或其他文件)中添加注释,这需要每个开发人员付出最少的努力。

您可以使用托管解决方案进行预提交钩子管理,如。 或者是服务器端git钩子的集中式解决方案,比如。 它具有内置的策略,如:

  • 检测和预防
  • 执行适当的命令
  • 强制-在请求名称/提交消息中提及票证号
  • 它不会取代您所有的钩子,但它可能会帮助您的开发人员使用最明显的钩子,而无需在每个应用程序上安装钩子 开发人员计算机/回购


    免责声明:我是Datrees的创始人之一,负责基于Composer的PHP项目,您可以自动分发给工程师。下面是预提交和提交消息挂钩的示例

    创建一个
    hooks
    文件夹,然后在composer.json中:

     },
     "scripts": {
         "post-install-cmd": [
             "cp -r 'hooks/' '.git/hooks/'",
             "php -r \"copy('hooks/pre-commit', '.git/hooks/pre-commit');\"",
             "php -r \"copy('hooks/commit-msg', '.git/hooks/commit-msg');\"",
             "php -r \"chmod('.git/hooks/pre-commit', 0777);\"",
             "php -r \"chmod('.git/hooks/commit-msg', 0777);\"",
         ],
    

    然后,您甚至可以在项目继续时更新它们,因为每个人都在定期运行
    composer install

    我将
    chmod+x.git/hooks/*
    添加到您的
    bin/create hook-symlinks
    中以使用它。@guneysus您不应该需要它,因为钩子应该已经是可执行的(应该以这种方式进行检查),并且链接不需要任何特殊权限,获取hook dir的更好方法是
    hook\u dir=$(git rev parse--show toplevel)/.git/hooks
     },
     "scripts": {
         "post-install-cmd": [
             "cp -r 'hooks/' '.git/hooks/'",
             "php -r \"copy('hooks/pre-commit', '.git/hooks/pre-commit');\"",
             "php -r \"copy('hooks/commit-msg', '.git/hooks/commit-msg');\"",
             "php -r \"chmod('.git/hooks/pre-commit', 0777);\"",
             "php -r \"chmod('.git/hooks/commit-msg', 0777);\"",
         ],