【问题标题】:Prevent large text file from being added to commit when using GitHub防止使用 GitHub 时将大文本文件添加到提交
【发布时间】:2018-12-09 07:35:41
【问题描述】:

我们要防止:

  • 非常大的文本文件(每个文件 > 50MB)不会被提交到 git 而不是 git-lfs,因为它们会膨胀 git 历史记录。
  • 问题是,其中 99% 的大小都小于 1MB,应该致力于更好地区分。
  • 大小差异的原因:这些是 YAML 文件,它们支持通过 base64 编码进行二进制序列化。
  • 我们不能可靠地阻止二进制序列化的原因:这是一个 Unity 项目,由于各种原因需要二进制序列化。

给定:

  • GitHub 托管缺乏预接收挂钩支持。
  • git-lfs 缺少文件大小属性支持。

问题:

  1. 我们如何可靠地防止大文件被添加到提交?
  2. 这可以通过 repo 中的配置文件来完成,以便所有用户都能优雅地遵循此规则吗?
  3. 如果不是,这是否可以通过 bash 命令别名来完成,以便受信任的用户在意外git add 一个大文件并且它未被git-lfs 处理时可以看到警告消息?

(我们的环境是 macOS。我看过很多解决方案,目前没有一个能满足我们的需求)

【问题讨论】:

  • 您能否包括(至少一些)您已经查看并丢弃的解决方案?我不是特别精通 git 钩子,但这听起来像是 pre-commit 钩子可以处理的事情。
  • @Cyrus 我没有读过那个,谢谢,但我需要测试它是否包含 git-lfs 跟踪的文件的可能性。是的,它会阻止大文件,但 git-lfs 会在预提交之前启动,这就是问题所在。
  • @solarshado 我稍后会添加一些链接,但我假设 pre-commit 不考虑 git-lfs,但我对 git-lfs 真的不太了解,无法以一种或另一种方式说.
  • 我也不熟悉 git-lfs,但基于 its home page,它看起来像“Just Works:tm:”。浏览一些docs,听起来它使用了一个预推钩来实现它的一些(大部分?)魔法。

标签: bash git unity3d github git-lfs


【解决方案1】:

好的,在 CodeWizard 和 this SO answer 的帮助下,我自己创建了一个很好的指南:

首先,设置你的 repo core.hooksPath

git config core.hooksPath .githooks

其次,在.githooks文件夹中创建这个pre-commit文件,这样它就可以被跟踪(gist link),然后记得给它chmod +x的执行权限。

#!/bin/sh
#
# An example hook script to verify what is about to be committed.
# Called by "git commit" with no arguments. The hook should
# exit with non-zero status after issuing an appropriate message if
# it wants to stop the commit.
#
# To enable this hook, rename this file to "pre-commit".

# Redirect output to stderr.
exec 1>&2

FILE_SIZE_LIMIT_KB=1024
CURRENT_DIR="$(pwd)"
COLOR='\033[01;33m'
NOCOLOR='\033[0m'
HAS_ERROR=""
COUNTER=0

# generate file extension filter from gitattributes for git-lfs tracked files
filter=$(cat .gitattributes | grep filter=lfs | awk '{printf "-e .%s$ ", $1}')

# before git commit, check non git-lfs tracked files to limit size
files=$(git diff --cached --name-only | sort | uniq | grep -v $filter)
while read -r file; do
    if [ "$file" = "" ]; then
        continue
    fi
    file_path=$CURRENT_DIR/$file
    file_size=$(ls -l "$file_path" | awk '{print $5}')
    file_size_kb=$((file_size / 1024))
    if [ "$file_size_kb" -ge "$FILE_SIZE_LIMIT_KB" ]; then
        echo "${COLOR}${file}${NOCOLOR} has size ${file_size_kb}KB, over commit limit ${FILE_SIZE_LIMIT_KB}KB."
        HAS_ERROR="YES"
        ((COUNTER++))
    fi
done <<< "$files"

# exit with error if any non-lfs tracked files are over file size limit
if [ "$HAS_ERROR" != "" ]; then
    echo "$COUNTER files are larger than permitted, please fix them before commit" >&2
    exit 1
fi

exit 0

现在,假设您正确设置了 .gitattributesgit-lfs,当您尝试 git commit 并确保所有暂存文件未被 git-lfs 跟踪(如您在.gitattributes),将满足指定的文件大小限制。

您的存储库的任何新用户都需要自己设置 core.hooksPath,但除此之外,一切都应该正常工作

希望这可以帮助其他 Unity 开发人员应对日益增长的 git repo 大小!

【讨论】:

  • man git-configcore.hooksPath : This configuration variable is useful in cases where you’d like to centrally configure your Git hooks instead of configuring them on a per-repository basis。当我从$HOME 运行您的命令git config core.hooksPath .githooks 时返回fatal: not in a git directory,如果我希望我的机器上的每个项目都可以使用这些钩子,我是否需要使用--global 选项?
【解决方案2】:
  • 我们如何可靠地防止大文件被添加到提交?
  • 这可以通过 repo 中的配置文件来完成,以便所有用户都能优雅地遵循此规则吗? 由于 GitHub 不支持服务器端挂钩,因此您可以使用客户端挂钩。您可能知道,这些钩子可以毫无问题地传递和禁用,但仍然是一个很好的方法。

core.hooksPath

Git v2.9 添加了在远程文件夹上设置客户端挂钩的功能。在此之前,钩子必须放在.git 文件夹中。

这将允许您编写脚本并将它们放在任何地方。我假设您知道什么是钩子,但如果不知道,请随时询问。


怎么做?

通常,您将挂钩放在您的 repo(或任何其他常用文件夹)中。

# set the hooks path. for git config, the default location is --local
# so this configuration is locally per project
git config core.hooksPath .githooks

【讨论】:

  • 非常好,我会检查并反馈
  • 好吧,这行得通,但钩子花了我一段时间(其他 SO 的代码在处理路径中的空格时有问题),所以我做了我的,随时附加它们以获得更完整的答案: gist.github.com/bitinn/834756d57f3d47df97937aab68162ae6
  • 酷,乐于助人
  • 对不起,我说得太早了,这似乎不适用于 git-lfs,因为它不够聪明,无法跳过 git-lfs 可以处理的文件(比如说一个 PNG 文件,它可能超过 1MB,但可以提交,因为 lfs 可以处理它)
  • 你可以使用smudge-clean脚本stackoverflow.com/questions/41773264/…
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-10-10
  • 2019-08-28
  • 2017-12-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多