Ограничение размера файла в репозитории git - PullRequest
27 голосов
/ 22 августа 2011

Я сейчас думаю о том, чтобы сменить VCS (с subversion) на git.Можно ли ограничить размер файла внутри коммита в репозитории git?Например, для подрывной деятельности есть хук: http://www.davidgrant.ca/limit_size_of_subversion_commits_with_this_hook

Из моего опыта люди, особенно неопытные, иногда склонны к фиксации файлов, которые не должны входить в VCS (например, большие образы файловой системы).

Ответы [ 8 ]

24 голосов
/ 03 февраля 2012

Поскольку я боролся с этим некоторое время, даже с описанием, и я думаю, что это актуально и для других, я подумал, что опубликую реализацию того, как J16 SDiZ, описанный , может бытьреализован.

Итак, мой подход на стороне сервера update перехватывает, предотвращая слишком большие файлы, которые нужно нажимать:

#!/bin/bash

# Script to limit the size of a push to git repository.
# Git repo has issues with big pushes, and we shouldn't have a real need for those
#
# eis/02.02.2012

# --- Safety check, should not be run from command line
if [ -z "$GIT_DIR" ]; then
        echo "Don't run this script from the command line." >&2
        echo " (if you want, you could supply GIT_DIR then run" >&2
        echo "  $0 <ref> <oldrev> <newrev>)" >&2
        exit 1
fi

# Test that tab replacement works, issue in some Solaris envs at least
testvariable=`echo -e "\t" | sed 's/\s//'`
if [ "$testvariable" != "" ]; then
        echo "Environment check failed - please contact git hosting." >&2
        exit 1
fi


# File size limit is meant to be configured through 'hooks.filesizelimit' setting
filesizelimit=$(git config hooks.filesizelimit)

# If we haven't configured a file size limit, use default value of about 100M
if [ -z "$filesizelimit" ]; then
        filesizelimit=100000000
fi

# Reference to incoming checkin can be found at $3
refname=$3

# With this command, we can find information about the file coming in that has biggest size
# We also normalize the line for excess whitespace
biggest_checkin_normalized=$(git ls-tree --full-tree -r -l $refname | sort -k 4 -n -r | head -1 | sed 's/^ *//;s/ *$//;s/\s\{1,\}/ /g' )

# Based on that, we can find what we are interested about
filesize=`echo $biggest_checkin_normalized | cut -d ' ' -f4,4`

# Actual comparison
# To cancel a push, we exit with status code 1
# It is also a good idea to print out some info about the cause of rejection
if [ $filesize -gt $filesizelimit ]; then

        # To be more user-friendly, we also look up the name of the offending file
        filename=`echo $biggest_checkin_normalized | cut -d ' ' -f5,5`

        echo "Error: Too large push attempted." >&2
        echo  >&2
        echo "File size limit is $filesizelimit, and you tried to push file named $filename of size $filesize." >&2
        echo "Contact configuration team if you really need to do this." >&2
        exit 1
fi

exit 0

Обратите внимание, что это было прокомментировал , что этот код проверяет только последнюю фиксацию, поэтому этот код необходимо настроить, чтобы выполнить итерации между $ 2 и $ 3 и выполнить проверку для всех них.

8 голосов
/ 09 апреля 2015

Ответы eis и J-16 SDiZ страдают от серьезной проблемы. Они только проверяют состояние финального коммита $ 3 или $ newrev. Они также должны проверить, что представлено в других коммитах. от $ 2 (или $ oldrev) до $ 3 (или $ newrev) в хуке udpate.

J-16 SDiZ ближе к правильному ответу.

Большой недостаток заключается в том, что тот, на чьем ведомственном сервере установлен этот крючок обновления для его защиты, найдет трудный путь:

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

Для решения проблемы нужно либо проверить каждый коммит от $ oldrev до $ newrev, либо указать весь диапазон $ oldrev .. $ newrev. Будьте уверены, что вы проверяете не только $ newrev, либо это не удастся с огромным мусором в вашей истории Git, вытесненным, чтобы поделиться с другими, а затем трудно или невозможно удалить после этого.

4 голосов
/ 11 февраля 2015

если вы используете гитолит, вы также можете попробовать VREF.По умолчанию уже есть один VREF (код находится в gitolite / src / VREF / MAX_NEWBIN_SIZE).Он называется MAX_NEWBIN_SIZE.Это работает следующим образом:

repo name
RW+     =   username
-   VREF/MAX_NEWBIN_SIZE/1000   =   usernames 

Где 1000 - пример порогового значения в байтах.

Этот VREF работает как хук обновления, и он отклонит ваш push, если один файл, который вы хотите отправить, большечем порог.

2 голосов
/ 22 августа 2011

Да, у git также есть крючки ( git hooks ). Но это зависит от того, какой рабочий процесс вы будете использовать.

Если у вас есть неопытные пользователи, гораздо безопаснее тянуть, чем позволить им подтолкнуть. Таким образом, вы можете быть уверены, что они не испортят основной репозиторий.

0 голосов
/ 30 августа 2014

Я использую gitolite, и хук обновления уже использовался - вместо хука обновления я использовал хук предварительного получения. Сценарий, опубликованный Chriki, работал невероятно, за исключением того, что данные передаются через stdin - поэтому я сделал одно изменение строки:

- refname=$3
+ read a b refname

(может быть, есть более элегантный способ сделать это, но это работает)

0 голосов
/ 22 августа 2011

Это будет очень редкий случай из того, что я видел, когда кто-то регистрируется, например, файл размером 200 МБ или даже больше.

Хотя вы можете предотвратить это, используя перехватчики на стороне сервера (не уверенные в перехватах на стороне клиента, поскольку вы должны полагаться на человека, у которого установлены перехватчики), так же, как в SVN, вы также должны принять во внимание что в Git гораздо проще удалить такой файл / коммит из репозитория. У вас не было такой роскоши в SVN, по крайней мере, нелегкий путь.

0 голосов
/ 22 августа 2011

Другой способ - это версия .gitignore, которая не позволит любому файлу с определенным расширением отображаться в статусе.
У вас все еще могут быть зацепки (в нисходящем или восходящем направлении, как предлагают другие ответы), но по крайней мере все нисходящие репо могут включать это .gitignore, чтобы избежать добавления .exe, .dll, .iso, .. .

0 голосов
/ 22 августа 2011

Вы можете использовать hook , либо pre-commit hook (на клиенте), либо update hook (на сервере). Выполните git ls-files --cached (для предварительной фиксации) или git ls-tree --full-tree -r -l $3 (для обновления) и действуйте соответственно.

git ls-tree -l даст что-то вроде этого:

100644 blob 97293e358a9870ac4ddf1daf44b10e10e8273d57    3301    file1
100644 blob 02937b0e158ff8d3895c6e93ebf0cbc37d81cac1     507    file2

Возьмите четвертую колонку, и это будет размер. Используйте git ls-tree --full-tree -r -l HEAD | sort -k 4 -n -r | head -1, чтобы получить самый большой файл. cut для извлечения, if [ a -lt b ] для проверки размера и т.д ..

Извините, я думаю, что если вы программист, вы сможете сделать это самостоятельно.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...