Линус предложил (полный список рассылки см. Ниже) использовать git gc --aggressive
только тогда, когда у вас, по его словам, « действительно плохой пакет» или «действительно ужасно плохие дельты», однако «почти всегда, в других случаях, это действительно очень плохо». вещь которую нужно сделать." Результат может даже оставить ваше хранилище в худшем состоянии, чем при запуске!
Команда, которую он предлагает сделать это правильно после импортирования «долгой и сложной истории», такова:
Date: Wed, 5 Dec 2007 22:09:12 -0800 (PST)
From: Linus Torvalds <torvalds at linux-foundation dot org>
To: Daniel Berlin <dberlin at dberlin dot org>
cc: David Miller <davem at davemloft dot net>,
ismail at pardus dot org dot tr,
gcc at gcc dot gnu dot org,
git at vger dot kernel dot org
Subject: Re: Git and GCC
In-Reply-To: <4aca3dc20712052111o730f6fb6h7a329ee811a70f28@mail.gmail.com>
Message-ID: <alpine.LFD.0.9999.0712052132450.13796@woody.linux-foundation.org>
References: <4aca3dc20712051947t5fbbb383ua1727c652eb25d7e@mail.gmail.com>
<20071205.202047.58135920.davem@davemloft.net>
<4aca3dc20712052032n521c344cla07a5df1f2c26cb8@mail.gmail.com>
<20071205.204848.227521641.davem@davemloft.net>
<4aca3dc20712052111o730f6fb6h7a329ee811a70f28@mail.gmail.com>
В четверг, 6 декабря 2007 г., Даниэль Берлин написал:
На самом деле, оказывается, что git-gc --aggressive
эта тупица иногда упаковывает файлы независимо от того, конвертировали вы из репозитория SVN или нет.
Абсолютно. git --aggressive
в основном тупой. Это действительно полезно только в том случае, если «я знаю, что у меня действительно плохая упаковка, и я хочу отбросить все плохие решения, которые я принял».
Чтобы объяснить это, стоит объяснить (вы, вероятно, знаете об этом, но позвольте мне в любом случае пройтись по основам), как работают дельта-цепочки git и чем они так отличаются от большинства других систем.
В других SCM дельта-цепочка обычно фиксируется. Это может быть «вперед» или «назад», и оно может немного развиваться по мере того, как вы работаете с репозиторием, но, как правило, это цепочка изменений одного файла, представленного как некая единая сущность SCM. В CVS, очевидно, это *,v
файл, и многие другие системы делают аналогичные вещи.
Git также создает дельта-цепочки, но делает их гораздо более «вольно». Нет фиксированной сущности. Дельты генерируются для любой другой случайной версии, которую git считает хорошим кандидатом в дельта (с различными довольно успешными эвристиками), и здесь нет абсолютно никаких правил жесткой группировки.
Это вообще очень хорошо. Это хорошо по разным концептуальным причинам ( например , git внутри никогда даже не нужно заботиться обо всей цепочке ревизий - он вообще не мыслит в терминах дельт), но это также здорово, потому что избавление от негибких правил дельты означает у этого git вообще нет проблем с объединением двух файлов, например - просто не существует произвольных *,v
«файлов ревизий», которые имеют какое-то скрытое значение.
Это также означает, что выбор дельт - гораздо более открытый вопрос. Если вы ограничите дельта-цепочку одним файлом, у вас действительно не будет большого выбора, что делать с дельтами, но в git это действительно может быть совершенно другой проблемой.
И вот --aggressive
тут-то и появляется действительно плохо названный . Хотя git обычно пытается повторно использовать дельта-информацию (потому что это хорошая идея, и он не тратит время процессора на повторное нахождение всех хороших дельт, которые мы нашли ранее), иногда вы хочу сказать: «Давайте начнем все сначала, с чистого листа, и проигнорируем всю предыдущую информацию о дельтах и попытаемся создать новый набор дельт».
Так --aggressive
что на самом деле речь идет не об агрессивности, а о том, чтобы тратить время процессора на повторное принятие решения, которое мы уже приняли ранее!
Иногда это хорошо. В частности, некоторые инструменты импорта могут создавать действительно ужасно плохие дельты. git fast-import
Например, все, что использует , скорее всего, не имеет хорошего дельта-макета, поэтому, возможно, стоит сказать: «Я хочу начать с чистого листа».
Но почти всегда, в других случаях, это действительно плохой поступок. Это приведет к потере процессорного времени, и особенно если вы действительно хорошо поработали с дельтами ранее, в конечном результате не будут повторно использоваться все те хорошие дельты, которые вы уже нашли, так что вы фактически получите много худший конечный результат тоже!
Я пришлю патч Юнио, чтобы просто удалить git gc --aggressive
документацию. Это может быть полезно, но обычно полезно только тогда, когда вы действительно очень глубоко понимаете, что он делает, и эта документация вам не поможет.
Как правило, постепенное выполнение git gc
- правильный подход, и он лучше, чем делать это git gc --aggressive
. Он будет повторно использовать старые дельты, и когда эти старые дельты не могут быть найдены (в первую очередь, причина для выполнения инкрементного сборщика мусора!), Он создаст новые.
С другой стороны, определенно верно, что «начальный импорт долгой и сложной истории» - это момент, когда стоит потратить много времени на поиск действительно хороших дельт. Тогда каждый пользователь когда-либо после (если он не использует его git gc --aggressive
для отмены!) Получит преимущество этого одноразового события. Так что особенно для больших проектов с долгой историей, вероятно, стоит проделать дополнительную работу, чтобы заставить дельта-поисковый код сойти с ума.
Таким образом, эквивалент git gc --aggressive
- но все сделано правильно - это сделать (за ночь) что-то вроде
git repack -a -d --depth=250 --window=250
где эта глубина касается как раз того, насколько глубокими могут быть дельта-цепочки (сделать их длиннее для старой истории - это стоит накладных расходов на пространство), а проблема окна заключается в том, насколько большое окно объекта мы хотим, чтобы каждый дельта-кандидат сканировал.
И здесь вы, возможно, захотите добавить -f
флаг (который означает «отбросить все старые дельты», поскольку сейчас вы на самом деле пытаетесь убедиться, что он действительно находит хороших кандидатов.
А потом это займет целую вечность и день ( например , «сделай это в одночасье»). Но в конечном итоге все, кто ниже по течению из этого репозитория, получат гораздо лучшие пакеты, не тратя на это никаких усилий.
Linus
Как я уже упоминал в статье «Сборка мусора Git, похоже, не работает полностью », одного
git gc --aggressive
элемента a недостаточно и даже недостаточно.И, как я объясню ниже , часто не нужны.
Самым эффективным сочетанием было бы добавление
git repack
, но такжеgit prune
:Примечание. Git 2.11 (4 квартал 2016 г.) установит
gc aggressive
глубину по умолчанию 50.См. Commit 07e7dbf (11 августа 2016 г.) Джеффа Кинга (
peff
) .(Объединено Junio C Hamano -
gitster
- в коммите 0952ca8 , 21 сентября 2016 г.)(См. Коммит для изучения )
Говоря об экономии CPU, "
git repack
" научилась принимать--threads=<n>
опцию и передавать ее pack-объектам.См. Commit 40bcf31 (26 апреля 2017 г.), автор Junio C Hamano (
gitster
) .(Объединено Junio C Hamano -
gitster
- в коммите 31fb6f4 , 29 мая 2017 г.)Мы уже делаем это для
--window=<n>
и--depth=<n>
; это поможет, когда пользователь хочет принудительно выполнить--threads=1
воспроизводимое тестирование, не подвергаясь влиянию гонок нескольких потоков.источник
git gc --aggressive
это было исправлено дважды: во-первых, сделать то, что Линус предложил в 2007 году как «лучший метод упаковки». А затем в Git 2.11, чтобы избежать чрезмерной глубины объекта, которую предложил Линус, но которая оказалась вредной (замедляет все будущие операции Git и не экономит место, о котором стоит говорить).man git-repack
говорит для-d
: «Также запустите git prune-Pack, чтобы удалить лишние свободные объектные файлы». Илиgit prune
тоже это делает?man git-prune
говоритIn most cases, users should run git gc, which calls git prune.
, так что толку послеgit gc
? Разве не было бы лучше или достаточно использовать толькоgit repack -Ad && git gc
?Проблема в
git gc --aggressive
том, что название параметра и документация вводят в заблуждение.Как объясняет сам Линус в этом письме , в
git gc --aggressive
основном это делается так:Обычно нет необходимости пересчитывать дельты в git, поскольку git определяет эти дельты очень гибко. Это имеет смысл только в том случае, если вы знаете, что у вас действительно очень плохие дельты. Как объясняет Линус,
git fast-import
в эту категорию попадают в основном инструменты, которые используют .В большинстве случаев git довольно хорошо справляется с определением полезных дельт, и использование
git gc --aggressive
оставляет вас с дельтами, которые потенциально могут быть еще хуже, при этом тратя много времени ЦП.Линус заканчивает свою почту с выводом , что
git repack
с большим--depth
и--window
является лучшим выбором в большинстве времени; особенно после того, как вы импортировали большой проект и хотите убедиться, что git находит хорошие дельты.источник
Осторожно. Не беги
git gc --agressive
репозиторий, который не синхронизирован с удаленным, если у вас нет резервных копий.Эта операция воссоздает дельты с нуля и может привести к потере данных, если ее корректно прервать.
Для моего компьютера с 8 ГБ агрессивному gc не хватило памяти в репозитории 1 ГБ с небольшими коммитами 10k. Когда OOM killer завершил процесс git - он оставил у меня почти пустой репозиторий, сохранилось только рабочее дерево и несколько дельт.
Конечно, это была не единственная копия репозитория, поэтому я просто воссоздал ее и вытащил с удаленного (выборка не работала на сломанном репо и заходила в тупик на этапе разрешения дельт несколько раз, я пытался это сделать), но если ваше репо локальное репозиторий одного разработчика без пультов - сначала сделайте резервную копию.
источник
Примечание: остерегайтесь использования
git gc --aggressive
, как поясняет Git 2.22 (второй квартал 2019 г.).См совершают 0044f77 , совершают daecbf2 , совершают 7384504 , совершают 22d4e3b , совершают 080a448 , совершают 54d56f5 , совершают d257e0f , совершают b6a8d09 (7 апреля 2019), и совершают fc559fb , совершают cf9cd77 , совершают b11e856 (22 март 2019) с помощью Эвар Arnfjord Bjarmason (
avar
) .(Объединено Junio C Hamano -
gitster
- в фиксации ac70c53 , 25 апреля 2019 г.)Это означает, что документация по git-gc теперь включает :
И ( совершить 080a448 ):
источник