Они живут до тех пор, пока git gc
не очистит их, как сказал WofWca , но точно, когда это происходит, может быть немного трудно определить.
Некоторые команды запускают git gc --auto
длявы автоматически.В наши дни это включало git commit
: git commit
всегда должно было запускать это, но код был случайно отброшен в очень ранней версии Git - Git 1.5.4 - и не восстанавливался до 2.17.Но git gc --auto
ничего не делает, если, по его оценке, еще нет причин для запуска, и это в большинстве случаев выполняется. 1 Затем, когда git gc
решит, что должен запустить, или когда вы запускаете git gc
без --auto
, чтобы запустить его сразу, даже тогда он может не удалить эти коммиты пока .
Что поддерживает коммит?Ну, ответ сложный:
Каждая ссылка - и имена ветвей - это ссылки, полное имя которых начинается с refs/heads/
- может иметь reflog .В журнале reflog хранятся записей журнала reflog , которые представляют собой записи с метками времени, в которых, по сути, указана ссылка на хэш-идентификатор H на дату D .Это позволяет Git восстанавливать состояние ветви (или любой другой ссылки) по состоянию на конкретное время, заданное в абсолютном или относительном выражении, до тех пор, пока не истек срок действия записей reflog около этого времени.
Срок действия этих записей журнала do истекает, за исключением refs/stash
, для которого по умолчанию никогда не истек срок действия записей журнала.Git удаляет все просроченные записи, оставляя в журнале только не просроченные записи.Срок действия каждой записи настраивается.Значение по умолчанию составляет 30 или 90 дней, как установлено gc.reflogExpire
и gc.reflogExpireUnreachable
.Какой из них применяется?Ну, это сложно: это зависит от понятия достижимость .Чтобы получить полное представление о том, что означает достижимость, см. Think Like (a) Git .
В данном конкретном случае нас интересует, является ли идентификатор хеша, сохраненный в записи reflog,достижимо из хеш-идентификатора, хранящегося в самой ссылкеТо есть, учитывая имя типа refs/heads/master
, мы проверяем master@{1}
, чтобы увидеть, является ли это предком master
.Если это так, то запись reflog достижима (из текущего master
).Если нет, эта запись reflog является недоступной достижимой (из текущей master
).Это в свою очередь выбирает, какую из двух gc.reflogExpire
переменных следует использовать.(Если ветвь имеет пользовательскую настройку через gc.<pattern>.reflogExpire
и / или gc.<pattern>.reflogExpireUnreachble
, она используется вместо этого, конечно. В документации это называется pattern и, по-видимому, используется код соответствия шаблона имени файла,например, .gitattributes
.)
Выбрав переменную срока действия, Git сравнивает временную метку reflog с предполагаемой датой истечения срока действия.Если срок действия записи reflog истек, она удаляется.
Если запись reflog сохраняется, она защищает объект, идентификатор хеша которого содержит reflog, и всех объектов, доступных из этого объекта.,Для объектов коммита это означает, что сам коммит защищен, как и все его предки, а также их и их снимки.
Короткая версия этого заключается в том, что по умолчанию записи reflog остаются в течение как минимум 30 дней.,Записи рефлогов, которые являются предками текущей ветки, остаются в течение не менее 90 дней.После этого вида git reset
запись не является предком кончика ветви, поэтому применяется правило 30 дней.
Если шаг 1 не сохраняетнепосредственно для внутреннего объекта, существует также журнал для самого HEAD
, который может сохранить объект напрямую.И, конечно, любой из них может сохранить объект косвенно через правила достижимости.
Если ни шаги 1, ни 2 не сохраняют объект прямо или косвенно, он все еще может быть еще не удален: все объекты получают льготный период, который по умолчанию равен 14 дням и может быть настроен как gc.pruneExpire
.Этот льготный период не позволяет git gc --auto
, работающему в фоновом режиме, удалять объект, созданный какой-либо активной командой Git.Например, git commit
может работать git write-tree
, а git write-tree
занят выделением объектов дерева на основе содержимого индекса.После завершения git write-tree
, git commit
запускает git commit-tree
для создания самого объекта фиксации.
Все они встроены в git commit
, но, тем не менее, все они создают свободные объекты, ни один из которых не являетсяпока еще доступен из любой ссылки, поэтому все эти будут иметь право на сборку мусора.Но 14-дневный льготный период означает, что git commit
может, теперь, когда записаны некоторые древовидные объекты и новый объект фиксации, завершить фиксацию, указав имя ветви для фиксации и добавив запись reflog в reflog ветви.Пока git commit
удается выполнить все это в течение двух недель, Git в порядке.Если ваш компьютер слишком медленный, чтобы завершить git commit
за две недели, что ж, это довольно плохо, во многих отношениях, чем один.
Итак, это дает вам набор правил:какие коммиты сохраняются или нет.Кроме того, помните, что в репозиториях bare (хранящихся на серверах) обычно отключены повторные журналы, и они редко имеют дело с незакрепленными объектами - объекты, поступающие на серверы, обычно вводятся как тонкие pack , который сервер "откармливает", а затем обычно все равно перепаковывает в ближайшее время.Таким образом, серверы имеют тенденцию собирать свои объекты намного раньше, чем обычные репозитории, отличные от обычных.
1 Чтобы решить, пора ли что-то делать, git gc --auto
выполняет следующие шаги:
Подсчитать количество файлов pack , исключая помеченные "keep".Если это превышает пороговое значение, это время для gc, который включает в себя перепаковку.
Если шаг 1 не сработал, посчитайте количество потерянных объектов в *Каталог 1130 *.(17 здесь - произвольный выбор, и он жестко закодирован. Вы должны спросить у Линуса или кого-то еще, почему 17. Более очевидный выбор - 42 или, возможно, 2a, поскольку они шестнадцатеричные. :-)) Если это превышает пороговое значение, этовремя для сборщика мусора, который собирает один новый пакет.
Если шаг 1 или 2 не сработал, не выполняйте сбор мусора.В противном случае, запустите хук pre-auto-gc
, чтобы дать ему возможность прервать сборку мусора.Если ловушка не существует или выходит с успешным, т. Е. Нулевым, состоянием, продолжайте и выполните GC.
Два порога в шагах 1 и 2 управляются gc.autopacklimit
, который по умолчанию равен 50, и gc.auto
, который по умолчанию равен 6700. Вы можете настроить один или оба из них с помощью git config
.Если вы установите gc.auto
на ноль или отрицательный, это запрещает оба типа auto-gc, независимо от того, что вы установили gc.autopacklimit
на.
Число, которое вы настраиваете в gc.autopacklimit
, делится на 256 с дробнымчасть округляется, так что по умолчанию 6700 выдает 27 (6700/256 - 26.171875).Причина деления на 256 состоит в том, что незакрепленные объекты разбросаны по 256 подкаталогам на основе первых двух шестнадцатеричных символов их хеш-идентификатора объекта.Предполагается, что распределение хэшей является равномерным, поэтому, если в .git/objects/17
имеется 26 объектов, вероятно, также имеется около 26 объектов в каждом из других каталогов 255 .git/objects/<em>XX</em>
, поэтому примерно 26 x 256 = 6656 потерянныхобъекты.Если в 17/
имеется 27 незакрепленных объектов, вероятно, имеется около 27 x 256 = 6912 незакрепленных объектов.Оценка числа путем подсчета одного подкаталога происходит быстрее, чем вычисление фактического числа путем подсчета всех подкаталогов.Как обычно, Git делает все быстро, когда ему это удается, как в этом случае.