本文目录导读:

- 检查单个文件大小(pre-commit 钩子)
- 检查暂存区总大小(pre-commit 钩子)
- 检查仓库总大小(pre-push 钩子)
- 检查单个文件类型限制(如禁止提交 .exe .zip 等)
- 结合多种检查的完整示例
- 使用 Git LFS 作为替代方案
- 部署钩子的脚本
- 使用建议
Git 钩子脚本检查容量门禁(通常指文件大小、仓库大小或磁盘配额限制)主要针对 pre-commit、commit-msg 或 pre-push 等阶段进行拦截,以下是几种常见场景的实现方案:
检查单个文件大小(pre-commit 钩子)
用途:防止提交超过设定阈值的文件(如大图片、二进制文件等)。
#!/bin/bash
# .git/hooks/pre-commit
# 设置最大文件大小(10MB = 10485760 字节)
MAX_FILE_SIZE=$((10 * 1024 * 1024))
# 获取暂存区(即将提交)的文件列表
staged_files=$(git diff --cached --name-only --diff-filter=A)
# 遍历检查
for file in $staged_files; do
if [ -f "$file" ]; then
file_size=$(stat -f%z "$file" 2>/dev/null || stat -c%s "$file" 2>/dev/null)
if [ "$file_size" -gt "$MAX_FILE_SIZE" ]; then
echo "错误:文件 '$file' 大小为 $(($file_size / 1024 / 1024))MB,超过允许的最大大小 $(($MAX_FILE_SIZE / 1024 / 1024))MB"
exit 1
fi
fi
done
exit 0
检查暂存区总大小(pre-commit 钩子)
#!/bin/bash
# 设置最大暂存区大小(100MB)
MAX_STAGED_SIZE=$((100 * 1024 * 1024))
# 计算暂存区总大小
total_size=$(git diff --cached --numstat | awk '{sum += $1 + $2} END {print sum}' 2>/dev/null)
if [ "$total_size" -gt "$MAX_STAGED_SIZE" ]; then
echo "错误:暂存区总大小 $(($total_size / 1024 / 1024))MB 超过限制 $(($MAX_STAGED_SIZE / 1024 / 1024))MB"
exit 1
fi
exit 0
检查仓库总大小(pre-push 钩子)
#!/bin/bash
# .git/hooks/pre-push
# 设置仓库大小限制(500MB)
MAX_REPO_SIZE=$((500 * 1024 * 1024))
# 获取本地仓库大小
repo_size=$(du -sb .git 2>/dev/null | cut -f1)
if [ "$repo_size" -gt "$MAX_REPO_SIZE" ]; then
echo "警告:本地仓库大小 $(($repo_size / 1024 / 1024))MB 超过限制 $(($MAX_REPO_SIZE / 1024 / 1024))MB"
echo "建议: 使用 git gc 清理或移除大文件历史"
exit 1
fi
exit 0
检查单个文件类型限制(如禁止提交 .exe .zip 等)
#!/bin/bash
# 禁止提交的文件扩展名
BLOCKED_EXTENSIONS=("exe" "zip" "rar" "7z" "iso" "dmg" "pkg")
staged_files=$(git diff --cached --name-only --diff-filter=A)
for file in $staged_files; do
extension="${file##*.}"
for blocked in "${BLOCKED_EXTENSIONS[@]}"; do
if [ "$extension" == "$blocked" ]; then
echo "错误:禁止提交 .$blocked 文件类型: $file"
exit 1
fi
done
done
exit 0
结合多种检查的完整示例
#!/bin/bash
# .git/hooks/pre-commit - 综合版本
# 配置
MAX_SINGLE_FILE=52428800 # 单个文件 50MB
MAX_STAGED_SIZE=524288000 # 暂存区总大小 500MB
BLOCKED_PATTERNS=("*.exe" "*.zip" "*.rar" "*.mp4" "*.avi")
# 颜色输出
RED='\033[0;31m'
NC='\033[0m' # No Color
echo "开始进行容量门禁检查..."
# 检查单个文件大小
staged_files=$(git diff --cached --name-only --diff-filter=ACMR)
for file in $staged_files; do
if [ -f "$file" ]; then
file_size=$(stat -f%z "$file" 2>/dev/null || stat -c%s "$file" 2>/dev/null)
if [ "$file_size" -gt "$MAX_SINGLE_FILE" ]; then
echo -e "${RED}门禁违规:${NC} 文件 '$file' 大小为 $(($file_size / 1024 / 1024))MB"
exit 1
fi
fi
done
# 检查文件模式
for pattern in "${BLOCKED_PATTERNS[@]}"; do
for file in $staged_files; do
if [[ "$file" == $pattern ]]; then
echo -e "${RED}门禁违规:${NC} 禁止提交文件类型 '$file'"
exit 1
fi
done
done
# 检查暂存区总大小
total_size=$(git diff --cached --numstat | awk '{sum += $1 + $2} END {print sum}')
if [ "$total_size" -gt "$MAX_STAGED_SIZE" ]; then
echo -e "${RED}门禁违规:${NC} 暂存区总大小 $(($total_size / 1024 / 1024))MB"
exit 1
fi
echo -e "\033[0;32m容量门禁检查通过\033[0m"
exit 0
使用 Git LFS 作为替代方案
对于大型文件,推荐使用 Git LFS:
# 安装 Git LFS
git lfs install
# 跟踪大文件类型
git lfs track "*.psd" "*.zip" "*.tar.gz"
# 在钩子中检查是否使用了 LFS
#!/bin/bash
# pre-commit 钩子中检查未跟踪的大文件
large_files=$(git diff --cached --name-only --diff-filter=A | while read file; do
if [ -f "$file" ] && [ $(stat -f%z "$file" 2>/dev/null || stat -c%s "$file" 2>/dev/null) -gt 1048576 ]; then
# 检查是否被 LFS 跟踪
if ! git check-attr filter "$file" | grep -q "lfs"; then
echo "$file"
fi
fi
done)
if [ -n "$large_files" ]; then
echo "以下大文件未被 Git LFS 跟踪:"
echo "$large_files"
echo "请使用 'git lfs track' 命令跟踪它们"
exit 1
fi
部署钩子的脚本
#!/bin/bash # 将此脚本保存为 install-hooks.sh HOOKS_DIR=".git/hooks" cat > "$HOOKS_DIR/pre-commit" << 'EOF' # 这里是上述 pre-commit 脚本内容 EOF cat > "$HOOKS_DIR/pre-push" << 'EOF' # 这里是上述 pre-push 脚本内容 EOF chmod +x "$HOOKS_DIR/pre-commit" "$HOOKS_DIR/pre-push" echo "钩子已安装"
使用建议
- 阈值设置:根据团队工作流和项目特点设置合理阈值
- 选择性检查:使用
--diff-filter仅检查新增或修改的文件 - 性能考虑:对于大型仓库,建议限制检查范围或使用缓存
- 提示信息:提供清晰的错误信息和解决方案建议
- 调试模式:可以添加
DEBUG=true环境变量模式获取详细输出
这些钩子脚本可以灵活组合,根据团队需求定制容量门禁策略。