我的编辑器中有一个错误(非常糟糕),有时大文件会写入到工作目录中。然后,我执行了git push
,而无需手动检查这些新文件,而git remote变得超载并最终出错。
是否可以使用一些检查(也许是git钩子)来检查我的存储库是否超过一定大小(以MB为单位)?
答案 0 :(得分:5)
在运行git push
时,Git不会以任何方式使用工作树。具体来说,git push
推送是 commits ,还需要任何对象(主要是内容在提交时被冻结到提交中的文件)才能完成这些提交。 1
请注意,git commit
本身也不使用工作树:它会提交 index 中的任何内容(也称为 staging-区域,有时还包括缓存)。这就是为什么您必须git add
提交文件之后再进行提交的原因。 git commit
中有一些选项可以使它自动在索引/暂存区域中的那些文件的版本之上复制工作树文件。但是原理仍然存在:git commit
提交索引中的内容,而不是工作树中的内容。
因此,您最好使用Git hook 来检测此问题,这是一个预先提交的钩子,如the githooks documentation中所述:
预提交
此钩子由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的对象吗?拿那个,从中间删除几个字节,然后用其他字节替换它们。
答案 1 :(得分:3)
由于这是一个持续存在的问题,因此您应该养成运行git status
的习惯,然后再进行git commit
。您可以查看将提交的文件列表,以查找不属于它们的文件。
答案 2 :(得分:2)
如果您知道大文件名或格式,例如后缀,您可以将其添加到.gitignore
中,直到解决编辑器问题为止。
您可以检查this answer,它描述了服务器端更新挂钩。
答案 3 :(得分:0)
另一种方法,如果您希望多次提交的大小:
使用Git 2.29(2020年第四季度)时,“ git for-each-ref --format=
(man) <>”学到了%(contents:size)
。
请参见commit b6839fd之前的commit 6e2ef8e(2020年7月16日)和commit 9fcc9ca,Christian Couder (chriscool
)(2020年7月10日)。
(由Junio C Hamano -- gitster
--在commit be53706中合并,2020年7月30日)
ref-filter
:添加对%(contents:size)
的支持签名人:Christian Couder
能够直接获取内容的大小而不必通过
wc -c
进行传递,这既有用又有效。也是以下结果:
git for-each-ref --format='%(contents)' refs/heads/my-branch | wc -c
(man)偏移了一个,因为
[
git for-each-ref](https://github.com/git/git/blob/b6839fda6809b1de8d528837dfc99d0837f77c9d/Documentation/git-for-each-ref.txt)<sup>([man](https://git-scm.com/docs/git-for-each-ref))</sup>
在内容后面附加了换行符,可以通过将其输出与git cat-file
的输出进行比较来看到< sup>(man)。与
%(contents)
一样,如果ref指向除提交或标记之外的其他内容,则%(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
现在包含在其man page中:
contents:size
提交或标记消息的字节大小。