Как использовать git sparse-checkout в версии 2.27+

Я пытался воспроизвести несколько шагов из руководства:

https://github.blog/2020-01-17-bring-your-monorepo-down-to-size-with-sparse-checkout

Это было сделано для git 2.25, но теперь в 2.27 ничего не происходит при запуске:

$ git sparse-checkout set client/android

Я не могу найти способ заставить его работать.

Вот MWE:

$ git clone --no-checkout https://github.com/derrickstolee/sparse-checkout-example
Cloning into 'sparse-checkout-example'...

$ cd sparse-checkout-example/

$ git sparse-checkout init --cone

Используя git 2.25, я получаю непустой каталог:

$ ls -a
.  .. bootstrap.sh LICENSE.md  README.md .git

Используя git 2.27, я получаю пустой каталог:

$ ls -a
.  .. .git

4 ответа

Решение

Думаю, я нашел для этого причину. Зафиксировать f56f31af0301 в Git изменили реализацию sparse-checkout так что, когда у вас есть неинициализированное рабочее дерево (как и сразу после запуска git clone --no-checkout), Бег git sparse-checkout initне будет извлекать файлы из вашего рабочего дерева. В предыдущих версиях команда фактически извлекала файлы, что могло иметь неожиданные последствия, учитывая, что в этот момент у вас не было активной ветки.

Соответствующий коммит, f56f31af0301был включен в Git 2.27, но не в 2.25. Это объясняет, почему поведение, которое вы видите, не соответствует поведению, показанному на веб-странице, за которой вы пытаетесь следовать. По сути, поведение на веб-странице было ошибкой, которую в то время никто не осознавал, но в Git 2.27 она была исправлена.

Я думаю, это очень хорошо объясняется в сообщении для фиксации b5bfc08a972d:

Итак... это подводит нас к особому случаю: клон git, выполняемый с --no-checkout. Согласно значению флага,--no-checkoutне проверяет какую-либо ветку, подразумевая, что вы не в одной из них и вам нужно переключиться на одну после клона. В практическом планеHEAD все еще установлен (так что в некотором смысле вы частично находитесь на ветке), но

  • индекс "нерожденный" (не существует)
  • в рабочем дереве нет файлов (кроме .git/)
  • в следующий раз git switch (или git checkout) запускается unpack_trees с initial_checkout флаг установлен в значение true.

Это не так, пока вы не запустите, например git switch <somebranch> что индекс будет записан, а файлы в рабочем дереве заполнены.

С этим особенным --no-checkout случай, традиционный read-tree -mu HEAD поведение было бы эквивалентно действию как checkout - перейти в ветку по умолчанию (HEAD), выпишите индекс, соответствующий HEAD, и обновите рабочее дерево, чтобы оно соответствовало. Этот особый случай ускользнул от проверки на избежание внесения изменений в оригинале.sparse-checkout команда и таким образом продолжил там.

После update_sparsity() был введен и использован (см. коммит f56f31a ("sparse-checkout: use new update_sparsity() function", 2020-03-27)) поведение для --no-checkout case изменен: из-за автоматического оживления пустого индекса в памяти git (см. do_read_index() и обратите внимание, что must_exist ложно), и из-за sparse-checkoutс update_working_directory()код, чтобы всегда записывать индекс после того, как это было сделано, мы получили новую ошибку. Это сделало так, чтоsparse-checkout переключит репозиторий с клона с "нерожденным" индексом (т.е. все еще нуждается в initial_checkout) на тот, у которого был записанный указатель без записей. Таким образом, вместо того, чтобы все файлы были удалены вgit status Поскольку git известен как особый артефакт того, что он еще не находится в ветке, наша запись пустого индекса заставила его внезапно выглядеть как git, как если бы он определенно находился в ветке со ВСЕМИ файлами, подготовленными для удаления! Последующая проверка или переключение должны были бороться с тем фактом, что он не былinitial_checkout но было несколько поэтапных удалений.

Вот решение, которое будет заполнять только файлы в корневой папке:

$ git clone --filter=blob:none --sparse https://github.com/derrickstolee/sparse-checkout-example

Тогда последующие звонки с редкими проверками работают как шарм.

До сих пор не понимаю, почему учебник не работает.

Я уже упоминал ранее в разделе « Почему исключенные файлы продолжают появляться в моем git sparse checkout? », Что любой файл skip-worktree не должен больше изменяться или даже просматриваться во время разреженной проверки с Git 2.27+.

Но с новым sparceIndex вариант с Git 2.32 (2 квартал 2021 г.), который снова меняется:

В Git 2.32 (второй квартал 2021 г.) он строится поверх инфраструктуры разреженного индекса, чтобы отмечать операции, которые не готовы пометить разреженным индексом, заставляя их возвращаться к полностью заполненному индексу, с которым они всегда работали.

См совершают 4589bca , совершают 71f82d0 , совершают 5f11669 (12 апреля 2021), совершают f5fed74 , совершают dc26b23 , совершают 0c18c05 , совершают 465a04a , совершают f7ef64b , совершают 3450a30 , совершают d425f65 , совершают 2508df0 , совершают a029120 , совершают e43e2a1 , совершают 299e2c4 , совершают 42f44e8 , фиксация 46eb6e3 , фиксация 2227ea1 , фиксация 48b3c7d , фиксация cb8388d , фиксация 0f6d3ba, Совершают 1b850d3 , совершают 54beed2 , совершают 118a2e8 , совершают 95e0321 , совершают 847a9e5 , совершают 839a663 (01 апр 2021), а также совершать c9e40ae , совершают 9ad2d5e , совершают 2de37c5 , совершают dcc5fd5 , , совершают 58300f4 , совершают 0938e6f , совершают 13e1331 , совершают f442313 , фиксация 6e77352 , фиксация cd42415 , фиксация 836e25c , фиксация 6863df3 , фиксация 2782db3, фиксация e2df6c3 , фиксация ecfc47c , фиксация 4300f84 , фиксация 3964fc2 , фиксация 4b3f765 , фиксация 0b5fcb0 , (30 марта 2021 г.) Деррик Столи ( derrickstolee) .
(Слияние Junio ​​C Hamano - gitster- в коммите 8e97852 , 30 апр 2021 г.)

фиксация 0ad6090sparse-index: дизайн документа и обновление формата

Подписано: Деррик Столи

С этого начинается долгая работа по обновлению формата индекса, чтобы разрешить разреженные записи каталога.
Это должно привести к значительному улучшению команд Git, когда HEAD содержит миллионы файлов, но пользователь выбрал гораздо меньше файлов для сохранения в их определении.

В настоящее время формат индекса обновляется только при наличии, а не при увеличении номера версии формата файла.
Это временно, и индекс v5 является частью плана будущей работы в этой области.

В проектной документации подробно описаны многие причины для начала этой работы, а также план ее безопасного завершения.

technical/index-formatтеперь включает в свою справочную страницу :

Запись индекса обычно представляет собой файл. Однако, если разреженная проверка включена в режиме конуса (включена) и extensions.sparseIndexрасширение включено, то индекс может содержать записи для каталогов вне определения sparse-checkout. Эти записи имеют режим 040000, включите бит, и путь заканчивается разделителем каталогов.

technical/sparse-indexтеперь включает в свою справочную страницу :

Проектный документ Git Sparse-Index

Функция разреженной проверки позволяет пользователям сосредоточить рабочий каталог на подмножестве файлов в HEAD. Шаблоны режима конуса, включенные core.sparseCheckoutCone, позволяют очень быстро сопоставить с образцом, чтобы определить, какие файлы в HEAD принадлежат конусу разреженной проверки.

Три важных измерения масштаба для рабочего каталога Git:

  • : Сколько файлов присутствует?

  • Заполнено: сколько файлов находится в конусе разреженной проверки.

  • Изменено: сколько файлов пользователь изменил в рабочем каталоге?

Мы будем использовать нотацию большого O - O(X) - чтобы обозначить, насколько дороги определенные операции с точки зрения этих размеров.

Эти размеры упорядочены по их величине: пользователи (обычно) изменяют меньше файлов, чем заполнено, и мы можем заполнить файлы только в.

Проблемы возникают, если наблюдается крайний дисбаланс в этих размерах. Например, если содержит миллионы путей, но заполненный набор содержит только десятки тысяч, тогда команды, такие как и могут преобладать над операциями, которые требуют операций O() вместо O(заполнено). В первую очередь затраты заключаются в синтаксическом анализе и перезаписи индекса, который в основном заполняется файлами, помеченными битом.

Sparse-index намеревается принимать эти команды, которые читают и изменяют индекс с O() на O(заполнено) .

Для этого нам нужно существенно изменить формат индекса: добавить " sparse directory"записи.

С помощью шаблонов режима конуса можно определить, когда весь каталог будет иметь свое содержимое за пределами определения разреженной проверки. Вместо того, чтобы перечислять все файлы, которые он содержит, как отдельные записи, разреженный индекс содержит запись с именем каталога, ссылающуюся на идентификатор объекта дерева в HEAD и отмечен SKIP_WORKTREEнемного. Если нам нужно узнать подробности о путях в этом каталоге, мы можем проанализировать деревья, чтобы найти этот список.

Итак, у вас есть новая возможность:

совершают 122ba1fsparse-checkout: переключить разреженный индекс со встроенного

Подписано: Деррик Столи

Расширение разреженного индекса используется для обозначения того, что запись индекса должна выполняться в разреженном режиме.
Это было обновлено только с использованием GIT_TEST_SPARSE_INDEX=1.

Добавьте параметр '- [no-] sparse-index' в ' '( man ), который указывает, следует ли использовать разреженный индекс.
Он также обновляет индекс, чтобы в любом случае использовать правильный формат.
Добавьте в документацию предупреждение о том, что использование расширения репозитория может снизить совместимость со сторонними инструментами.
' git sparse-checkout init уже устанавливает extension.worktreeConfig, что выводит пользователей с редкими заказами вне сферы действия большинства сторонних инструментов.

git sparse-checkoutтеперь включает в свою справочную страницу :

Использовать --[no-]sparse-index опция для переключения использования формата разреженного индекса.

Это уменьшает размер индекса, чтобы он лучше соответствовал вашему определению разреженной проверки.

Это может иметь значительные преимущества в производительности для таких команд, как git status или же git add. Эта функция все еще экспериментальная. Некоторые команды могут работать медленнее с разреженным индексом, пока они не будут должным образом интегрированы с функцией.

ПРЕДУПРЕЖДЕНИЕ. Использование разреженного индекса требует изменения индекса таким образом, чтобы его не полностью понимали внешние инструменты. Если у вас проблемы с совместимостью, запустите git sparse-checkout init --no-sparse-index чтобы переписать индекс, чтобы он не был разреженным.

Более старые версии Git не распознают расширение индекса разреженных записей каталога и могут не взаимодействовать с вашим репозиторием, пока оно не будет отключено.

В Git 2.35 (1 квартал 2022 г.) подкоманды "" и "" в "git sparse-checkout" ( man ) были унифицированы для лучшего взаимодействия с пользователем и производительности.

См. коммит dfac9b6 (23 декабря 2021 г.) и коммит d359541 , коммит d30e2bb , коммит ba2f3f5 , коммит 4e25673 , , коммит be61fd1 , коммит f85751a , коммит 45c5e47 , коммит 0b624e0 , коммит 1530ff3 (214) от Elihren 2jaren ( 214 Dec 2jaren)newren) .
(Объединено Junio ​​C Hamano -- gitster-- в коммите 2dc94da , 3 января 2022 г.)

коммит f2e3a21sparse-checkout: включить для инициализации режима разреженной проверки

Рецензировал: Деррик Столи
Рецензировал: Виктория Дай
Подписал: Элайджа Ньюрен

Предложенный ранее рабочий процесс: git sparse-checkout init...git sparse-checkout set...

Столкнулся с тремя проблемами:

  1. Он удалит почти все файлы на первом этапе, а затем восстановит их на втором.
    Это была плохая производительность и вынужденные ненужные перестроения.
  2. Двухэтапный процесс привел к появлению двух индикаторов выполнения, что было неоптимально с точки зрения пользовательского интерфейса для оболочек, которые вызывали обе эти команды, но предоставляли своим конечным пользователям только одну команду.
  3. В конусном режиме первым шагом будет удаление почти всех игнорируемых файлов повсюду, потому что все считалось находящимся за пределами указанных путей разреженности.
    (Пользователю не разрешалось указывать какие-либо пути разреженности на этом шаге.)

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

Другие вопросы по тегам