Предотвратить добавление большого текстового файла в фиксацию при использовании GitHub

Мы хотим предотвратить:

  • Очень большие текстовые файлы (> 50 МБ на файл) не должны быть зафиксированы в git вместо git-lfs, так как они раздувают историю git.
  • Проблема в том, что 99% из них имеют размер ‹ 1 МБ и должны быть зафиксированы для лучшего сравнения.
  • Причина разницы в размере: это файлы YAML, они поддерживают бинарную сериализацию через кодировку base64.
  • Причина, по которой мы не можем надежно предотвратить бинарную сериализацию: это проект Unity, бинарная сериализация необходима по разным причинам.

Дано:

  • На хостинге GitHub отсутствует поддержка перехватчиков перед получением.
  • git-lfs отсутствие поддержки атрибута размера файла.

Вопросы:

  1. Как мы можем надежно предотвратить добавление больших файлов в коммит?
  2. Можно ли это сделать с помощью файла конфигурации в репозитории, чтобы все пользователи изящно следовали этому правилу?
  3. Если нет, можно ли это сделать с помощью псевдонима команды bash, чтобы доверенные пользователи могли видеть предупреждающее сообщение, когда они случайно git add большой файл, и он не обрабатывается git-lfs?

(Наша среда — macOS. Я просмотрел множество решений, и пока ни одно из них не удовлетворяет нашим требованиям)


person bitinn    schedule 09.12.2018    source источник
comment
comment
Можете ли вы включить (хотя бы некоторые из них) решения, которые вы рассмотрели и отбросили? Я не особенно хорошо разбираюсь в git-хуках, но это звучит так, как будто pre-commit хук может справиться со мной.   -  person solarshado    schedule 09.12.2018
comment
@Cyrus Я не читал этого, спасибо, но мне нужно проверить, включает ли он возможность файла, который будет отслеживаться git-lfs. Да, это предотвратит большой файл, но срабатывает ли git-lfs до предварительной фиксации, вот в чем вопрос.   -  person bitinn    schedule 09.12.2018
comment
@solarshado Я добавлю несколько ссылок позже, но я предполагаю, что предварительная фиксация не учитывает git-lfs, но я действительно недостаточно знаю о git-lfs, чтобы так или иначе говорить.   -  person bitinn    schedule 09.12.2018
comment
Я тоже не знаком с git-lfs, но судя по его домашней странице, он выглядит так: это просто работает :tm:. Просматривая некоторые из документов, кажется, что он использует пре-толкающий хук для некоторой (большинства?) своей магии.   -  person solarshado    schedule 09.12.2018


Ответы (2)


Хорошо, с помощью CodeWizard и этого ответа SO мне удалось создать хороший путеводитель самостоятельно:

Сначала настройте репозиторий core.hooksPath с помощью:

git config core.hooksPath .githooks

Во-вторых, создайте этот pre-commit файл в папке .githooks, чтобы его можно было отслеживать (основная ссылка), затем не забудьте дать ему разрешение на выполнение с помощью 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

Теперь, предполагая, что вы правильно настроили и .gitattributes, и git-lfs, этот хук предварительной фиксации будет запущен, когда вы попытаетесь git commit и убедиться, что все промежуточные файлы, не отслеживаемые git-lfs (как указано в вашем .gitattributes), будут соответствовать указанному размеру файла. предел.

Всем новым пользователям вашего репозитория потребуется настроить core.hooksPath самостоятельно, но кроме этого все должно работать.

Надеюсь, это поможет другим разработчикам Unity бороться с растущим размером репозитория git!

person bitinn    schedule 09.12.2018
comment
man git-config говорит о core.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. Ваша команда git config core.hooksPath .githooks возвращает fatal: not in a git directory, когда я запускаю ее из $HOME, нужно ли мне использовать параметр --global, если я хочу, чтобы хуки можно было использовать во всех проектах на моей машине? - person SebMa; 28.11.2020

  • Как мы можем надежно предотвратить добавление больших файлов в коммит?
  • Можно ли это сделать через файл конфигурации в репозитории, чтобы все пользователи изящно следовали этому правилу? Поскольку GitHub не поддерживает хуки на стороне сервера, вы можете использовать хуки на стороне клиента. Как вы, наверное, знаете, эти хуки можно без проблем обойти и отключить, но, тем не менее, это хороший способ сделать это.

core.hooksPath

В Git v2.9 добавлена ​​возможность устанавливать клиентские хуки на удаленную папку. До этого хуки должны быть размещены внутри папки .git.

Это позволит вам писать сценарии и размещать их где угодно. Я предполагаю, что вы знаете, что такое крючки, но если нет, не стесняйтесь спрашивать.


Как это сделать?

Обычно вы размещаете хуки внутри своего репозитория (или любой другой общей папки).

# set the hooks path. for git config, the default location is --local
# so this configuration is locally per project
git config core.hooksPath .githooks
person CodeWizard    schedule 09.12.2018
comment
очень красиво, посмотрю и отчитаюсь - person bitinn; 09.12.2018
comment
Итак, это работает, но хук занял у меня некоторое время (код из другого SO имеет проблемы с обработкой пробелов в пути), поэтому я сделал свой, не стесняйтесь добавлять их для более полного ответа: gist.github.com/bitinn/834756d57f3d47df97937aab68162ae6 - person bitinn; 09.12.2018
comment
Круто, рад помочь - person CodeWizard; 09.12.2018
comment
извините, я говорю слишком рано, похоже, это еще не работает с git-lfs, например, недостаточно умно, чтобы пропустить файл, который может обрабатываться git-lfs (скажем, файл PNG, который, вероятно, более 1 МБ, но может быть зафиксирован, потому что lfs может с этим справиться) - person bitinn; 09.12.2018
comment
Вы можете сделать это с помощью скриптов с очисткой от пятен чтобы сохранить вкладки в github для make-файлов"> stackoverflow.com/questions/41773264/ - person CodeWizard; 09.12.2018
comment
Давайте продолжим обсуждение в чате. - person bitinn; 09.12.2018