一个 pre-commit 的 Git 钩子能否将目录压缩并添加到存储库中?

4
我正在为WordPress插件进行开发。我的开发目录包含许多开发相关的文件(例如Grunt文件、Sass文件、git仓库等)。
显然,我不想分发包含所有这些开发文件的文件夹;当人们下载我的WordPress插件时,他们不需要几MB的Grunt文件。
但迄今为止,我的“发布”过程非常繁琐:
1.提交Git更改 2.压缩整个文件夹 3.打开zip文件并删除.git文件夹、Grunt文件和所有其他开发特定文件 4.发布新zip 我不知道完成这个任务的最佳方法,但我非常模糊地了解Git挂钩,并且我有这样一个想法:能否设置一个Git挂钩,仅将所需的生产文件压缩到ZIP文件中并将其存储到仓库中?这样,每次我提交时,它都会自动创建一个新的发布ZIP文件。
这是否可行?如果是,可以有人指点我吗?
哦还有,我在Windows上(・ _ ・;)。所以我希望有一种在Windows上完成此操作的方法。
2个回答

5

我无法代表Windows,但是:

  1. 在预提交钩子中进行这种操作在技术上是可行的。
  2. 不要这样做。

修改“你将提交的内容”的预提交钩子很烦人(如果什么都没有,它违反了“最少惊讶规则”,即您的版本控制系统仅存储您告诉它要存储的版本)。除此之外,存储大型预压缩二进制文件会干扰git试图在包文件中节省空间的尝试,并会导致快速存储库膨胀、性能差、内存不足等问题。ZIP归档文件是一种预压缩二进制文件,因此会表现得很差。

通常,处理发布的更合理的“钩子式”方法是设置一个“发布服务器”,将新发布推送到其中,并触发存档生成。 (有一些方法可以在没有单独的服务器/存储库的情况下执行此操作,您可以以更拉式的方式执行此操作,但是推送样式易于说明。)

[编辑:我最初考虑使用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
}

感谢提供如此出色的信息! - Pete

4

实际上,这个可以用一个命令来完成,git archive

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

请查看示例部分,您可以选择路径,在它们前面添加前缀,通过输出扩展名定义自定义后处理,并进行一些其他微小的调整。

还请查看属性部分:您可以为文件 - 任意模式真正地 - 提供 export-ignore 属性以将其从存档中排除。

还包括许多有用的功能,您可以从远程存储库获取存档,扩展任意的 git log --pretty=format: 占位符,git manpages 绝对值得投入时间来学习。


哇,太棒了!是否可以预先配置要排除的文件列表(例如通过将它们保存在文件中),而不是必须将它们作为参数添加到每个git存档请求中? - Pete
根据文档,它具有正路径指示器(列出特定目录等,它们将被包含在内,而所有其他目录则被排除),但没有负指示器。因此,采用临时检出的更迂回的方法,如上所述... - torek
1
是的,您可以使用git属性(它基于通常的模式匹配)来标记需要进行特殊归档处理的文件。 - jthill
@torek 我也忘了,直到OP直接问才想起来。 - jthill
哈哈,我刚刚看了一下git属性,正准备在任何人注意到之前删除我的愚蠢评论/问题 >.> 但是我来不及了!尽管如此,感谢您的额外评论和有用信息!这似乎是一个很好的选择。 - Pete
@torek 如果没有使用属性的原因,我认为我会通过在旁路索引中构建树来完成它,( export GIT_INDEX_FILE=$somewhere; git read-tree $commit:; sed 's/^/git rm -r --cached /e' $excludes; git archive \git write-tree`; )`。 - jthill

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接