Add LFS config and pre-push hook
This commit is contained in:
parent
7a9e8c78bb
commit
bcb7daa62e
6 changed files with 274 additions and 0 deletions
27
.gitattributes
vendored
Normal file
27
.gitattributes
vendored
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
# Git LFS 跟踪规则
|
||||
# 提交到每个启用 LFS 的 GitHub 仓库根目录
|
||||
# 策略:按文件类型全覆盖(含小图,可接受此开销)
|
||||
# Issue: OS-GBL-F-002
|
||||
|
||||
# 视频
|
||||
*.mp4 filter=lfs diff=lfs merge=lfs -text
|
||||
*.mov filter=lfs diff=lfs merge=lfs -text
|
||||
*.avi filter=lfs diff=lfs merge=lfs -text
|
||||
*.wmv filter=lfs diff=lfs merge=lfs -text
|
||||
|
||||
# 设计稿
|
||||
*.psd filter=lfs diff=lfs merge=lfs -text
|
||||
*.ai filter=lfs diff=lfs merge=lfs -text
|
||||
*.sketch filter=lfs diff=lfs merge=lfs -text
|
||||
*.fig filter=lfs diff=lfs merge=lfs -text
|
||||
|
||||
# 图片
|
||||
*.png filter=lfs diff=lfs merge=lfs -text
|
||||
*.jpg filter=lfs diff=lfs merge=lfs -text
|
||||
*.jpeg filter=lfs diff=lfs merge=lfs -text
|
||||
*.gif filter=lfs diff=lfs merge=lfs -text
|
||||
*.webp filter=lfs diff=lfs merge=lfs -text
|
||||
*.tiff filter=lfs diff=lfs merge=lfs -text
|
||||
|
||||
# 如特定仓库需要某类型不走 LFS,在该仓库的 .gitattributes 追加覆盖规则:
|
||||
# *.png -filter -diff -merge
|
||||
4
.githooks/post-checkout
Executable file
4
.githooks/post-checkout
Executable file
|
|
@ -0,0 +1,4 @@
|
|||
#!/bin/sh
|
||||
# LFS post-checkout passthrough (required when core.hooksPath = .githooks)
|
||||
command -v git-lfs >/dev/null 2>&1 || { git lfs version >/dev/null 2>&1 || exit 0; }
|
||||
git lfs post-checkout "$@"
|
||||
4
.githooks/post-commit
Executable file
4
.githooks/post-commit
Executable file
|
|
@ -0,0 +1,4 @@
|
|||
#!/bin/sh
|
||||
# LFS post-commit passthrough (required when core.hooksPath = .githooks)
|
||||
command -v git-lfs >/dev/null 2>&1 || { git lfs version >/dev/null 2>&1 || exit 0; }
|
||||
git lfs post-commit "$@"
|
||||
4
.githooks/post-merge
Executable file
4
.githooks/post-merge
Executable file
|
|
@ -0,0 +1,4 @@
|
|||
#!/bin/sh
|
||||
# LFS post-merge passthrough (required when core.hooksPath = .githooks)
|
||||
command -v git-lfs >/dev/null 2>&1 || { git lfs version >/dev/null 2>&1 || exit 0; }
|
||||
git lfs post-merge "$@"
|
||||
233
.githooks/pre-push
Executable file
233
.githooks/pre-push
Executable file
|
|
@ -0,0 +1,233 @@
|
|||
#!/bin/sh
|
||||
# LFS Pre-Push Hook — push 前显示 LFS 文件清单并要求确认
|
||||
# Issue: OS-GBL-F-002
|
||||
#
|
||||
# 功能:
|
||||
# 1. 检测本次 push 涉及的 LFS 文件,显示清单和总大小
|
||||
# 2. >500MB 的文件标记警告
|
||||
# 3. 用户确认后执行 git lfs pre-push 上传
|
||||
#
|
||||
# 环境变量:
|
||||
# LFS_PREPUSH_SKIP=1 跳过确认(CI/CD 用)
|
||||
#
|
||||
# 兼容性:POSIX sh + BSD awk(macOS 原生环境)
|
||||
|
||||
REMOTE="$1"
|
||||
URL="$2"
|
||||
|
||||
# --- 捕获 stdin(ref 数据),后续 replay 给 git lfs pre-push ---
|
||||
INPUT=""
|
||||
while IFS= read -r line; do
|
||||
if [ -z "$INPUT" ]; then
|
||||
INPUT="$line"
|
||||
else
|
||||
INPUT="$INPUT
|
||||
$line"
|
||||
fi
|
||||
done
|
||||
|
||||
# --- 检查 git-lfs 是否可用 ---
|
||||
if ! command -v git-lfs >/dev/null 2>&1 && ! git lfs version >/dev/null 2>&1; then
|
||||
echo "pre-push: git-lfs not found, skipping LFS check"
|
||||
exit 0
|
||||
fi
|
||||
|
||||
# --- 收集所有 ref 涉及的 LFS 文件 ---
|
||||
LFS_LIST=""
|
||||
|
||||
process_ref() {
|
||||
local_ref="$1"
|
||||
local_sha="$2"
|
||||
remote_ref="$3"
|
||||
remote_sha="$4"
|
||||
|
||||
ZERO="0000000000000000000000000000000000000000"
|
||||
|
||||
# 删除分支 → 跳过
|
||||
if [ "$local_sha" = "$ZERO" ]; then
|
||||
return
|
||||
fi
|
||||
|
||||
# 确定比较基准
|
||||
if [ "$remote_sha" = "$ZERO" ]; then
|
||||
# 新分支:找与默认分支的 merge-base
|
||||
base=""
|
||||
for candidate in main master develop; do
|
||||
if git rev-parse --verify "refs/remotes/origin/$candidate" >/dev/null 2>&1; then
|
||||
base=$(git merge-base "refs/remotes/origin/$candidate" "$local_sha" 2>/dev/null)
|
||||
break
|
||||
fi
|
||||
done
|
||||
if [ -z "$base" ]; then
|
||||
# 无法找到基准,列出该分支所有 LFS 文件
|
||||
base=""
|
||||
fi
|
||||
else
|
||||
base="$remote_sha"
|
||||
fi
|
||||
|
||||
# 获取 LFS 文件列表(带大小)
|
||||
if [ -n "$base" ]; then
|
||||
files=$(git lfs ls-files --size "$base" "$local_sha" 2>/dev/null)
|
||||
else
|
||||
files=$(git lfs ls-files --size "$local_sha" 2>/dev/null)
|
||||
fi
|
||||
|
||||
if [ -n "$files" ]; then
|
||||
LFS_LIST="$LFS_LIST
|
||||
$files"
|
||||
fi
|
||||
}
|
||||
|
||||
# 解析每一行 ref 数据
|
||||
if [ -n "$INPUT" ]; then
|
||||
echo "$INPUT" | while IFS=' ' read -r local_ref local_sha remote_ref remote_sha; do
|
||||
if [ -n "$local_ref" ]; then
|
||||
process_ref "$local_ref" "$local_sha" "$remote_ref" "$remote_sha"
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
# 因为上面的 while 在子 shell 中,LFS_LIST 不会传递回来
|
||||
# 重新在当前 shell 处理
|
||||
LFS_LIST=""
|
||||
if [ -n "$INPUT" ]; then
|
||||
set -f # 禁用 glob
|
||||
OLD_IFS="$IFS"
|
||||
IFS='
|
||||
'
|
||||
for line in $INPUT; do
|
||||
IFS="$OLD_IFS"
|
||||
local_ref=$(echo "$line" | awk '{print $1}')
|
||||
local_sha=$(echo "$line" | awk '{print $2}')
|
||||
remote_ref=$(echo "$line" | awk '{print $3}')
|
||||
remote_sha=$(echo "$line" | awk '{print $4}')
|
||||
|
||||
ZERO="0000000000000000000000000000000000000000"
|
||||
|
||||
# 删除分支 → 跳过
|
||||
if [ "$local_sha" = "$ZERO" ]; then
|
||||
continue
|
||||
fi
|
||||
|
||||
# 确定比较基准
|
||||
base=""
|
||||
if [ "$remote_sha" = "$ZERO" ]; then
|
||||
for candidate in main master develop; do
|
||||
if git rev-parse --verify "refs/remotes/origin/$candidate" >/dev/null 2>&1; then
|
||||
base=$(git merge-base "refs/remotes/origin/$candidate" "$local_sha" 2>/dev/null)
|
||||
break
|
||||
fi
|
||||
done
|
||||
else
|
||||
base="$remote_sha"
|
||||
fi
|
||||
|
||||
# 获取 LFS 文件列表
|
||||
if [ -n "$base" ]; then
|
||||
files=$(git lfs ls-files --size "$base" "$local_sha" 2>/dev/null)
|
||||
else
|
||||
files=$(git lfs ls-files --size "$local_sha" 2>/dev/null)
|
||||
fi
|
||||
|
||||
if [ -n "$files" ]; then
|
||||
LFS_LIST="$LFS_LIST
|
||||
$files"
|
||||
fi
|
||||
|
||||
IFS='
|
||||
'
|
||||
done
|
||||
IFS="$OLD_IFS"
|
||||
set +f
|
||||
fi
|
||||
|
||||
# --- 去重并解析 ---
|
||||
# git lfs ls-files --size 输出格式: <oid> <indicator> <path> (<size>)
|
||||
# 示例: abc1234567 * assets/logo.png (1.2 MB)
|
||||
|
||||
if [ -z "$LFS_LIST" ] || [ "$(echo "$LFS_LIST" | sed '/^$/d' | wc -l)" -eq 0 ]; then
|
||||
# 无 LFS 文件 → 静默执行 git lfs pre-push 并放行
|
||||
echo "$INPUT" | git lfs pre-push "$@"
|
||||
exit $?
|
||||
fi
|
||||
|
||||
# 按文件路径去重
|
||||
DEDUPED=$(echo "$LFS_LIST" | sed '/^$/d' | awk '!seen[$3]++')
|
||||
FILE_COUNT=$(echo "$DEDUPED" | wc -l | awk '{print $1}')
|
||||
|
||||
# --- 非 TTY 或 CI 模式 → 自动放行 ---
|
||||
if [ "${LFS_PREPUSH_SKIP:-0}" = "1" ]; then
|
||||
echo "$INPUT" | git lfs pre-push "$@"
|
||||
exit $?
|
||||
fi
|
||||
|
||||
if [ ! -t 0 ] && [ ! -t 1 ]; then
|
||||
# 非交互环境,自动放行
|
||||
echo "$INPUT" | git lfs pre-push "$@"
|
||||
exit $?
|
||||
fi
|
||||
|
||||
# --- 显示 LFS 文件清单 ---
|
||||
echo ""
|
||||
echo "=========================================="
|
||||
echo " LFS Pre-Push: $FILE_COUNT file(s) detected"
|
||||
echo "=========================================="
|
||||
echo ""
|
||||
|
||||
TOTAL_BYTES=0
|
||||
HAS_LARGE=0
|
||||
|
||||
echo "$DEDUPED" | while IFS= read -r entry; do
|
||||
# 提取路径和大小
|
||||
path=$(echo "$entry" | awk '{print $3}')
|
||||
size_str=$(echo "$entry" | sed 's/.*(\(.*\))/\1/')
|
||||
|
||||
# 解析大小为字节数(用于判断 >500MB)
|
||||
size_num=$(echo "$size_str" | awk '{print $1}')
|
||||
size_unit=$(echo "$size_str" | awk '{print $2}')
|
||||
|
||||
bytes=0
|
||||
case "$size_unit" in
|
||||
B) bytes=$(echo "$size_num" | awk '{printf "%.0f", $1}') ;;
|
||||
KB) bytes=$(echo "$size_num" | awk '{printf "%.0f", $1 * 1024}') ;;
|
||||
MB) bytes=$(echo "$size_num" | awk '{printf "%.0f", $1 * 1048576}') ;;
|
||||
GB) bytes=$(echo "$size_num" | awk '{printf "%.0f", $1 * 1073741824}') ;;
|
||||
esac
|
||||
|
||||
# 检查是否超过 500MB (524288000 bytes)
|
||||
is_large=$(echo "$bytes" | awk '{if ($1 > 524288000) print 1; else print 0}')
|
||||
|
||||
if [ "$is_large" = "1" ]; then
|
||||
printf " %-50s %s %s\n" "$path" "$size_str" "[!] >500MB"
|
||||
else
|
||||
printf " %-50s %s\n" "$path" "$size_str"
|
||||
fi
|
||||
done
|
||||
|
||||
echo ""
|
||||
echo "------------------------------------------"
|
||||
echo " Total: $FILE_COUNT file(s)"
|
||||
echo "------------------------------------------"
|
||||
echo ""
|
||||
|
||||
# --- 确认提示 ---
|
||||
printf "Proceed with LFS upload? [y/N] "
|
||||
|
||||
# 从 /dev/tty 读取用户输入(因为 stdin 已被 git 占用)
|
||||
if read -r answer < /dev/tty 2>/dev/null; then
|
||||
case "$answer" in
|
||||
[yY]|[yY][eE][sS])
|
||||
echo "Uploading LFS files..."
|
||||
echo "$INPUT" | git lfs pre-push "$@"
|
||||
exit $?
|
||||
;;
|
||||
*)
|
||||
echo "Push aborted by user."
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
else
|
||||
echo "Cannot read from terminal, aborting."
|
||||
exit 1
|
||||
fi
|
||||
2
.lfsconfig
Normal file
2
.lfsconfig
Normal file
|
|
@ -0,0 +1,2 @@
|
|||
[lfs]
|
||||
url = http://silicon:5e2aa6ff8dd2042a65eaaac0e8e5028bf3c99968@100.64.144.118:3000/silicon/lfs-hook-test.git/info/lfs
|
||||
Loading…
Add table
Reference in a new issue