【问题标题】:commit to utility repo in git `pre-push` hook提交到 git `pre-push` 挂钩中的实用程序仓库
【发布时间】:2016-01-01 15:58:22
【问题描述】:

我想为一个 git repo 设置一个 pre-push 钩子:

1) 检查我们是否正在推送到 master,并且

2) 如果是,运行 webpack,将编译后的 .js 文件复制到另一个 repo,并将编译后的文件提交到实用程序 repo。

背景:我正在使用 webpack + react 使用 leaflet.js 构建地图。我想让实用程序存储库始终保存最新编译的 .js 文件,以便我可以使用 rawgit 在不同的静态站点中获取它。

这是我目前所拥有的(无法正常工作):

#!/bin/bash

current_branch=$(git rev-parse --abbrev-ref HEAD)
if [[ $current_branch == 'master' ]]; then
    webpack
    cp bundle.js ../utility
    eval 'cd ../utility && git add bundle.js && git commit -m "updated east_boston.js"'
fi

我知道有一些自动设置的环境变量(如$GIT_DIR$GIT_INDEX),但我只是不确定如何使这项工作。我不断收到奇怪的行为,主 repo 的 README 将被意外提交到实用程序 repo,或者我将在实用程序 repo 上提交删除主 repo 中的文件(这些文件从未出现在实用程序中回购)。

基本上我不知道如何正确使用 git hooks。我是否使用正确的钩子来满足我的需求?这可能吗?

我应该注意,上面的 shell 脚本本身可以正常工作 - 所以如果我这样做 bash pre-push 我会得到我想要的行为。

【问题讨论】:

  • This page 可能在这里有用。我不知道它与您当前的尝试直接相关,但它应该可以帮助您找到想要工作的方法。

标签: git bash github githooks


【解决方案1】:

这里有很多问题需要解决。第一个是让你绊倒的那个:git hooks 可能从奇怪的目录运行(所以../something 可能不是你所期望的)并且$GIT_DIR 设置为某些东西(通常是..git 取决于他们所在的目录)。移动到另一个目录并运行 git 命令不起作用,因为你在错误的地方结束或$GIT_DIR 指向错误的地方,或两者兼而有之。

我相信 pre-push 挂钩是从您认为它所在的目录运行的(在大多数情况下:如果您从完全位于 <path> 之外的某个地方使用 git --work-tree=<path>,这一切都会崩溃),所以它只是 @导致直接问题的 987654328@ 设置。

不太明显但仍然很重要,您使用git rev-parse 找到的 current 分支不一定是被推送到的分支,而被推送的提交则不是必然是任何分支的尖端。例如:

$ git push origin zog~3:master

告诉 git 要求遥控器将他们的 master 设置为任何提交 ID zog~3 的结果,即使你当前在分支 rye 上。您可能不关心处理这种情况,但它可以处理的:预推送挂钩在其标准输入上接收一系列形式的行:

<local ref> SP <local sha1> SP <remote ref> SP <remote sha1> LF

(这是直接来自文档)。在 sh 或 bash 中处理:

while read lref lsha rref rsha; do
    ...
done

... 部分使用 $lref$lsha 计算出本地引用名称(如果有)和 SHA-1,以及远程引用名称和 SHA-1(远程名称将是完全限定的,因此推送到master 将在$rref 中为您提供refs/heads/master

最棘手的一点是,如果您想要提交远程将设置其标签的内容(假设推送最终成功 - 这不是您可以在挂钩中说出的内容!),您不能依赖当前工作树的文件:

  • 它们可能已被修改但尚未添加和/或提交,或者
  • 它们可能与被推送的提交无关。

要真正彻底地检查或使用它们,您需要将所有这些文件提取到临时工作区(这实际上非常简单,只需 git --work-tree=$tmpdir checkout $lsha 其中$lsha 是您的 SHA-1从输入中读取,$tmpdir 是一个合适的临时工作树,完成后您将其删除;但您可能还需要覆盖 $GIT_INDEX_FILE

不过,忽略其中的大部分内容,以下相当俗气(且未经测试)的脚本(用 sh 编写,但应该可以在 bash 中正常工作)可能会获得大部分内容:

#! /bin/sh

. git-sh-setup  # for require_clean_work_tree() and die()

check_push_to_master()
{
    # we're pushing to remote "master"; reject if
    # the work tree is not clean or is not at the
    # commit-ID ($1) being pushed
    local headsha pushsha

    require_clean_work_tree 'push to master'
    headsha=$(git rev-parse HEAD)
    pushsha=$1
    [ $headsha = $pushsha ] ||
        die "HEAD commit $headsha does not match push to master $pushsha"
}

to_master=false
while read lref lsha rref rsha; do
    case $rref in
    refs/heads/master) check_push_to_master $lsha; to_master=true;;
    esac
done

# if we get here it's OK to try the push, but first...
if $to_master; then
    unset GIT_DIR # make git work normally again
    # set -e      # might want this to make sure any failures => stop push
    webpack
    cp bundle.js ../utility
    cd ../utility && git add bundle.js && git commit -m "updated east_boston.js"
fi
exit 0 # allow push to proceed

【讨论】:

  • 非常感谢您的广泛回答!当我今晚回家时,我会试试这个!
猜你喜欢
  • 2017-12-30
  • 2020-06-24
  • 2014-02-15
  • 1970-01-01
  • 1970-01-01
  • 2015-09-10
  • 1970-01-01
  • 1970-01-01
  • 2021-09-16
相关资源
最近更新 更多