【问题标题】:Can a pre-commit Git hook zip a directory and add it to the repository?预提交 Git 挂钩可以压缩目录并将其添加到存储库吗?
【发布时间】:2015-02-06 01:32:00
【问题描述】:

我正在开发一个 Wordpress 插件。我的开发目录包含许多特定于开发的东西(例如 Grunt 文件、Sass 文件、git 存储库本身等)。

显然,我不想分发这个包含所有这些开发文件的文件夹;人们在下载我的 Wordpress 插件时不想要几 MB 的 Grunt 文件。

不过,到目前为止,我的“发布”过程一直很麻烦:

  1. 提交 Git 更改
  2. 压缩整个文件夹
  3. 打开 zip 文件并删除 .git 文件夹、grunt 文件和所有其他开发特定文件
  4. 释放新的 zip

我不知道实现这一点的最佳方法,但我非常对 Git 挂钩有点熟悉,我有这样的想法:我可以设置一个 Git 挂钩吗?是否只将所需的生产文件压缩到 ZIP 文件中并将其与 repo 一起存储?这样,每次我提交时,它都会自动创建一个新的发布 ZIP。

这可能吗?如果是这样,有人可以指出我正确的方向吗?

哦,我也在 Windows 上 (・_・;)。所以我希望有办法在 Windows 上做到这一点。

【问题讨论】:

    标签: wordpress git githooks


    【解决方案1】:

    我不能代表 Windows,但是:

    1. 技术上可以在 pre-commit 挂钩中执行此类操作。
    2. 不要。

    修改“您将提交的内容”的预提交挂钩很烦人(如果没有别的,它违反了“最小惊讶规则”,您的版本控制系统只是存储您告诉它存储的版本)。除此之外,存储大的预压缩二进制文件会干扰 git 尝试在包文件中节省空间,并且会导致存储库快速膨胀、性能低下、内存不足等。 ZIP 存档预压缩的二进制文件,因此会表现不佳。

    一般来说,处理发布的更合理的“hook-y”方式是设置一个“发布服务器”,您可以将新发布推送到该“发布服务器”,并让推送触发归档生成。 (有一些方法可以在没有单独的服务器/存储库的情况下做到这一点,您可以采用更拉式的方式来实现,但推式很容易说明。)

    [编辑:我最初考虑过git archive,但没有意识到你可以方便地排除文件,所以写在下面。所以,jthill's answer 更好,应该是首选。在某些情况下,由于某种原因,git archive 可能不会这样做。]

    例如,这里有一个服务器端post-receive 钩子代码片段,它检查名称与release* 匹配的分支是否已被推送,如果是,则调用具有分支名称的shell 函数(一次对于每个这样的分支):

    #! /bin/sh
    
    NULL_SHA1=0000000000000000000000000000000000000000
    
    scan()
    {
        local oldsha newsha fullref shortref
        local optype
    
        while read oldsha newsha fullref; do
            case $oldsha,$newsha in
            $NULL_SHA1,*) optype=create;;
            *,$NULL_SHA1) optype=delete;;
            *)            optype=update;;
            esac
            case $fullref in
            refs/heads/*)
                reftype=branch
                shortref=${fullref#refs/heads/}
                ;;
            *)
                reftype=other
                shortref=fullref
                ;;
            esac
    
            case $optype,$reftype,$shortref in
            create,branch,release*|update,branch,release*)
                do_release $shortref;;
            esac
        done
    }
    
    scan
    

    (以上大部分内容都是样板文件,我已将其简化为基本内容)。您必须编写 do_release 函数,它可能类似于(完全未经测试):

    do_release()
    {
        local tmpdir=/tmp/build.$$ # or use mktemp -d
    
        # $tmpdir/index is git's index; $tmpdir/t is the work tree
        trap "rm -rf $tmpdir; exit 1" 1 2 3 15
        rm -rf $tmpdir
        mkdir $tmpdir/t
    
        GIT_INDEX_FILE=$tmpdir/index GIT_WORK_TREE=$tmpdir/t git checkout $1
    
        # now clean out grunt files and make zip archive
        (cd $workdir/t; rm -rf grunt; zip ../t.zip .)
    
        # put completed zip archive in export location, name it
        # based on the branch name
        mv $workdir/t.zip /place/where/zip/files/live/$1.zip
    
        # clean up temp dir now, and no longer need to clean up
        # on signal related abort
        rm -rf $tmpdir
        trap - 1 2 3 15
    }
    

    【讨论】:

    • 感谢您的宝贵信息!
    【解决方案2】:

    实际上有一个命令,git archive

    git archive master -o wizzo-v1.13.0.zip
    

    参见EXAMPLES 部分,您可以选择路径、为其添加前缀、通过输出扩展定义自定义后处理,以及一些更小的调整。

    另请参阅ATTRIBUTES 部分:您可以给文件——实际上是任意模式——一个export-ignore 属性以将它们从档案中排除。

    它有很多更方便的花花公子,您可以从远程存储库获取存档,扩展任意 git log --pretty=format: 占位符,git 联机帮助页绝对值得您花时间投资。

    【讨论】:

    • 哇,太棒了!是否可以预先配置要排除的文件列表(例如通过将它们保存在文件中),而不必将它们作为参数添加到每个 git 归档请求中?
    • 根据文档,它具有正路径说明符(列出特定目录等,它们将被包括在内,而所有其他目录将被排除)但没有负说明符。因此,上面有临时结账的更迂回方法......
    • 是的,您可以使用 git 属性(与通常的模式匹配不同)来标记文件以进行特殊归档处理。
    • @torek 我也忘记了,直到 OP 直接询问才记得。
    • 哈哈,实际上我刚刚阅读了 git 属性,并在有人注意到之前就回来删除我愚蠢的评论/问题 >.> 但我来不及!尽管如此,感谢额外的 cmets 和重要信息!这些似乎是一条不错的路线。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-10-16
    • 2013-12-24
    • 1970-01-01
    • 2017-11-09
    • 1970-01-01
    • 2015-12-31
    相关资源
    最近更新 更多