Как предотвратить сбор мусора в GIT?

Git загадочно запускает сбор мусора "время от времени" и удаляет и осиротевшие коммиты, которые у вас есть.

https://www.kernel.org/pub/software/scm/git/docs/git-gc.html

С научной точки зрения, это произойдет примерно через 6-8 часов, прежде чем вы осознаете, что вам действительно нужна эта фиксация, которая была просто удалена.

Я не хочу, чтобы мои файлы были удалены с помощью Git. Как вообще отключить автоматическую сборку мусора?

Ответ 1

Из той же самой страницы, с которой вы только что связались:

Некоторые команды git могут автоматически запускать git gc; подробнее см. флаг -auto. Если вы знаете, что делаете, и все, что вам нужно, - это отключить это поведение навсегда без дальнейших соображений, просто выполните:

$ git config --global gc.auto 0

Ответ 2

Другой подход, недавно задокументированный в:
Documentation/config: упомяните " now " и " never " для настроек "expire"

В дополнение к значениям в стиле приближения (" 2.months.ago ", " yesterday ") потребители конфигурационных переменных " gc.*expire* " также принимают и уважают " now " ("сделай это немедленно") и " never ". ("полностью подавить").

См. Коммит 8cc8816 (28 июля 2015 г.) Эрика Саншайна (sunshineco).
Предложил: Майкл Хаггерти (mhagger).
(Объединено Junio C Hamano - gitster - в коммите 8cc8816, 28 июля 2015 г.)

Это означает, что это также предотвратит любой gc:

git config --global gc.pruneExpire never
git config --global gc.reflogExpire never

Однако вы можете столкнуться (если вы never используете значение конфигурации):

warning: There are too many unreachable loose objects; run 'git prune' to remove them. 

В этом случае вы, вероятно, захотите установить для gc.auto какое-то высокое значение (например, 100000), если вы действительно не хотите ничего истекать. Это отключит предупреждение, но может привести к тому, что сборка мусора будет менее эффективной в целом, поэтому это следует рассматривать как обходной путь, а не как реальное решение. См. Возможно ли получить 'git gc' для упаковки объектов reflog? для дополнительных деталей.


Чтобы избежать git gc только в фоновом режиме, установите, как в ответе nornagon:

git config gc.autodetach false

Это происходит из коммита Git v2.14.0-rc1 c45af94 (11 июля 2017 г.) Джеффа Кинга (peff).
(Объединено Junio C Hamano - gitster - в коммите 764046f, 18 июля 2017 г.)

Мы запускаем раннюю часть " git gc ", которая имеет дело с ссылками перед демонами (и не под блокировкой), даже при запуске фонового auto-gc, что вызвало попытки нескольких процессов gc запустить раннюю часть одновременно.
Теперь это можно предотвратить, запустив раннюю часть также под замком GC.

gc: запустить pre- отсоединить операции под блокировкой

Обычно мы стараемся избегать одновременного запуска двух операций auto-gc, поскольку это приводит к напрасной трате ресурсов.
Это было сделано давно в 64a99eb (gc: отклонить, если запущен другой gc, если не указано --force, 2013-08-08, v1.8.5-rc0).

Когда мы выполняем отсоединенный auto-gc, мы запускаем связанные с ref команды перед отсоединением, чтобы избежать путаницы в блокировке.
Это было сделано 62aad18 (gc --auto: не блокировать ссылки в фоновом режиме, 2014-05-25, Git v2.0.1).

Эти две функции плохо взаимодействуют.
Операции отсоединения pre- запускаются до того, как мы проверим блокировку gc.pid, что означает, что в занятом репозитории мы можем запускать многие из них одновременно.
В идеале мы бы взяли блокировку перед порождением каких-либо операций и удерживали ее в течение всей программы.

Это сложно, однако, с тем, как pid файл взаимодействует с daemonize().
Другие процессы проверят, что pid, записанный в pid файле, все еще существует. Но отсоединение заставляет нас раскошелиться и продолжить работу под новым пидом.
Так что, если мы возьмем блокировку перед отсоединением, файл pid будет содержать поддельный pid. Мы должны были бы вернуться и обновить его новым pid после отсоединения.
Нам также пришлось бы поработать с подсистемой tempfile, чтобы настроить поле "owner", чтобы родительский процесс не очищал его при выходе, а дочерний процесс.

Вместо этого мы можем сделать что-то попроще: взять блокировку только на время отсоединения pre-, затем отсоединить, а затем снова сделать это для работы после отсоединения.

Технически это означает, что блокировка после отсоединения может проиграть другому процессу, выполняющему pre- отсоединение.
Но в конечном итоге это работает.

После этого второго процесса будет проведена последующая работа. Если только он не был заблокирован третьим процессом, выполняющим pre- отсоединение, и так далее.

Теоретически это может продолжаться до бесконечности, так как работа по отсоединению pre- не перепаковывается, и поэтому need_to_gc() будет продолжать срабатывать.
Но в каждом раунде мы участвуем в гонках между замками pre- и post-detach.
В конце концов, один из замков после отрыва выиграет гонку и завершит полный gc.

Таким образом, в худшем случае мы можем быстро повторить работу по отсоединению pre-, но мы никогда не сделаем это одновременно (это произойдет через последовательность сериализованных гонок).

Ответ 3

Я нашел этот ответ, потому что пытался запретить git запускать git gc в фоновом режиме, потому что он мешал другим операциям, которые я пытался выполнить в репо. Оказывается, вы можете специально отключить фоновое поведение с

$ git config gc.autodetach false