Git 远程/共享预提交挂钩

发布于 2024-09-19 04:56:37 字数 69 浏览 4 评论 0原文

将一个官方存储库作为远程存储库,并从其克隆多个本地存储库,是否可以在该主存储库上编写预提交挂钩脚本并在其所有克隆上强制执行?

With a one official repository as the remote, and multiple local repositories cloned from it, can a pre-commit hook be scripted on that main repository and be enforced on all clones of it?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

三五鸿雁 2024-09-26 04:56:37

我不这么认为,因为钩子不会被克隆。
可能是如果该挂钩脚本本身是版本化的,然后链接到克隆服务器中的(符号链接)(前提是它们的操作系统支持该链接功能)。

或者,如果挂钩是 git 模板的一部分用于创建克隆的目录(这只能确保它们存在于克隆存储库中,不能保证它们实际被使用和执行)。

但我不认为有任何“核心”方式来执行提交。


正如 Jefromi 在评论中更清楚地解释的那样(强调我的):

我认为这确实违背了 git 存储库的想法,即与存储库一起分发强制挂钩。
我的克隆是我的存储库。我应该能够以我喜欢的方式使用 git,包括选择是否运行钩子。
(从安全角度来看,这确实有点可怕 - 每当我运行某些 git 命令时,没有人应该有能力强迫我执行某些脚本。)

我同意这一评论,并且只看到了强制执行的方法在给定的专门存储库中本地应用的规则。
例如,您不会直接推送到中央存储库,而是首先推送到 QA 存储库,该存储库仅在遵循某些规则时才会接受您的提交。如果是,那么 QA 存储库会将您的提交推送到中央存储库。

直接源自我刚才提到的另一个例子是“无服务器连续与 Git 集成”,这是一种在将它们推送到任何地方之前强制执行本地私有构建的方法。

I don't think so, as hooks are not cloned.
May be if that hook script is itself versioned, and then link to (symbolic link) in the clone servers (provided their OS support that link feature).

Or maybe if the hooks are part of a git template directory used for creating the clones (that would only ensure their presences in the clone repo, that would not guarantee they are actually used and executed).

But I don't think there is any "central" way to enforce a commit.


As Jefromi explains even more clearly in the comments (emphasis mine):

I think it really goes against the idea of a git repository to have enforced hooks distributed with the repo.
My clone is my repository. I should be able to use git on it however I like, including choosing whether or not to run hooks.
(And from a security standpoint, that'd be really kind of scary - no one should have the ability to force me to execute certain scripts whenever I run certain git commands.)

I agree with that comment, and have only seen ways to enforce rules applied locally, in a given specialized repo.
For instance, you wouldn't push to the central repo directly, but would first push to a QA repo which would accept your commit only if it follows certain rules. If it does, then the QA repo will push your commit to the central repo.

Another illustration directly derived from what I just mentioned would be "Serverless Continuous Integration with Git", a way to enforce locally private build that works before pushing them anywhere.

弱骨蛰伏 2024-09-26 04:56:37

您不能在人们的本地存储库上强制使用预提交挂钩,但在您的中央存储库中您仍然可以运行预接收挂钩。

F. ex 我需要确保提交消息遵守某些规则(用于 trac 集成等)
所以我使用了以下预接收钩子,它检查推送到中央存储库的每个提交消息,如果不正确,将拒绝推送。

#!/bin/sh
while read rev_old rev_new ref
do
    MALFORMED="$(git rev-list --oneline $rev_old..$rev_new | egrep -v '#[0-9]+' |  awk '{print $1}' )"
    if [ x"$MALFORMED" != x ]
    then
        echo Invallid commit message on $MALFORMED
        exit 1
    fi
done

有关更多信息,请参阅 f.ex https://git-scm。 com/book/en/v2/Customizing-Git-Git-Hooks

You can not have the pre-commit hook forced on peoples local repositories, but in your central repo you can still run a pre-receive hook.

F. ex I needed to be sure the commit messages obeyed certain rules (for trac integration etc)
so I used following pre-receive hook, which checks every commit messages being pushed to the central repository, and will deny the push if it is not welformed.

#!/bin/sh
while read rev_old rev_new ref
do
    MALFORMED="$(git rev-list --oneline $rev_old..$rev_new | egrep -v '#[0-9]+' |  awk '{print $1}' )"
    if [ x"$MALFORMED" != x ]
    then
        echo Invallid commit message on $MALFORMED
        exit 1
    fi
done

for more info see f.ex https://git-scm.com/book/en/v2/Customizing-Git-Git-Hooks

趁微风不噪 2024-09-26 04:56:37

两个选项:

1. 使用 Husky

如果您正在编写 JavaScript,最好的方法是使用 Husky。 Husky 有一个 postInstall 脚本,可以设置和管理你的 githooks。然后,您可以在 package.json 或 husky 点文件中配置预提交和预推送脚本。

您可以使用它来运行任意脚本。我通常会预推送yarn lintyarn test

2. 在 git.config 中设置 core/hooksPath,然后在您的存储库中包含 /hooks

如果您不使用 JavaScript,或者您无法使用 Husky,您可以将提交钩子克隆到开发人员计算机上并将其签入一个存储库,但你不能强迫开发人员运行它们。

要签入您的钩子,请在存储库中的某个位置创建一个 hooks 目录。然后将您的钩子放在那里,而不是通常的 .git/hooks 目录。这是您可以强制执行的部分。

另一部分取决于开发商的商誉。要将 hooks 文件夹设置为 hooksPath,每个开发人员都必须运行:

git config core.hooksPath hooks

现在,hooks 文件夹中的所有钩子都将按照您的预期运行。

Two options:

1. Use Husky

If you are writing JavaScript, the best way to do this is with Husky. Husky has a postInstall script that will set up and manage your githooks. You can then configure precommit and prepush scripts in your package.json or a husky dotfile.

You can use this to run arbitrary scripts. I typically yarn lint and yarn test prepush.

2. Set core/hooksPath in git.config, then include /hooks in your repo

If you are not using JavaScript, or you cannot use Husky, you can clone commit hooks onto developer machines and check them into a repo, but you cannot force developers to run them.

To check in your hooks, create a hooks directory somewhere in your repo. Then put your hooks there instead of the usual .git/hooks directory. This is the part you can enforce.

The other part depends on developer goodwill. To set your hooks folder as the hooksPath, each developer must run:

git config core.hooksPath hooks

Now all the hooks in the hooks folder will run as you would expect.

初见 2024-09-26 04:56:37

可以在该主存储库上编写预提交挂钩脚本并在其所有克隆上强制执行吗?

来自 githooks(5)

    pre-commit
      This hook is invoked by git commit, and can be bypassed with
      --no-verify option.

由于该钩子很容易被绕过,看来你的问题的答案是“否”。

另外,由于 .git/hooks 目录没有被克隆,因此似乎没有一种机制将其推送到客户端。

can a pre-commit hook be scripted on that main repository and be enforced on all clones of it?

From githooks(5):

    pre-commit
      This hook is invoked by git commit, and can be bypassed with
      --no-verify option.

Since the hook can easily be bypassed, it seems the answer to your question is "no".

Also, since the .git/hooks directory is not cloned, there does not seem to be a mechanism to push it to the client.

高跟鞋的旋律 2024-09-26 04:56:37

这里有非常非常的答案。如今这绝对是可能的。

从 Git 2.9 左右开始,配置 core.hooksPath 可用。根据 git 文档

core.hooksPath

默认情况下,Git 会在 $GIT_DIR/hooks 目录中查找您的钩子。将其设置为不同的路径,例如 /etc/git/hooks,Git 会尝试在该目录中找到您的钩子,例如 /etc/git/hooks/pre-receive > 而不是在 $GIT_DIR/hooks/pre-receive 中。

路径可以是绝对路径,也可以是相对路径。相对路径被视为相对于运行钩子的目录(请参阅 githooks 的“描述”部分[5])。

如果您想要集中配置 Git 挂钩而不是在每个存储库上配置它们,或者作为 init.templateDir< 的更灵活和集中的替代方案,此配置变量非常有用/code> 您更改了默认挂钩的位置。


这意味着您可以在客户端计算机之间共享 Git 挂钩(可能使用项目内的非 .git 文件夹,或使用本地克隆的专用 Git 存储库,或使用 OneDrive 或 Dropbox 等同步软件)只需将 core.hooksPath 配置设置为该(共享)文件夹即可。

Very very old answers here. This is definitely possible these days.

Since Git 2.9 or so, the config core.hooksPath is available. Per the git documentation:

core.hooksPath

By default Git will look for your hooks in the $GIT_DIR/hooks directory. Set this to different path, e.g. /etc/git/hooks, and Git will try to find your hooks in that directory, e.g. /etc/git/hooks/pre-receive instead of in $GIT_DIR/hooks/pre-receive.

The path can be either absolute or relative. A relative path is taken as relative to the directory where the hooks are run (see the "DESCRIPTION" section of githooks[5]).

This configuration variable is useful in cases where you’d like to centrally configure your Git hooks instead of configuring them on a per-repository basis, or as a more flexible and centralized alternative to having an init.templateDir where you’ve changed default hooks.

This means that you can share Git hooks between client machines (perhaps using a non-.git folder inside the project, or using a dedicated Git repository locally cloned, or using sync software such as OneDrive or Dropbox) by just setting the core.hooksPath config to that (shared) folder.

还不是爱你 2024-09-26 04:56:37

假设您的 git 存储库中的源代码具有与其关联的构建系统,您可以配置构建系统来设置预提交挂钩,即通过移动或链接版本控制的预提交挂钩。

我还没有尝试过这个。我在谷歌搜索更好的解决方案时来到这里。

Assuming you have source code in your git repo that has a build system associated with it, you could configure the build system to set up the pre-commit hook, i.e. by moving or linking a pre-commit hook that ~is versioned.

I have not tried this yet. I came here while googling for a better solution.

意犹 2024-09-26 04:56:37

它不是全自动的,但您可以在要添加到 git 的 hooks/ 目录中添加存储库的钩子脚本,然后要求开发人员在克隆后对钩子脚本进行符号链接存储库:

ln -s ../../hooks/pre-commit.sh .git/hooks/pre-commit

在项目自述文件中记录可能效果很好。

It's not fully automatic, but you can add hook scripts for a repo inside a hooks/ directory that you'd add to git, and then ask developers to symlink the hook script(s) once after they clone the repo:

ln -s ../../hooks/pre-commit.sh .git/hooks/pre-commit

Documenting in a project README might work well enough.

眉黛浅 2024-09-26 04:56:37

我创建了一个新文件: pre-commit-hook.sh

#!/usr/bin/env bash
CHANGES=$(git whatchanged ..origin)

if [ ! -z "${CHANGES}" ]; then
    echo "There are changes in remote repository. Please pull from remote branch first."
    exit 1;
fi

exit 0;

这就是我提交到 Git 的方式:

bash pre-commit-hook.sh && git commit -m "<Commit message>"

I create a new file: pre-commit-hook.sh

#!/usr/bin/env bash
CHANGES=$(git whatchanged ..origin)

if [ ! -z "${CHANGES}" ]; then
    echo "There are changes in remote repository. Please pull from remote branch first."
    exit 1;
fi

exit 0;

And this is how I commit to Git:

bash pre-commit-hook.sh && git commit -m "<Commit message>"
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文