【问题标题】:How to limit file size on commit?如何在提交时限制文件大小?
【发布时间】:2017-01-27 07:48:39
【问题描述】:

提交时是否有限制文件大小的选项?

例如:文件大小超过 500K 会产生警告。超过 10M 的文件大小将停止提交。

我完全了解this question,这在技术上会造成重复,但答案仅提供了一个推送解决方案,这对于我的要求来说为时已晚。

【问题讨论】:

  • @bbodenmiller,这不是重复的。你有没有把我的问题读到最后?我提到了你在上一句中指定的问题。
  • @user2476373 虽然我理解您希望找到一个在推送之前检查文件大小的解决方案的愿望,但您应该明白这是对多人强制​​执行此限制的唯一可靠方法. pre-commit 钩子是 local 钩子,因此不与存储库一起分发。在同事的机器上,这个钩子将不存在。你可能想要both,一个本地的pre-commit-hook 和一个远程的update-hook。

标签: linux git github filesize


【解决方案1】:

只是想评论@Leon 提供的解决方案太棒了。如果一个空目录开始尝试被跟踪,我遇到了一个小障碍,它中止了。所以我不得不添加

[ -d "$f" ] && continue 

ls-files 命令之前有避免错误。

我更愿意发表评论,因为这不是答案,但我没有声誉积分。

注意:我知道 git 'ignores' 目录,但显然不是在 pre-commit 挂钩运行之前。

【讨论】:

    【解决方案2】:

    @Leon 脚本的更短的 bash 特定版本,它以人类可读的格式打印文件大小。 --diff-filter=d 选项需要更新的 git:

    #!/bin/bash
    hard_limit=$(git config hooks.filesizehardlimit)
    soft_limit=$(git config hooks.filesizesoftlimit)
    : ${hard_limit:=10000000}
    : ${soft_limit:=1000000}
    
    status=0
    
    bytesToHuman() {
      b=${1:-0}; d=''; s=0; S=({,K,M,G,T,P,E,Z,Y}B)
      while ((b > 1000)); do
        d="$(printf ".%01d" $((b % 1000 * 10 / 1000)))"
        b=$((b / 1000))
        let s++
      done
      echo "$b$d${S[$s]}"
    }
    
    # Iterate over the zero-delimited list of staged files.
    while IFS= read -r -d '' file ; do
      hash=$(git ls-files -s "$file" | cut -d ' ' -f 2)
      size=$(git cat-file -s "$hash")
    
      if (( $size > $hard_limit )); then
        echo "Error: Cannot commit '$file' because it is $(bytesToHuman $size), which exceeds the hard size limit of $(bytesToHuman $hard_limit)."
        status=1
      elif (( $size > $soft_limit )); then
        echo "Warning: '$file' is $(bytesToHuman $size), which exceeds the soft size limit of $(bytesToHuman $soft_limit). Please double check that you intended to commit this file."
      fi
    done < <(git diff -z --staged --name-only --diff-filter=d)
    exit $status
    

    与其他答案一样,这必须以.git/hooks/pre-commit 的执行权限保存。

    示例输出:

    Error: Cannot commit 'foo' because it is 117.9MB, which exceeds the hard size limit of 10.0MB.
    

    【讨论】:

    • 它有什么改进?
    • 在描述中澄清。它并不是天生就更好,只是更短更简单,文件大小显示更人性化。
    • 这比今天选择的答案更好,因为 munge 逻辑似乎不适用于当前的 git 输出?这使用了 git 参数来避免 unmunge 的需要。
    【解决方案3】:

    这个预提交钩子会检查文件大小:

    .git/hooks/pre-commit

    #!/bin/sh
    hard_limit=$(git config hooks.filesizehardlimit)
    soft_limit=$(git config hooks.filesizesoftlimit)
    : ${hard_limit:=10000000}
    : ${soft_limit:=500000}
    
    list_new_or_modified_files()
    {
        git diff --staged --name-status|sed -e '/^D/ d; /^D/! s/.\s\+//'
    }
    
    unmunge()
    {
        local result="${1#\"}"
        result="${result%\"}"
        env echo -e "$result"
    }
    
    check_file_size()
    {
        n=0
        while read -r munged_filename
        do
            f="$(unmunge "$munged_filename")"
            h=$(git ls-files -s "$f"|cut -d' ' -f 2)
            s=$(git cat-file -s "$h")
            if [ "$s" -gt $hard_limit ]
            then
                env echo -E 1>&2 "ERROR: hard size limit ($hard_limit) exceeded: $munged_filename ($s)"
                n=$((n+1))
            elif [ "$s" -gt $soft_limit ]
            then
                env echo -E 1>&2 "WARNING: soft size limit ($soft_limit) exceeded: $munged_filename ($s)"
            fi
        done
    
        [ $n -eq 0 ]
    }
    
    list_new_or_modified_files | check_file_size
    

    以上脚本必须保存为.git/hooks/pre-commit并启用执行权限(chmod +x .git/hooks/pre-commit)。

    默认的软(警告)和硬(错误)大小限制设置为 500,000 和 10,000,000 字节,但可以分别通过 hooks.filesizesoftlimithooks.filesizehardlimit 设置覆盖:

    $ git config hooks.filesizesoftlimit 100000
    $ git config hooks.filesizehardlimit 4000000
    

    【讨论】:

    • 这很好,但你想read 没有-r 因为git diff --name-status 编码文件名。 (另一种选择是使用 -z 和 bash 使用零终止的能力,但这限制了你使用 bash。)你也可以只使用 git diff --name-only --diff-filter=d (假设 Git 版本足够新,可以理解小写 d,否则拼写出来使用ACMRTUXB,尽管其中一些无论如何都不会发生),然后消除sed
    • @torek read without -r as git diff --name-status 编码文件名 不知道这个.在脚本中添加了文件名的解码。
    • echo -e 不被 shell 普遍支持,所以如果这个脚本失败(它在最近的 mac bash 版本 3.2.57 上失败)那么 -e 标志需要被删除(env echo - e 和 env echo -E) 或为了使其更便携,应将调用 echo -e / -E 替换为 printf 例如: env printf "$result" and env printf 1>&2 '\n%s\n' “错误:硬大小...”
    • 脚本实际上对我不起作用,出现错误: 致命:不是有效的对象名称 .git/hooks/pre-commit: 27: [: Illegal number: .git/hooks/预提交:31:[:非法数字:
    【解决方案4】:

    您需要实现您已经在pre-commit hook 中寻找的eis script

    从文档中,我们了解到 预提交挂钩

    不带参数,在获取建议的提交日志消息并进行提交之前调用。从该脚本中以非零状态退出会导致 git commit 命令在创建提交之前中止。

    基本上,调用钩子来检查是否允许用户提交他的更改。

    原来eisother post上制作的脚本变成了

    #!/bin/bash
    # File size limit is meant to be configured through 'hooks.filesizelimit' setting
    filesizelimit=$(git config hooks.filesizelimit)
    
    # If we haven't configured a file size limit, use default value of about 10M
    if [ -z "$filesizelimit" ]; then
            filesizelimit=10000000
    fi
    
    # You specify a warning limit
    filesizewarning=500000
    
    # With this command, we can find information about the file coming in that has biggest size
    # We also normalize the line for excess whitespace
    biggest_checkin_normalized=$(git ls-tree --full-tree -r -l HEAD | sort -k 4 -n -r | head -1 | sed 's/^ *//;s/ *$//;s/\s\{1,\}/ /g' )
    
    # Based on that, we can find what we are interested about
    filesize=`echo $biggest_checkin_normalized | cut -d ' ' -f4,4`
    
    # Actual comparison
    # To cancel a push, we exit with status code 1
    # It is also a good idea to print out some info about the cause of rejection
    if [ $filesize -gt $filesizelimit ]; then
    
            # To be more user-friendly, we also look up the name of the offending file
            filename=`echo $biggest_checkin_normalized | cut -d ' ' -f5,5`
    
            echo "Error: Too large push attempted." >&2
            echo  >&2
            echo "File size limit is $filesizelimit, and you tried to push file named $filename of size $filesize." >&2
            echo "Contact configuration team if you really need to do this." >&2
            exit 1
    elif [ $filesize -gt $filesizewarning ]; then
            echo "WARNING ! A file size is bigger that $filesizewarning"
    fi
    exit 0
    

    【讨论】:

    • 此脚本检查已提交文件的大小(对应于 HEAD),因此不适合作为预提交挂钩
    【解决方案5】:

    有一个通用的预提交挂钩。您可以编写一个脚本来检查文件大小,然后接受或拒绝提交。然而,Git 让用户能够从命令行类型“git help hooks”绕过检查以获取更多信息。这是关于 pre-commit 钩子的相关信息。

    预提交

    这个钩子由 git commit 调用,可以通过 --no-verify 选项绕过。它不带参数,并在获取建议的提交日志消息并进行提交之前被调用。从该脚本中以非零状态退出会导致 git 提交中止。

    【讨论】:

    • 我看不到答案。缺少链接吗?
    猜你喜欢
    • 1970-01-01
    • 2016-02-05
    • 2020-07-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-30
    • 2019-07-12
    相关资源
    最近更新 更多