图片上传git时压缩
你想实现在上传图片到 Git 仓库时自动进行压缩,这可以通过 Git Hooks 来实现。
下面我将为你详细介绍如何配置一个 Git 钩子(pre-commit hook),在你每次执行 git commit 时,自动压缩 staged(已暂存)的图片文件(如 .png, .jpg, .jpeg),然后用压缩后的文件替换原文件并重新暂存。
核心思路
- 创建钩子脚本:在项目的
.git/hooks目录下创建一个pre-commit脚本。 - 脚本功能:
- 检查当前暂存区(staged)是否有图片文件被修改或新增。
- 如果有,使用一个图片压缩工具(如
sips- macOS 自带,或pngquant,jpegoptim等更高效的命令行工具)对这些图片进行压缩。 - 将压缩后的文件重新添加到暂存区(
git add),这样它们就会被包含在即将进行的 commit 中。
- 安装依赖:确保你选择的压缩工具已经安装在你的开发环境中。
方案一:使用 macOS 自带的 sips 工具 (最简单,无需额外安装)
sips 是 macOS 自带的命令行图片处理工具,可以用来调整图片大小和质量。虽然它的压缩效率可能不如专业工具,但胜在方便快捷。
步骤:
-
创建
pre-commit钩子文件:打开终端,进入你的项目根目录,然后执行以下命令:
bash
cd /path/to/your/project touch .git/hooks/pre-commit chmod +x .git/hooks/pre-commit open .git/hooks/pre-commit -
粘贴以下脚本内容:
这会在每次 commit 前,自动压缩所有新增或修改的
.png,.jpg,.jpeg文件。bash
#!/bin/sh# 获取所有暂存区中被修改或新增的图片文件 IMAGE_FILES=$(git diff --cached --name-only --diff-filter=ACMR | grep -E '\.(png|jpg|jpeg)$' | tr '\n' ' ')if [ -z "$IMAGE_FILES" ]; thenexit 0 fiecho "pre-commit hook: 开始压缩图片..."# 遍历文件并压缩 for file in $IMAGE_FILES; doif [ -f "$file" ]; thenecho " 正在压缩: $file"# 使用 sips 进行压缩,降低质量到 80%# 注意:sips 会直接覆盖原文件sips -s formatOptions 80 "$file" --out "$file"# 将压缩后的文件重新添加到暂存区git add "$file"fi doneecho "pre-commit hook: 图片压缩完成。" exit 0说明:
git diff --cached --name-only --diff-filter=ACMR:这个命令非常关键。--cached:查看暂存区的文件。--name-only:只显示文件名。--diff-filter=ACMR:只筛选出 (A) dded, (C) opied, (M) odified, (R) enamed 的文件。
grep -E '\.(png|jpg|jpeg)$':使用正则表达式筛选出图片文件。sips -s formatOptions 80 "$file" --out "$file":这是压缩命令。formatOptions 80表示将质量设置为 80%。你可以调整这个值(0-100)来平衡质量和大小。--out "$file"表示输出到原文件,即覆盖。
方案二:使用更高效的压缩工具 (pngquant 和 jpegoptim)
对于更极致的压缩,推荐使用 pngquant (针对 PNG) 和 jpegoptim (针对 JPG)。它们通常能在保持较好视觉质量的同时,提供比 sips 更高的压缩比。
步骤:
-
安装压缩工具:
使用 Homebrew 安装(如果没有安装 Homebrew,请先访问 brew.sh 进行安装)。
bash
brew install pngquant jpegoptim -
创建 / 修改
pre-commit钩子文件:同样,在
.git/hooks/pre-commit文件中,粘贴以下内容:bash
#!/bin/sh# 获取所有暂存区中被修改或新增的图片文件 FILES=$(git diff --cached --name-only --diff-filter=ACMR)if [ -z "$FILES" ]; thenexit 0 fiecho "pre-commit hook: 开始压缩图片..."# 遍历文件 while IFS= read -r file; doif [[ "$file" =~ \.(png)$ ]]; thenif [ -f "$file" ]; thenecho " 正在压缩 PNG: $file"# pngquant 会生成一个新文件,例如 image.png -> image-fs8.png# --ext .png 表示输出文件使用 .png 后缀# --force 表示强制覆盖pngquant --quality=65-80 --ext .png --force "$file"git add "$file"fielif [[ "$file" =~ \.(jpg|jpeg)$ ]]; thenif [ -f "$file" ]; thenecho " 正在压缩 JPG: $file"# jpegoptim 会直接优化并覆盖原文件# --max=80 表示将质量控制在最大 80%# --strip-all 移除所有元数据jpegoptim --max=80 --strip-all "$file"git add "$file"fifi done <<< "$FILES"echo "pre-commit hook: 图片压缩完成。" exit 0说明:
pngquant --quality=65-80 ...:为 PNG 文件设置一个质量范围,pngquant会尝试找到最佳的压缩点。jpegoptim --max=80 --strip-all ...:为 JPG 文件设置最大质量,并移除 EXIF 等元数据以减小体积。
如何使用
- 保存脚本:将上述任一方案的代码粘贴到
.git/hooks/pre-commit文件后保存。 - 确保脚本可执行:
chmod +x .git/hooks/pre-commit这个命令已经做了这件事。 - 正常工作:现在,当你修改或新增一个图片文件,并执行
git add .和git commit -m "your message"时,钩子脚本就会自动运行,压缩图片并将压缩后的版本提交。
重要注意事项
git add再次:脚本中必须包含git add "$file"。因为压缩工具修改了文件,使其变成了 "modified but not staged" 状态。如果不重新git add,那么 commit 的将是压缩前的版本,而工作区会留下压缩后的版本,导致不一致。- 二进制文件差异:Git 默认对二进制文件(如图片)的处理效率不高。每次图片被压缩后,即使变化很小,Git 也会存储一个全新的版本。这会导致仓库体积随着时间推移而增长。
- 解决方案:可以考虑使用 Git LFS (Large File Storage) 来管理大图片和其他二进制资产。Git LFS 会将大文件存储在外部服务器上,而 Git 仓库中只保留一个指针。这是一个更长期、更可持续的解决方案,特别是对于团队协作项目。
- 团队协作:
.git/hooks目录下的文件默认不会被 Git 版本控制。如果你希望团队中的其他成员也能使用这个钩子,你需要:- 在项目中创建一个
hooks目录(例如./githooks),将pre-commit脚本放在这里。 - 在
README.md中说明,让团队成员在克隆仓库后,执行cp ./githooks/* .git/hooks/来安装钩子。 - 或者使用像
husky(一个流行的 Git Hooks 管理工具) 这样的库来更方便地共享和管理钩子。不过husky主要在 Node.js 项目中使用,但也可以用于其他类型的项目。
- 在项目中创建一个
- 测试:在正式使用前,务必进行测试。修改一张图片,
git add它,然后尝试git commit。观察终端输出,并检查提交后的图片是否是压缩后的版本。
总结
使用 Git Hooks 是在提交前自动压缩图片的绝佳方式,能有效控制 Git 仓库的大小。
- 方案一 (
sips):适合个人项目或快速设置,无需额外依赖。 - 方案二 (
pngquant/jpegoptim):压缩效果更好,推荐用于对体积敏感的项目。 - 长远之计:结合 Git LFS 来管理所有大文件,这是处理二进制资产的最佳实践。
