Git submodule: добавить, клонировать и обновить подмодули

Категория: Git · Язык: Bash · Обновлено:

Подмодуль в Git это ссылка на конкретный коммит другого репозитория внутри вашего. Добавить его можно командой git submodule add адрес путь, а клонировать проект вместе с подмодулями командой git clone --recurse-submodules.

Добавить подмодуль

Bash
git submodule add https://github.com/user/library.git libs/library
git commit -m "Добавить подмодуль libs/library"

Git скачает репозиторий в libs/library, создаст файл .gitmodules и запишет в индекс не файлы подмодуля, а ссылку на его коммит. В .gitmodules попадёт такая запись:

Текст
[submodule "libs/library"]
	path = libs/library
	url = https://github.com/user/library.git

Клонировать проект с подмодулями

Bash
git clone --recurse-submodules https://github.com/user/project.git

Если репозиторий уже склонирован без этого флага, папки подмодулей будут пустыми. Заполните их:

Bash
git submodule update --init --recursive

Обновить подмодуль

Есть два разных действия. Первое подтягивает ту версию, которую записал автор проекта:

Bash
git pull --recurse-submodules       # забрать изменения проекта и обновить подмодули
git submodule update --recursive    # выставить подмодули на записанные коммиты

Второе переводит подмодуль на последний коммит его собственной ветки:

Bash
git submodule update --remote libs/library
git add libs/library                # зафиксировать новый коммит подмодуля в проекте
git commit -m "Обновить libs/library"

Посмотреть состояние

Bash
git submodule status                # первый символ: - не загружен, + коммит отличается, пробел всё совпадает
git config submodule.recurse true   # включить обработку подмодулей для pull, checkout и других команд

Удалить подмодуль

В Git нет одной команды для удаления, нужны четыре шага:

Bash
git submodule deinit -f libs/library
git rm -f libs/library
rm -rf .git/modules/libs/library
git commit -m "Удалить подмодуль libs/library"

Частые вопросы

Почему подмодуль «detached HEAD»?

Подмодуль привязан к конкретному коммиту, а не к ветке. Чтобы внести в него правки, перейдите в папку подмодуля и выполните git switch main, затем коммитьте как в обычном репозитории.

Почему коллеги не видят мои изменения в подмодуле?

Нужно отправить два репозитория: сначала сам подмодуль (git push внутри его папки), потом основной проект с новой ссылкой на коммит.