推送到git remote之前检查提交大小

8gsdolmq  于 2022-11-20  发布在  Git
关注(0)|答案(4)|浏览(132)

我的编辑器有一个bug(很可怕),有时会有大文件被写入工作目录。然后我在没有手动检查这些新的大文件的情况下执行git push,git remote就会过载,最终出错。
是否有一些检查(也许是一个git挂钩),我可以用来检查我的回购是否超过一定的大小在MB?

u4vypkhs

u4vypkhs1#

当你运行git push时,Git不会以任何方式使用工作树。具体来说,git push推送的是 commits,沿着任何对象(大多数是在提交时被冻结在提交中的文件),这些对象是完成这些提交所必需的。1
注意,git commit本身 * 也 * 不使用工作树:它会提交 index(也称为 staging-area,有时也称为 cache)中的所有文件。这就是为什么你必须在提交前对文件进行git addgit commit有几个选项可以让它自动将工作树文件复制到index / staging-area中的文件版本之上;但原则仍然是:git commit提交索引中的内容,而不是工作树中的内容。
因此,使用Git * 钩子 * 检测此问题的最佳方法是使用预提交钩子,如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 G的文本文件,但你对它做了一个小的修改并提交,推送该提交-即使它里面有一个10 G的文件-占用的空间非常小,因为Git发送的所谓的“精简包”最终会说:* 嘿,还记得你已经拥有的10 GB对象吗?拿那个对象,从中间删除几个字节,然后用其他字节替换它们。*

hjqgdpho

hjqgdpho2#

如果您知道大文件名或模式(例如后缀),则可以将其添加到.gitignore,直到您解决编辑器的问题。
您可以选中this answer,它描述了服务器端更新挂接。

mkshixfv

mkshixfv3#

由于这是一个持续的问题,您应该养成在执行git commit之前运行git status的习惯。您可以查看将提交的文件列表,以查找不属于该文件的文件。

zfycwa2u

zfycwa2u4#

另一种方法是,如果你想要多个提交的大小:
在Git 2.29(2020年第四季度)中,“git for-each-ref --format= <>(人)”学习了%(contents:size)
参见commit b6839fd(2020年7月16日)和commit 6e2ef8ecommit 9fcc9ca(2020年7月10日),作者为Christian Couder ( chriscool )
(2020年7月30日由Junio C Hamano -- gitster --合并至commit be53706
第1001章:添加对%(contents:size)的支持
签署人:克里斯蒂安·库德
能够直接获得内容的大小,而不必通过wc -c管道,这是非常有用和高效的。
也是以下的结果:

git for-each-ref --format='%(contents)' refs/heads/my-branch | wc -c

git for-each-refman)会在内容之后附加新行字符,因此会相差1,比较其输出与git cat-fileman)的输出即可看出这一点。
%(contents)一样,如果ref指向的不是commit或tag,%(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

提交或标记消息的大小(以字节为单位)。

相关问题