我的编辑器中有一个错误(太可怕了),有时会将大文件写入工作目录。然后,我在不手动检查这些大的新文件的情况下执行了
git push
,并且 git 远程超载并最终出错。
是否有一些检查(可能是 git hook)可以用来检查我的存储库是否超过特定大小(以 MB 为单位)?
当您运行
git push
时,Git 不会以任何方式使用工作树。 具体来说,git push
推送的是提交,以及完成这些提交所需的任何对象(主要是其内容在提交时被冻结到提交中的文件)。1
请注意,
git commit
本身also不使用工作树:它提交index中的任何内容(也称为staging-area,有时也称为cache)。 这就是为什么您必须在提交之前git add
您的文件。 git commit
有一些选项可以使其自动将工作树文件复制到索引/暂存区域中这些文件的版本之上;但原则仍然是:git commit
提交索引中的内容,而不是工作树中的内容。
因此,在 Git hook 上检测此问题的最佳选择是预提交挂钩,如 githooks 文档中所述:
预提交
这个钩子由 git commit(1) 调用,并且可以通过
选项。它不带任何参数,并且在之前调用 获取建议的提交日志消息并进行提交。退出 此脚本的非零状态会导致--no-verify
命令 在创建提交之前中止。git commit
(文档还有更多内容;请点击链接查看。)
编写 Git 挂钩有点棘手(尤其是服务器端挂钩),但这还不错:
#! /bin/sh
# pre-commit hook: check for large files
TMP=$(mktemp)
trap "rm -f $TMP" 0 1 2 3 15
MAX_FILE_SIZE=1048576 # 1 MB
status=0
git ls-files --stage > $TMP
while read mode hash stage path; do
objsize=$(git cat-file -s $hash)
if [ $objsize -gt $MAX_FILE_SIZE ]; then
echo "file too big: '$path' as staged exceeds $MAX_FILE_SIZE bytes" 1>&2
status=1
fi
done < $TMP
exit $status
(未经测试)。 您可以选择预推挂钩,但这不太合适。
1这些 Git 对象也被压缩。 只要有可能,它们就会通过使用服务器上已有的现有对象进行高度压缩。 因此,如果您有一个 10 GB 的文本文件,但您对其进行了一个小更改并提交,则推送该提交(即使它内部有一个 10 GB 的文件)只需要很少的空间,因为所谓的 thin pack Git 发送的内容是: 嘿,还记得你已经拥有的 10 GB 对象吗? 拿那个,从中间删除几个字节,然后用其他字节替换它们。
由于这是一个持续存在的问题,因此您应该在执行
git status
之前养成跑步 git commit
的习惯。您可以查看将提交的文件列表以查找不属于的文件。
另一种方法,如果您想要多个提交的大小:
git for-each-ref --format= <>
(man)”学会了%(contents:size)
。
请参阅 Christian Couder (chriscool
) 的 commit b6839fd(2020 年 7 月 16 日)和 commit 6e2ef8e
、commit 9fcc9ca(2020 年 7 月 10 日)。
gitster
-- 合并于 commit be53706,2020 年 7 月 30 日)
的支持
:添加对ref-filter
%(contents:size)
签署人:Christian Couder
无需通过管道即可直接获取内容的大小,这非常有用且高效。
还有以下结果:
wc -c
关闭了 1,因为(man) 在内容后面附加了一个换行符,可以通过将其输出与
git for-each-ref --format='%(contents)' refs/heads/my-branch | wc -c
git for-each-ref
(man) 的输出进行比较来看出. 与git cat-file
一样,如果 ref 指向提交或标签以外的内容,
会被默默忽略:%(contents)
%(contents:size)
$ git update-ref refs/mytrees/first HEAD^{tree}
$ git for-each-ref --format='%(contents)' refs/mytrees/first
$ git for-each-ref --format='%(contents:size)' refs/mytrees/first
现在包含在其
手册页中:
git for-each-ref
提交或标记消息的大小(以字节为单位)。
contents:size
“更改的文件”部分。其次,检查
staged文件的大小并忽略这些被“删除”的文件。 但是,它没有考虑压缩步骤,因此实际提交通常会具有较小的大小。另外,通过“ls -l”检查“修改”文件的大小可能是错误的,因为这些是“git对象”,并且可能最好通过
git status
和
git ls-files --stage
获取对象的大小,如Torek的答案所示.
git cat-file -s $hash
调用的缺点是它包含已知的 git 文件,这些文件可能不包含在当前提交中。
这是一个带有注释和调试行的脚本:git ls-files --stage
这就是它的实际工作原理。它使用一些技术来获取用户输入。
首先将文件添加到舞台: