利用git hooks,在服务器端每次接收到push的时候进行文件信息检查,若超过限制则拒绝提交。

具体实现:在update hook中对提交的文件进行检查,利用git log命令查询所有新提交的分支,利用git cat-file 命令递归查询文件树、查询文件大小,若超限则返回1拒绝提交。

#!/bin/bash
#
# An example hook script to block unannotated tags from entering.
# Called by "git receive-pack" with arguments: refname sha1-old sha1-new
#
# To enable this hook, rename this file to "update".
#
# Config
# ------
# hooks.allowunannotated
#   This boolean sets whether unannotated tags will be allowed into the
#   repository.  By default they won't be.
# hooks.allowdeletetag
#   This boolean sets whether deleting tags will be allowed in the
#   repository.  By default they won't be.
# hooks.allowmodifytag
#   This boolean sets whether a tag may be modified after creation. By default
#   it won't be.
# hooks.allowdeletebranch
#   This boolean sets whether deleting branches will be allowed in the
#   repository.  By default they won't be.
# hooks.denycreatebranch
#   This boolean sets whether remotely creating branches will be denied
#   in the repository.  By default this is allowed.
#

# --- Command line
refname="$1"
oldrev="$2"
newrev="$3"

# --- Safety check
if [ -z "$GIT_DIR" ]; then
    echo "Don't run this script from the command line." >&2
    echo " (if you want, you could supply GIT_DIR then run" >&2
    echo "  $0 <ref> <oldrev> <newrev>)" >&2
    exit 1
fi

if [ -z "$refname" -o -z "$oldrev" -o -z "$newrev" ]; then
    echo "usage: $0 <ref> <oldrev> <newrev>" >&2
    exit 1
fi

# check commit file size (MB)
export maxFileSize=20
export warningFileSize=10
# check repo size (GB)
export maxRepoSize=3
export warningRepoSize=1


# echo "tree sha"
# tree_sha=`git cat-file -p $newrev | grep tree | awk '{print $2}'`
# echo $tree_sha


IFS=$'\n\n'

# echo "tree info "
# git cat-file -p $tree_sha

export totalRepoSize=0

check_file_size(){
    # echo "$1"
    for line in `git cat-file -p $1`;
    do
        # echo "line: $line"
        file_type=`echo $line | awk '{print $2}'`
        file_sha=`echo $line | awk '{print $3}'`
        # echo "file_type: $file_type"
        # echo "file_sha: $file_sha"
        if [[ $file_type == "tree" ]];then
            check_file_size $file_sha $2
        else
            # echo `git cat-file -s $file_sha`
            # echo $(($maxFileSize * 1024 * 1024))
            file_size=`git cat-file -s $file_sha`
            totalRepoSize=$(($totalRepoSize + $file_size))
            if  [ $file_size -ge $(($maxFileSize * 1024 * 1024)) ];then
                file_name=`echo $line | awk '{print $4}'`
                echo -e "\e[1;31mERROR:\033[0m File '$file_name' size $(($file_size / 1024 / 1024)) MB >= $maxFileSize MB! Try reduce file size."
                echo -e "\e[1;36mFile SHA:\033[0m\t $file_sha"
                echo -e "\e[1;36mCommit SHA:\033[0m\t $2"
                exit 1
            fi
            if  [ $file_size -ge $(($warningFileSize * 1024 * 1024)) ];then
                file_name=`echo $line | awk '{print $4}'`
                echo -e "\e[1;33mWARNING:\033[0m File '$file_name' size $(($file_size / 1024 / 1024)) MB >= $warningFileSize MB! Don't commit too many large files!"
                echo -e "\e[1;36mFile SHA:\033[0m\t $file_sha"
                echo -e "\e[1;36mCommit SHA:\033[0m\t $2"
            fi
        fi
    done
}

# check_file_size $tree_sha

if [[ $newrev == "0000000000000000000000000000000000000000" ]];then # delete a branch
	exit 0
fi

export commits=`git log HEAD..$newrev | grep "commit" | awk '{print $2}'`
# echo $commits

for commit in $commits
do
    tree_sha=`git cat-file -p $commit | grep tree | awk '{print $2}'`
    
    # echo $commit
    # echo $tree_sha
    
    check_file_size $tree_sha $commit
done

# echo "totalRepoSize: $totalRepoSize"
if  [ $(($totalRepoSize / 1024)) -ge $(($maxRepoSize * 1024 * 1024)) ];then
    echo -e "\e[1;31mERROR:\033[0m Repository size > $maxRepoSize GB! Try reduce repo size!"
    exit 1
fi

# echo "totalRepoSize: $totalRepoSize"
if  [ $(($totalRepoSize / 1024)) -ge $(($warningRepoSize * 1024 * 1024)) ];then
    echo -e "\e[1;33mWARNING:\033[0m Repository size > $warningRepoSize GB!"
    exit 1
fi

# --- Finished
exit 0