git gc: отключена ли сборка мусора при пост-получении?

Я пытался закодировать эксперимент, который включает в себя размещение следующего кода в хуке post-receive git:

unset GIT_DIR
cd (path to some temp directory outside the repository)
git clone --local (path to repository just pushed to) .
git checkout dev
git reset --hard HEAD^
git reflog expire --expire=now --all
git gc --aggressive --prune=now

По сути, я клонирую только что отправленный репозиторий, делаю полный сброс для удаления последней фиксации, а затем выполняю сборку мусора, чтобы удалить следы последней фиксации из истории. Чтобы убедиться, что сборка мусора действительно выполняет свою работу, я фиксирую огромный 4-мегабайтный файл в последнем коммите, а затем проверяю размер .git, чтобы убедиться, что он был удален.

Поэтому, когда я запускаю этот код внутри хука git «post-receive», сброс, кажется, работает нормально; клонированный репозиторий вернулся в состояние без огромного файла. Однако сборка мусора, похоже, не сработала. Размер .git по-прежнему огромен.

С другой стороны, если я вручную запускаю «git reflog» и «git gc» из командной строки в этот момент, он правильно удаляет следы огромного файла, а размер .git восстанавливается до управляемого размера.

Любые идеи, почему сборка мусора может вести себя по-разному при запуске в «после получения», а не в командной строке?


person Daryl McCullough    schedule 08.09.2015    source источник


Ответы (2)


Агрессивная сборка мусора Git может не делать того, что вы ожидаете. Линус писал об этом здесь. Но это также было описано в других сообщениях:

person andygavin    schedule 09.09.2015
comment
Спасибо, попробую перепаковать. Но моя главная мысль заключалась в разнице в результатах между запуском приведенного выше кода в пост-получении, а не после его ручного ввода в командной строке. Я не могу понять, почему это может иметь значение. - person Daryl McCullough; 09.09.2015

Хорошо, я думаю, мне удалось добраться до сути этого. На самом деле это не имеет ничего общего с тем, находится ли он в пост-получении или нет.

Еще немного о проблеме, которая вызвала этот вопрос. У меня есть репозиторий, назовите его «репо». Последней фиксацией в этом репозитории был огромный файл, назовите его «BigFatFile.bin». Его размер составляет 4 МБ. Этого файла не должно быть в репозитории. Итак, моя попытка решить проблему заключается в следующем:

  1. Клонируйте репозиторий.
  2. Сделайте git reset --hard, чтобы удалить последний коммит.

Эти шаги позволяют удалить «BigFatFile.bin» из клонированного репозитория. Тем не менее, последствия этого толчка все еще видны в том смысле, что каталог .git по-прежнему огромен: 4 МБ «BigFatFile.bin» по-прежнему отражаются в каталоге .git/objects/pack.

На данный момент я могу попробовать различные команды очистки, чтобы попытаться избавиться от эффектов «BigFatFile.bin»:

git for-each-ref --format='delete %(refname)' refs/original | git update-ref --stdin
git reflog expire --expire=now --all
git repack -a -d -f --depth=250 --window=250
git gc --aggressive --prune=now --force

Эти шаги не оказывают существенного влияния на размер .git. Однако я обнаружил, что если я делаю git push -f origin master сразу после git reset --hard, а затем выполняю шаги очистки, размер .git возвращается к тому, что было до того, как "BigFatFile.bin" был отправлен. Это не решает мою проблему (потому что, хотя клонированный репозиторий вернулся в прежнее состояние, исходный репозиторий все еще раздут в размере). Тем не менее, это отвечает на мой вопрос о том, почему сборка мусора (и другие меры по очистке) не имели никакого эффекта: пока я не "протолкну" свои изменения, .git должен поддерживать не только локальное содержимое файлов, но и их исходное содержимое.

Итак, на мой первоначальный вопрос (почему очистка не работала локально) дан ответ, хотя я до сих пор не знаю ответа на реальный вопрос, а именно, как сбросить удаленный репозиторий, чтобы он не отображал последствия коммита. из "BigFatFile.txt"

person Daryl McCullough    schedule 10.09.2015
comment
Я не уверен, что это ответ, скорее разработка вашего вопроса с новыми знаниями о том, что делает gc. То есть, если вы ищете ответ, это может стать частью вопроса. - person andygavin; 11.09.2015