gitsubmodules
Название
gitsubmodules — встраивание одного репозитория в другой
Краткое описание
.gitmodules, $GIT_DIR/config
git submodule git <command> --recurse-submodules
Описание
Подмодуль — это репозиторий, встроенный в другой репозиторий. У подмодуля есть собственная история; репозиторий, в который он встроен, называется суперпроектом.
В файловой системе подмодуль обычно (но не всегда — см. раздел ФОРМЫ ниже) состоит из (i) каталога Git, расположенного в каталоге $GIT_DIR/modules/ суперпроекта, (ii) рабочего каталога внутри рабочего каталога суперпроекта и файла .git в корне рабочего каталога подмодуля, указывающего на (i).
Предположим, что каталог Git подмодуля находится в $GIT_DIR/modules/foo/, а рабочий каталог — в path/to/bar/. Суперпроект отслеживает подмодуль с помощью записи gitlink в дереве по адресу path/to/bar и записи в файле .gitmodules (см. gitmodules[5]) вида submodule.foo.path = path/to/bar.
Запись gitlink содержит имя объекта коммита, на который должна указывать рабочая директория подмодуля согласно суперпроекту.
Раздел submodule.foo.* в файле .gitmodules содержит дополнительные указания для пользовательского уровня Git. Например, параметр submodule.foo.url задаёт, откуда получать подмодуль.
Подмодули можно использовать как минимум в двух случаях:
-
Использование другого проекта с сохранением независимой истории. Подмодули позволяют включить рабочее дерево другого проекта в собственное рабочее дерево, сохраняя при этом истории обоих проектов отдельно. Кроме того, поскольку подмодули привязаны к произвольной версии, другой проект можно разрабатывать независимо, не затрагивая суперпроект. Это позволяет обновлять суперпроект до новых версий только тогда, когда это необходимо.
-
Разделение (логически единого) проекта на несколько репозиториев и их последующее объединение. Это можно использовать, чтобы преодолеть текущие ограничения реализации Git и обеспечить более детализированный доступ:
-
Размер репозитория Git: в текущем виде Git плохо масштабируется для больших репозиториев, содержащих данные, которые не сжимаются посредством дельта-вычислений между деревьями. Например, можно хранить большие двоичные ресурсы в подмодулях и клонировать эти репозитории без истории или с сокращённой историей, чтобы локально не хранить большой объём истории.
-
Объём передаваемых данных: в текущем виде Git требует наличия всего рабочего дерева. Он не позволяет передавать частичные деревья при получении данных или клонировании. Если проект, над которым вы работаете, состоит из нескольких репозиториев, связанных в суперпроекте как подмодули, можно не получать рабочие деревья репозиториев, которые вас не интересуют.
-
Контроль доступа: ограничивая доступ пользователей к подмодулям, можно реализовать политики чтения и записи для разных пользователей.
-
Настройка подмодулей
Операции с подмодулями можно настраивать с помощью следующих механизмов (от высшего приоритета к низшему):
-
Командная строка для команд, поддерживающих указание подмодулей в качестве частей pathspec. Большинство команд имеют булев флаг
--recurse-submodules, который указывает, следует ли рекурсивно обходить подмодули. Например,grepиcheckout. Некоторые команды принимают перечислимые значения, напримерfetchиpush, позволяющие указать, как именно затрагиваются подмодули. -
Конфигурация внутри подмодуля. Она включает в себя
$GIT_DIR/configв подмодуле, а также настройки в дереве, например файлы.gitattributesили.gitignore, задающие поведение команд внутри подмодуля.Например, действие настройки из файла
.gitignoreподмодуля будет заметно при выполнении командыgitstatus--ignore-submodules=noneв суперпроекте. Она собирает сведения из рабочего каталога подмодуля, выполняя в нёмstatusи учитывая файл.gitignoreподмодуля.Файл
$GIT_DIR/configподмодуля будет учитываться при выполнении командыgitpush--recurse-submodules=checkв суперпроекте, поскольку она проверяет, есть ли в подмодуле изменения, не опубликованные ни в одном удалённом репозитории. Удалённые репозитории настраиваются в подмодуле обычным образом в файле$GIT_DIR/config. -
Файл конфигурации
$GIT_DIR/configв суперпроекте. Git рекурсивно обходит только активные подмодули (см. раздел «АКТИВНЫЕ ПОДМОДУЛИ» ниже).Если подмодуль ещё не инициализирован, то конфигурации внутри него пока нет, поэтому, например, именно здесь указывается, откуда получать подмодуль.
-
Файл
.gitmodulesвнутри суперпроекта. Обычно проект использует этот файл, чтобы предложить значения по умолчанию для набора вышестоящих репозиториев и указать соответствие между именем подмодуля и его путём.Этот файл главным образом служит для сопоставления имён и путей подмодулей в суперпроекте, чтобы можно было найти каталог Git подмодуля.
Если подмодуль ещё ни разу не инициализировался, конфигурация подмодуля находится только здесь. Этот файл служит последним резервным источником сведений о том, откуда получать подмодуль.
Формы
Подмодули могут иметь следующие формы:
-
Базовая форма, описанная в разделе «ОПИСАНИЕ»: каталог Git, рабочий каталог, файл
gitlinkи запись.gitmodules. -
Подмодуль «старого формата»: рабочий каталог со встроенным каталогом
.git, а также отслеживающие записиgitlinkи.gitmodulesв суперпроекте. Обычно такие подмодули встречаются в репозиториях, созданных с помощью старых версий Git.Такие репозитории старого формата можно создать вручную.
При деинициализации или удалении (см. ниже) каталог Git подмодуля автоматически перемещается в
$GIT_DIR/modules/<name>/суперпроекта. -
Деинициализированный подмодуль: запись
gitlinkи запись.gitmodules, но без рабочего каталога подмодуля. Каталог Git подмодуля может оставаться на месте, поскольку после деинициализации он сохраняется. Каталог, предназначенный для рабочего каталога, остаётся пустым.Деинициализировать подмодуль можно командой
gitsubmoduledeinit. Помимо очистки рабочего каталога, эта команда изменяет только файл$GIT_DIR/configсуперпроекта, поэтому история суперпроекта не затрагивается. Отменить это действие можно командойgitsubmoduleinit. -
Удалённый подмодуль: подмодуль можно удалить, выполнив команду git rm <submodule-path> && git commit. Отменить это действие можно командой
gitrevert.При удалении удаляются данные суперпроекта для отслеживания подмодуля: запись
gitlinkи раздел в файле.gitmodules. Рабочий каталог подмодуля удаляется из файловой системы, но каталог Git сохраняется, чтобы можно было переключаться на предыдущие коммиты без необходимости получать данные из другого репозитория.Чтобы полностью удалить подмодуль, вручную удалите
$GIT_DIR/modules/<name>/.
Активные подмодули
Подмодуль считается активным,
-
если для
submodule.<name>.activeзадано значениеtrueили
-
если путь подмодуля соответствует pathspec в
submodule.activeили
-
если задано значение
submodule.<name>.url.
Эти условия проверяются в указанном порядке.
Например:
[submodule "foo"] active = false url = https://example.org/foo [submodule "bar"] active = true url = https://example.org/bar [submodule "baz"] url = https://example.org/baz
В приведённой выше конфигурации активны только подмодули bar и baz: bar — в соответствии с условием (1), а baz — в соответствии с условием (3). foo неактивен, поскольку условие (1) имеет приоритет над условием (3).
Обратите внимание, что условие (3) — исторический артефакт, и оно игнорируется, если в условиях (1) и (2) указано, что подмодуль неактивен. Иными словами, если для submodule.<name>.active задано значение false или путь подмодуля исключён из pathspec в submodule.active, наличие или отсутствие url не имеет значения. Это показано в следующем примере.
[submodule "foo"] active = true url = https://example.org/foo [submodule "bar"] url = https://example.org/bar [submodule "baz"] url = https://example.org/baz [submodule "bob"] ignore = true [submodule] active = b* active = :(exclude) baz
В этом примере активны все подмодули, кроме baz (foo, bar, bob). foo активен благодаря собственному флагу активности, а все остальные — благодаря pathspec активных подмодулей, который указывает, что активны также все подмодули, начинающиеся с b, кроме baz, независимо от наличия поля .url.
Рабочий процесс для сторонней библиотеки
# Add a submodule git submodule add <URL> <path>
# Occasionally update the submodule to a new version: git -C <path> checkout <new-version> git add <path> git commit -m "update submodule to new version"
# See the list of submodules in a superproject git submodule status
# See FORMS on removing submodules
Рабочий процесс для искусственно разделённого репозитория
# Enable recursion for relevant commands, such that # regular commands recurse into submodules by default git config --global submodule.recurse true
# Unlike most other commands below, clone still needs # its own recurse flag: git clone --recurse <URL> <directory> cd <directory>
# Get to know the code: git grep foo git ls-files --recurse-submodules
| Примечание | Для git ls-files также требуется собственный флаг --recurse-submodules. |
# Get new code git fetch git pull --rebase
# Change worktree git checkout git reset
Подробности реализации
При клонировании или получении данных из репозитория, содержащего подмодули, по умолчанию подмодули не извлекаются в рабочее дерево; можно указать clone рекурсивно обходить подмодули. Подкоманды init и update команды git submodule позволяют поддерживать подмодули извлечёнными в рабочем дереве и переключать их на соответствующие версии. Кроме того, можно задать параметр submodule.recurse, чтобы checkout рекурсивно обходила подмодули (обратите внимание: submodule.recurse влияет и на другие команды Git; полный список см. в git-config[1]).
См. также
gitsubmodules
© 2005–2026 Linus Torvalds and others
Licensed under the GNU General Public License version 2.
https://git-scm.com/docs/gitsubmodules