git-sparse-checkout
Название
git-sparse-checkout — сократить рабочее дерево до подмножества отслеживаемых файлов
Краткое описание
git sparse-checkout (init | list | set | add | reapply | disable | check-rules | clean) [<options>]
Описание
Эта команда используется для создания разреженных копий, в которых рабочее дерево, изначально содержащее все отслеживаемые файлы, сокращается до подмножества этих файлов. Она также может переключать набор присутствующих файлов или отменять разреженную копию и возвращать все отслеживаемые файлы в рабочую копию.
Подмножество файлов выбирается путем указания списка каталогов в режиме конуса (по умолчанию) или списка шаблонов в режиме без конуса.
В разреженной копии другие команды Git работают несколько иначе. Например, переключение веток не обновляет пути за пределами каталогов/шаблонов разреженной копии, а git commit -a не записывает пути за пределами каталогов/шаблонов разреженной копии как удалённые.
ЭТА КОМАНДА ЭКСПЕРИМЕНТАЛЬНАЯ. ЕЁ ПОВЕДЕНИЕ И ПОВЕДЕНИЕ ДРУГИХ КОМАНД ПРИ НАЛИЧИИ РАЗРЕЖЕННЫХ КОПИЙ, ВЕРОЯТНО, ИЗМЕНИТСЯ В БУДУЩЕМ.
Команды
- list
-
Описать каталоги или шаблоны в файле разреженной копии.
- set
-
Включить необходимые параметры конфигурации разреженной копии (
core.sparseCheckout,core.sparseCheckoutConeиindex.sparse), если они ещё не установлены в требуемые значения, заполнить файл разреженной копии списком аргументов, следующих за подкомандойset, и обновить рабочий каталог соответствующим образом.Чтобы изменение параметров разреженной копии в одном рабочем дереве не затрагивало параметры разреженной копии в других рабочих деревьях, подкоманда
setобновит конфигурацию репозитория, включив конфигурацию для конкретного рабочего дерева, если она ещё не включена. Разреженность, задаваемая аргументами подкомандыset, хранится в файле разреженной копии для конкретного рабочего дерева. Подробнее см. git-worktree[1] и документацию поextensions.worktreeConfigв git-config[1].Если указан параметр
--stdin, каталоги или шаблоны считываются из стандартного ввода в виде списка, разделённого символами новой строки, а не из аргументов.По умолчанию входной список считается списком каталогов, соответствующим выводу
gitls-tree-d--name-only. В частности, имена путей, начинающиеся с двойной кавычки ("), интерпретируются как строки в кавычках в стиле C. Обратите внимание: в разреженную копию будут включены все файлы во всех указанных каталогах (на любой глубине), а также файлы, находящиеся на одном уровне с указанным каталогом или любым из его родительских каталогов (подробнее см. ниже в разделеCONE PATTERN SET). Ранее это не было поведением по умолчанию, и требовалось указывать--coneили включатьcore.sparseCheckoutCone.Если указан
--no-cone, входной список считается списком шаблонов. У этого режима есть ряд недостатков, в том числе несовместимость с некоторыми параметрами, такими как--sparse-index. Как объясняется ниже в разделе «Проблемы режима без конуса», мы не рекомендуем его использовать.Используйте параметр
--[no-]sparse-index, чтобы применять разреженный индекс (по умолчанию он не используется). Разреженный индекс уменьшает размер индекса, приближая его к размеру, определяемому настройками разреженной копии. Это может значительно повысить производительность таких команд, какgitstatusилиgitadd. Эта возможность всё ещё экспериментальная. Некоторые команды с разреженным индексом могут работать медленнее, пока не будут должным образом интегрированы с этой возможностью.ПРЕДУПРЕЖДЕНИЕ: Для использования разреженного индекса требуется изменить индекс способом, который внешние инструменты понимают не полностью. Если возникнут проблемы совместимости, выполните
gitsparse-checkoutinit--no-sparse-index, чтобы перезаписать индекс в обычном, неразреженном виде. Старые версии Git не распознают расширение индекса с записями разреженных каталогов и могут не работать с репозиторием, пока эта возможность не будет отключена. - add
-
Обновить файл разреженной копии, добавив каталоги (в режиме конуса) или шаблоны (в режиме без конуса). По умолчанию эти каталоги или шаблоны считываются из аргументов командной строки, но их также можно считывать из стандартного ввода с помощью параметра
--stdin. - reapply
-
Повторно применить правила шаблонов разреженности к путям в рабочем дереве. Такие команды, как merge или rebase, могут материализовать пути для выполнения своей работы (например, чтобы показать конфликт), а другие команды разреженной копии могут не суметь сделать разреженным отдельный файл (например, если в нём есть неиндексированные изменения или конфликты). В таких случаях после очистки затронутых путей (например, после разрешения конфликтов, отмены или фиксации изменений и т. д.) имеет смысл выполнить
gitsparse-checkoutreapply.Команда
reapplyтакже принимает флаги--[no-]coneи--[no-]sparse-indexс тем же значением, что и флаги командыset. Они позволяют изменить используемый режим разреженности, не указывая заново все пути разреженности. - clean
-
По возможности удалить файлы за пределами определения разреженной копии. Для этой команды требуется режим конуса, чтобы по совпадениям с рекурсивными каталогами определять, какие файлы следует удалить. Файл рассматривается для удаления, если он находится в отслеживаемом каталоге за пределами определения разреженной копии.
В некоторых особых случаях, например при конфликтах слияния или изменённых файлах за пределами определения разреженной копии, файлы, которые иначе были бы удалены, могут сохраниться. Чтобы разрешить такие ситуации, разрешите конфликты, добавьте изменения в индекс и используйте
gitsparse-checkoutreapplyвместе сgitsparse-checkoutclean.Эту команду можно использовать, чтобы убедиться в эффективной работе разреженного индекса, хотя для этого не требуется включать разреженный индекс с помощью параметра конфигурации
index.sparse=true.Чтобы предотвратить случайное удаление файлов рабочего дерева, подкоманда
cleanне удаляет файлы без параметра-fили--force, если только параметр конфигурацииclean.requireForceне установлен в значениеfalse.Параметр
--dry-runвыводит список каталогов, которые были бы удалены, но не удаляет их. Этот режим полезен для предварительной проверки поведения команды clean или определения, какие типы файлов остаются в разреженных каталогах.Параметр
--verboseвыводит список всех файлов в каталогах, рассматриваемых для удаления. Этот параметр помогает определить, действительно ли эти файлы важны, или выяснить, почему каталог всё ещё существует при текущих настройках разреженной копии. - disable
-
Отключить параметр конфигурации
core.sparseCheckoutи восстановить рабочий каталог, включив в него все файлы. - init
-
Устаревшая команда, работающая как
setбез указания путей. В будущем она может быть удалена.Раньше
setне обрабатывала все необходимые параметры конфигурации, поэтому требовалось вызывать иinit, иset. При их совместном вызове сначала шагinitудалял почти все отслеживаемые файлы (а в режиме конуса — также игнорируемые файлы), а затем шагsetвозвращал многие отслеживаемые файлы (но не игнорируемые). Помимо потери файлов, производительность и удобство такого сочетания команд были низкими.Кроме того, раньше
initфактически не инициализировала файл разреженной копии, если он уже существовал. Благодаря этому можно было вернуться к разреженной копии, не запоминая, какие пути передавать последующей командеsetилиadd. Однако параметры--coneи--sparse-indexне сохранялись при выполнении команды disable, поэтому простой способ восстановления с помощью обычной командыinitстал менее полезен. - check-rules
-
Проверить, соответствуют ли правила разреженности одному или нескольким путям.
По умолчанию
check-rulesсчитывает список путей из стандартного ввода и выводит только те, которые соответствуют текущим правилам разреженности. Ожидается, что входные данные содержат по одному пути на строку, как в выводеgitls-tree--name-only; имена путей, начинающиеся с двойной кавычки ("), интерпретируются как строки в кавычках в стиле C.Если указан флаг
--rules-file<file>, входные пути сопоставляются с правилами разреженной копии из <file>, а не с текущими правилами. Ожидается, что правила в файлах имеют тот же формат, который принимаетgitsparse-checkoutset--stdin(в частности, они должны быть разделены символами новой строки).По умолчанию правила, передаваемые параметру
--rules-file, интерпретируются как каталоги режима конуса. Чтобы передать шаблоны режима без конуса с помощью--rules-file, сочетайте этот параметр с параметром--no-cone.Если указан флаг
-z, пути во входных данных из стандартного ввода и выходные пути завершаются символом \0 и не заключаются в кавычки. Обратите внимание: это не относится к формату правил, передаваемых параметру--rules-file.
Примеры
-
gitsparse-checkoutsetMY/DIR1SUB/DIR2 -
Перейти к разреженной копии, в которой в рабочей копии присутствуют все файлы (на любой глубине) в MY/DIR1/ и SUB/DIR2/, а также все файлы непосредственно в MY/ и SUB/ и в корневом каталоге. Если вы уже работаете с разреженной копией, изменить набор файлов, присутствующих в рабочей копии, в соответствии с новым выбором. Обратите внимание: эта команда также удалит все игнорируемые файлы в каталогах, где больше нет ни отслеживаемых, ни неигнорируемых неотслеживаемых файлов.
-
gitsparse-checkoutdisable -
Заполнить рабочий каталог всеми файлами, отключив разреженные копии.
-
gitsparse-checkoutaddSOME/DIR/ECTORY -
Добавить в разреженную копию все файлы (на любой глубине) из SOME/DIR/ECTORY/, а также все файлы непосредственно из SOME/DIR/ и SOME/. Перед использованием этой команды необходимо уже работать с разреженной копией.
-
gitsparse-checkoutreapply -
Команды могут обновлять рабочее дерево, не учитывая выбранные каталоги разреженности. Это может происходить из-за записи файлов внешними по отношению к Git инструментами или затрагивать сами команды Git в особых случаях (например, при возникновении конфликтов во время слияния или перебазирования) либо из-за неполной поддержки разреженных копий некоторыми командами (например, старый механизм слияния
recursiveподдерживал их лишь ограниченно). Эта команда повторно применяет существующие спецификации разреженных каталогов, чтобы привести рабочий каталог в соответствие с ними.
Внутреннее устройство — разреженная копия
«Разреженная копия» позволяет выборочно заполнять рабочий каталог. Для этого используется бит skip-worktree (см. git-update-index[1]), который сообщает Git, стоит ли учитывать файл в рабочем каталоге. Если бит skip-worktree установлен и файл отсутствует в рабочем дереве, отсутствие файла игнорируется. Git не будет заполнять содержимое таких файлов, поэтому разреженная копия полезна при работе с репозиторием, содержащим много файлов, из которых текущему пользователю нужны лишь некоторые.
Файл $GIT_DIR/info/sparse-checkout используется для определения битовой карты skip-worktree. При обновлении рабочего каталога Git обновляет биты skip-worktree в индексе на основе этого файла. Файлы, соответствующие шаблонам в файле, появятся в рабочем каталоге, а остальные — нет.
Внутреннее устройство — проблемы режима без конуса
Файл $GIT_DIR/info/sparse-checkout, заполняемый подкомандами set и add, содержит набор шаблонов (по одному на строку) с тем же синтаксисом, что и файлы .gitignore. В режиме конуса эти шаблоны ограничены совпадениями с каталогами (и пользователям нужно указывать или видеть только имена каталогов), тогда как в режиме без конуса разрешён любой шаблон в стиле gitignore. Использование в режиме без конуса полноценных шаблонов в стиле gitignore имеет ряд недостатков:
-
Прежде всего, различные процессы обновления рабочего дерева (pull, merge, rebase, switch, reset, checkout и т. д.) требуют O(N*M) сопоставлений с шаблонами, где N — число шаблонов, а M — число путей в индексе. При увеличении объёма данных производительность резко ухудшается.
-
Избежать проблем с масштабированием можно, ограничив число шаблонов указанием начального имени каталога или glob-шаблона.
-
Передача glob-шаблонов в командной строке чревата ошибками: пользователи могут забыть заключить шаблон в кавычки, в результате чего оболочка раскроет его во все соответствующие файлы и передаст их по отдельности команде sparse-checkout set/add. Подобная проблема возможна, например, с «git grep — *.c», но ошибки в grep/log/status заметны сразу по выводу команды. В случае sparse-checkout ошибка записывается при выполнении команды разреженной копии и может не проявиться до тех пор, пока пользователь позднее не переключит ветку, не выполнит перебазирование или слияние. Поэтому между ошибкой пользователя и возможностью её обнаружить может пройти время.
-
В связи с предыдущим пунктом у sparse-checkout есть подкоманда
add, но нет подкомандыremove. Даже если добавить подкомандуremove, отмена случайно переданного без кавычек glob-шаблона чревата «удалением лишнего», поскольку могут быть удалены записи, включённые ещё до ошибочного добавления. -
В режиме без конуса используются шаблоны в стиле gitignore для выбора того, что нужно включить (за исключением отрицающих шаблонов), тогда как файлы .gitignore используют шаблоны в стиле gitignore для выбора того, что нужно исключить (за исключением отрицающих шаблонов). В документации по шаблонам в стиле gitignore обычно речь идёт не о совпадениях или несовпадениях, а о том, что пользователь хочет «исключить». Это может запутать пользователей, которые пытаются разобраться, как задавать шаблоны разреженной копии для получения желаемого результата.
-
Все остальные подкоманды git, которым требуется своего рода «особое сопоставление шаблонов путей», используют спецификации путей (pathspec), но режим без конуса в sparse-checkout использует шаблоны gitignore, что выглядит непоследовательно.
-
Есть неоднозначные случаи, в которых неясно, какое поведение считать «правильным». Вот два примера:
Два пользователя находятся в подкаталоге, и первый выполняет
git sparse-checkout set '/toplevel-dir/*.c'
а второй выполняет
git sparse-checkout set relative-dir
Следует ли преобразовать эти аргументы в
current/subdirectory/toplevel-dir/*.c
и
current/subdirectory/relative-dir
перед добавлением в файл разреженной копии? Пользователь, введший первую команду, вероятно, знает, что в режиме без конуса аргументы set/add должны быть шаблонами, и, скорее всего, не обрадуется такому преобразованию. Однако многие шаблоны в стиле gitignore — это просто пути, что, возможно, имел в виду пользователь, введший вторую команду; он будет недоволен, если его аргумент не преобразуют.
Во-вторых, что должна подставлять автодополнение bash для команд set/add в режиме без конуса? Если оно предлагает пути, не усугубляет ли это описанную выше проблему? Кроме того, если оно предлагает пути, что произойдёт, если имя файла или каталога начинается с
!или#либо содержит в имени*,\,?,[или]? А если оно предлагает пути, преобразует ли оно «/pro» в «/proc» (в корневой файловой системе), а не в «/progress.txt» в текущем каталоге? (Обратите внимание: в режиме без конуса пользователи, вероятно, захотят начинать пути с начального/по той же причине, по которой он часто используется в файлах .gitignore.) Подстановка файлов или каталогов во всех этих случаях может приводить к неприятным неожиданностям. -
Излишняя гибкость сделала другие расширения практически нереализуемыми.
--sparse-indexв режиме без конуса, вероятно, реализовать невозможно; даже если это каким-то образом возможно, реализация потребовала бы гораздо больше усилий и могла бы работать слишком медленно. Некоторые идеи по добавлению взаимодействия между частичными клонами и разреженными копиями также практически осуществимы только при более строгих ограничениях на набор путей.
По всем этим причинам режим без конуса считается устаревшим. Перейдите на режим конуса.
Внутреннее устройство — обработка режима конуса
«Режим конуса», используемый по умолчанию, позволяет указывать только каталоги для включения. Для каждого указанного каталога включаются все пути внутри него, а также все пути непосредственно в родительских каталогах (включая корневой каталог). Таким образом, если указать каталог Documentation/technical/, разреженная копия будет содержать:
-
все файлы в корневом каталоге
-
все файлы непосредственно в Documentation/
-
все файлы на любой глубине в Documentation/technical/
Кроме того, в режиме конуса файлы в корневом каталоге включаются, даже если каталоги не указаны.
При изменении шаблонов разреженной копии в режиме конуса Git проверяет каждый отслеживаемый каталог за пределами конуса разреженной копии на наличие неотслеживаемых файлов. Если все такие файлы игнорируются согласно шаблонам .gitignore, каталог будет удалён. Если хотя бы один неотслеживаемый файл в этом каталоге не игнорируется, удаление файлов в этом каталоге не выполняется и выводится предупреждение. Если эти файлы важны, измените определение разреженной копии, чтобы включить их, используйте git add и git commit, чтобы сохранить их, а затем вручную удалите оставшиеся файлы, чтобы Git мог работать оптимально.
О том, как каталоги преобразуются внутри Git в подмножество полного набора шаблонов разреженной копии, см. также раздел «Внутреннее устройство — набор шаблонов режима конуса».
Внутреннее устройство — полный набор шаблонов
Полный набор шаблонов допускает произвольное сопоставление с шаблонами и сложные правила включения/исключения. При обновлении индекса это может привести к O(N*M) сопоставлениям с шаблонами, где N — число шаблонов, а M — число путей в индексе. Для решения этой проблемы с производительностью при включённом параметре core.sparseCheckoutCone допускается более ограниченный набор шаблонов.
В файле разреженной копии используется тот же синтаксис, что и в файлах .gitignore; подробности см. в gitignore[5]. Однако здесь шаблоны обычно используются для выбора файлов, которые нужно включить, а не исключить. (Это может немного запутать, поскольку шаблоны в стиле gitignore задают отрицание с помощью шаблонов, начинающихся с !, поэтому можно также выбрать файлы, которые нужно not включить.)
Например, чтобы выбрать всё, а затем исключить файл unwanted (так, чтобы в рабочем дереве отображался каждый файл, кроме файла с именем unwanted):
git sparse-checkout set --no-cone '/*' '!unwanted'
Эти шаблоны без изменений помещаются в $GIT_DIR/info/sparse-checkout, поэтому на этом этапе содержимое этого файла будет таким:
/* !unwanted
Дополнительные сведения о шаблонах в стиле gitignore, используемых в разреженных копиях, см. также в разделе «Sparse Checkout» страницы git-read-tree[1].
Внутреннее устройство — набор шаблонов режима конуса
В режиме конуса допускаются только каталоги, но они преобразуются в те же шаблоны в стиле gitignore, что и в полном наборе шаблонов. Используемые в этом режиме шаблоны относятся к одному из двух типов:
-
Рекурсивный: включаются все пути внутри каталога.
-
Родительский: включаются все файлы непосредственно внутри каталога.
Поскольку режим конуса всегда включает файлы в корневом каталоге, при запуске git sparse-checkout set без указания каталогов корневой каталог добавляется как родительский шаблон. В этот момент файл разреженной копии содержит следующие шаблоны:
/* !/*/
Это означает: «включить всё непосредственно в корневом каталоге, но ничего на более низких уровнях».
В режиме конуса подкоманда git sparse-checkout set принимает список каталогов. Команда git sparse-checkout set A/B/C задаёт каталог A/B/C как рекурсивный шаблон, а каталоги A и A/B добавляются как родительские шаблоны. В результате файл разреженной копии теперь выглядит так:
/* !/*/ /A/ !/A/*/ /A/B/ !/A/B/*/ /A/B/C/
В данном случае порядок имеет значение: отрицательные шаблоны переопределяются положительными шаблонами, расположенными ниже в файле.
Если для параметра core.sparseCheckoutCone явно не задано значение false, Git будет анализировать файл разреженной копии, ожидая шаблоны этих типов. Если шаблоны не соответствуют ожидаемому формату, Git выдаст предупреждение. Если шаблоны соответствуют ожидаемому формату, Git будет использовать более быстрые алгоритмы на основе хеширования для вычисления включения в разреженную копию. Если они не соответствуют формату, Git будет вести себя так, как если бы значение core.sparseCheckoutCone было false, независимо от его фактической настройки.
В режиме конуса, несмотря на то что в файле $GIT_DIR/info/sparse-checkout записываются полные шаблоны, подкоманда git sparse-checkout list выводит каталоги, задающие рекурсивные шаблоны. Для приведённого выше примера файла разреженной копии вывод будет таким:
$ git sparse-checkout list A/B/C
Если включён параметр core.ignoreCase=true, алгоритм сопоставления шаблонов будет проверять совпадения без учёта регистра. Это позволяет исправить несовпадение регистра имён файлов в команде git sparse-checkout set, чтобы ожидаемый конус соответствовал рабочему каталогу.
Внутреннее устройство — подмодули
Если репозиторий содержит один или несколько подмодулей, их заполнение зависит от взаимодействия с командой git submodule. В частности, git submodule init -- <path> обеспечивает наличие подмодуля по пути <path>, а git submodule deinit [-f] -- <path> удаляет файлы подмодуля по пути <path> (включая неотслеживаемые файлы, незакоммиченные изменения и неопубликованную историю). Подобно тому как sparse-checkout удаляет файлы из рабочего дерева, но оставляет записи в индексе, деинициализированные подмодули удаляются из рабочего каталога, но их запись в индексе сохраняется.
Поскольку в подмодулях могут быть неопубликованные изменения или неотслеживаемые файлы, их удаление может привести к потере данных. Поэтому изменение правил включения/исключения в разреженной копии не приводит к удалению уже извлечённого подмодуля из рабочей копии. Иначе говоря, так же как checkout не удаляет и не инициализирует подмодули автоматически при переключении между ветками, в которых подмодули удаляются или добавляются, использование sparse-checkout для сокращения или расширения набора «интересующих» файлов также не приводит к автоматической деинициализации или инициализации подмодулей.
Кроме того, из сказанного выше следует, что отслеживаемые файлы могут отсутствовать в рабочей копии по нескольким причинам: применение шаблонов разреженности командой sparse-checkout и состояние инициализации подмодуля. Поэтому такие команды, как git grep, работающие с отслеживаемыми файлами в рабочей копии, могут выдавать результаты, ограниченные одним или обоими этими условиями.
См. также
sparse-checkout
© 2005–2026 Linus Torvalds and others
Licensed under the GNU General Public License version 2.
https://git-scm.com/docs/git-sparse-checkout