git submodules
Механизм включения одного Git-репозитория внутрь другого как вложенной зависимости с фиксацией конкретного коммита.
Зачем нужно
Submodule позволяет держать в проекте сторонний репозиторий (библиотеку, общие конфиги, шаблоны) с жёсткой привязкой к конкретному коммиту. Основной репозиторий отслеживает не файлы submodule, а лишь ссылку на точный коммит. Это даёт воспроизводимые сборки и возможность независимо обновлять зависимость.
Где используется
- Монорепозиторий: общие компоненты между несколькими проектами
- Включение сторонней библиотеки с фиксацией версии
- Отдельный репозиторий с конфигурациями/темами (Hugo themes, dotfiles)
- Большой проект разбит на субмодули для работы разных команд
Основной контент
Добавление submodule
# Добавить submodule
git submodule add https://github.com/org/shared-lib libs/shared
# Что произошло:
# 1. Создалась папка libs/shared/ с содержимым репозитория
# 2. Создан файл .gitmodules:
# [submodule "libs/shared"]
# path = libs/shared
# url = https://github.com/org/shared-lib
# 3. В индекс добавлена запись-ссылка на коммит submodule
git commit -m "chore: добавить shared-lib как submodule"
Клонирование репозитория с submodules
# При обычном clone submodule-папки будут пустыми
git clone https://github.com/org/main-repo.git
# Инициализировать и загрузить submodules
cd main-repo
git submodule init
git submodule update
# Или одной командой при clone
git clone --recurse-submodules https://github.com/org/main-repo.git
Обновление submodule
# Обновить конкретный submodule до последнего коммита remote
git submodule update --remote libs/shared
# Обновить все submodules
git submodule update --remote
# Зафиксировать новую версию submodule в основном репо
git add libs/shared
git commit -m "chore(deps): обновить shared-lib до HEAD"
Работа внутри submodule
# Submodule находится в состоянии detached HEAD
cd libs/shared
git checkout main # переключиться на ветку
git pull # получить обновления
# ... внести изменения, закоммитить ...
git push
# Вернуться в основной репозиторий
cd ../..
git add libs/shared
git commit -m "chore(deps): обновить shared-lib"
Удаление submodule
# Корректное удаление submodule
git submodule deinit libs/shared # очистить конфиг
git rm libs/shared # удалить из индекса и папку
# Удалить секцию из .gitmodules (git rm уже сделал это)
git commit -m "chore: удалить submodule shared-lib"
Просмотр submodules
# Список submodules и текущие коммиты
git submodule status
# Запустить команду в каждом submodule
git submodule foreach 'git pull origin main'
Частые ошибки
- Забыть
--recurse-submodulesпри clone — папки будут пустыми, проект не соберётся - Коммитить изменения только в submodule без обновления основного репо — другие разработчики будут смотреть на старую версию submodule
- Detached HEAD в submodule — после
git submodule updatesubmodule находится в detached HEAD; для работы с ним переключись на ветку - Submodules как замена пакетным менеджерам — для npm/pip/cargo зависимостей используй соответствующие менеджеры; submodule — для исходного кода