Перейти к содержимому

Git-подмодуль

Что такое подмодуль

Очень часто кодовый репозиторий зависит от внешнего кода из других репозиториев. Вы можете напрямую скопировать и вставить внешний код в основной репозиторий или использовать систему управления пакетами языка. Однако у обоих способов есть недостаток: они не отслеживают изменения во внешнем репозитории. Git позволяет включать в один репозиторий другие Git-репозитории, называемые подмодулями. Подмодули позволяют отслеживать изменения в нескольких репозиториях из одного родительского репозитория. Подмодули — это репозитории, включённые в родительский репозиторий по определённому пути в рабочем каталоге. Они могут располагаться в любой части рабочего каталога и настраиваются через файл .gitmodules, который находится в корне родительского репозитория. Файл .gitmodules содержит метаданные о сопоставлении между URL проекта подмодуля и локальным каталогом. Подмодули поддерживают добавление, синхронизацию, обновление и клонирование. Подмодули отслеживают только конкретные коммиты, а не ссылки Git или ветки.

Когда использовать подмодули

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

  • Если подпроект меняется слишком быстро или предстоящие изменения могут сломать API, зафиксируйте код на конкретном коммите ради безопасности.
  • Если компонент обновляется не очень часто и вы хотите отслеживать его как зависимость от поставщика.
  • Если вы представляете часть проекта третьей стороне и хотите интегрировать их работу в определённый момент (это работает только тогда, когда обновления происходят не слишком часто).
  • Если технологический контекст позволяет упаковку и формальное управление зависимостями, следует использовать менеджеры пакетов вместо подмодулей.
  • Если ваша кодовая база огромна и вы не хотите загружать её каждый раз, используйте подмодули, чтобы не позволять участникам проекта скачивать всю кодовую базу.

Команды для Git-подмодулей

Чтобы создать новый подмодуль в существующем репозитории, используйте git submodule add.

создать новый подмодуль в существующем репозитории git

bash
mkdir git-submodule-demo
cd git-submodule-demo/
git init
Initialized empty Git repository in /Users/example/git-submodule-demo/.git/

Чтобы добавить подмодуль в новый репозиторий, выполните следующее:

добавить подмодуль в новый репозиторий git

bash
git submodule add https://somehost/example/textexample
Cloning into '/Users/example/git-submodule-demo/textexample'...
remote: Counting objects: 8, done.
remote: Compressing objects: 100% (6/6), done.
remote: Total 8 (delta 1), reused 0 (delta 0)
Unpacking objects: 100% (8/8), done.

Команда git submodule add принимает URL, указывающий на Git-репозиторий. Git немедленно клонирует подмодуль textexample. Проверьте состояние репозитория, выполнив команду git status:

проверить состояние репозитория git status

bash
git status
On branch master

No commits yet

Changes to be committed:
  (use "git rm --cached <file>..." to unstage)

 new file: .gitmodules
 new file: textexample

Вы можете зафиксировать файлы в репозитории с помощью команд git add и git commit:

зафиксировать файлы git

bash
git add .gitmodules textexample/
git commit -m "added submodule"
[master (root-commit) d5002d0] added submodule
 2 files changed, 4 insertions(+)
 create mode 100644 .gitmodules
 create mode 160000 textexample

Обновление подмодулей

Участники команды должны обновлять код подмодуля, если он был изменён где-то ещё. Вы не можете использовать git pull, потому что он обновляет только ссылку родительского репозитория на коммит подмодуля, а не сам код подмодуля. Чтобы обновить подмодуль до записанного коммита, выполните:

обновление кода подмодуля git

bash
git submodule update

Примечание: без флага --remote эта команда только переключает на коммит, записанный в родительском репозитории, и не загружает новые изменения из upstream.

Если файл .gitmodules был обновлён (например, если изменился URL подмодуля), выполните git submodule sync, чтобы обновить локальный .git/config новыми URL перед запуском git submodule update.

Клонирование Git-подмодулей

Чтобы клонировать проект с подмодулями, используйте команду git clone. По умолчанию она клонирует родительский репозиторий, но оставляет каталоги подмодулей пустыми. Затем необходимо выполнить git submodule init и git submodule update. Первая команда обновляет локальный .git/config сопоставлениями из .gitmodules, а вторая загружает данные подмодуля и переключает на записанный коммит.

В качестве альтернативы можно использовать флаг --recursive с git clone, чтобы автоматически инициализировать и обновлять подмодули. Если вы клонировали без --recursive, выполните следующее:

команда git clone инициализирует и обновляет подмодули

bash
git clone /url/to/repo/with/submodules
git submodule init
git submodule update

Получение кода подмодуля

Когда вы получаете репозиторий, содержащий новые подмодули, другим участникам команды нужно их инициализировать. Сначала выполните git pull, чтобы получить последнее состояние родительского репозитория. Если перечислены новые подмодули, инициализируйте их с помощью:

инициализировать новые подмодули git

bash
git submodule init

Обратите внимание, что init обновляет только локальный файл .git/config. Чтобы фактически загрузить код и переключиться на записанный коммит, необходимо выполнить git submodule update.

Отправка обновлений в подмодуле

Поскольку подмодуль — это отдельный репозиторий, вы можете отправлять изменения в него так же, как в любой обычный Git-репозиторий, выполняя команды внутри каталога подмодуля. Если вы создадите новые коммиты внутри подмодуля, родительский репозиторий всё равно будет указывать на старый коммит. Чтобы обновить родительский репозиторий до нового коммита, выполните git add для каталога подмодуля, затем зафиксируйте изменения и отправьте их. Когда вы запускаете git status в основном репозитории, подмодуль будет отображаться как «Changes not staged for commit» с сообщением «modified content (new commits)». Это означает, что код подмодуля переключён на другой коммит, чем ожидает родительский репозиторий.

Подмодули — хороший способ хранить проекты в отдельных репозиториях, при этом всё ещё ссылаясь на них как на папки в рабочем каталоге другого репозитория. Однако помните, что для многих проектов подмодули — не лучший подход, и работать с ними бывает непросто.

Практика

Каковы ключевые аспекты использования Git-подмодулей?

Считаете ли это полезным?

Предпросмотр dual-run — сравните с маршрутами Symfony на продакшене.