在git`pre-push` hook

时间:2016-01-01 15:58:23

标签: git bash github githooks

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

1)检查我们是否正在推动掌握,

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

背景:我正在使用webpack +做出反应,使用leaflet.js构建地图。我想让实用程序repo始终保存最新编译的.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),但我不知道如何使这项工作。我不断变得奇怪的行为,主要仓库的自述文件意外地被提交到实用程序仓库,或者我将获得删除主仓库中的文件的实用程序仓库的提交(这些文件在实用程序中不存在)回购)。

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

我应该注意上面的shell脚本可以自己正常工作 - 所以如果我bash pre-push我得到了我想要的行为。

1 个答案:

答案 0 :(得分:1)

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

我相信预推钩是从您正在考虑的目录中运行的(在大多数情况下:如果您从git --work-tree=<path>完全在<path>以外的地方使用$GIT_DIR 1}}),所以它只是造成直接问题的git rev-parse设置。

不太明显但仍然非常重要的是,您使用$ git push origin zog~3:master 找到的当前分支不一定是被推送到的分支,并且提交被推送-from不一定是任何分支的一角。例如:

master

告诉git要求远程设置他们的zog~3到任何提交ID rye的结果,即使您当前在分支<local ref> SP <local sha1> SP <remote ref> SP <remote sha1> LF 上。您可能不关心处理这种情况,但 可以处理:预推钩在其标准输入上接收以下形式的一系列行:

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

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

...

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

最棘手的一点是,如果你想使用提交的东西,遥控器将其标签设置为(假设推送最终成功 - 这不是你可以在钩子中告诉的东西!),你不能依赖当前工作树的文件:

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

要完成检查或使用它们的全面工作,您需要将所有这些文件提取到临时工作区(这实际上非常简单,仅$lsha $tmpdir是您从输入中读取的SHA-1,$GIT_INDEX_FILE是一个合适的临时工作树,一旦您完成它就会删除;但是您可能还需要覆盖sh同样)。

忽略大部分内容,以下非常俗气(和未经测试)的脚本(用#! /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 编写,但应该可以正常使用bash)可能会在那里大部分时间:

localhost:3000/api/v1/posts