Git. Cheat Sheet
Submodules
Всё про подмодули написано в документации. Однако, на базовом уровне, когда не нужно знать всё, неизбежно придётся пользоваться следующими вещами:
- как подключить
- как свичнуться на новую версию подмодуля
- как откатить то, что ты случайно изменил в подмодуле
- как склонировать репозиторий с подмодулями
Также можно было бы рассмотреть работу с репозиторием подмодуля из подмодуля. Но я этим пока не пользуюсь, подмодуль у меня — это отдельный проект, где я всё правлю, а у consumers мне его править не приходится. Поэтому пока я эту тему опускаю.
Подключаем
git submodule add <git-repo-url> <folder/of/submodule>
git commit -am "add submodule"
Если мы хотим, чтобы в подмодуле был не мастер, а другая ветка, настраиваем ветку:
git config -f .gitmodules submodule.<folder/of/submodule>.branch <desired-branch>
git submodule update --remote
Первая команда настраивает ветку, вторая переключает папку подмодуля на неё. После этого нужно закоммититься.
Также может быть интересным настроить такой флаг:
git config status.submodulesummary 1
Клонируем
Если мы точно знаем, что собираемся пользоваться подмодулями, то клонируем так:
git clone --recurse-submodules <git-repo-url>
Однако мы можем склонировать только основной репозиторий, и работать с ним так, как будьто подмодулей в нём нет:
git clone <git-repo-url>
Так вы склонируете репо, там будет папка подмодуля, но она будет пустая. И вообще, репозиторий будет работать так, будто подмодуля нет. Но их можно подключить позднее:
git submodule update --init
Эта команда настроит репо на работу с подмодулями и склонирует его репозиторий в папку подмодуля. С флагом --recursive настроятся и подмодули подмодуля.
Обновляем подмодуль
Предположим, кто-то накоммитил в репозиторий подмодуля и мы хотим применить эти изменения в нашем репозитории, тогда мы делаем так:
git submodule update --remote --merge
git commit -am "upgrade the submodule"
Стягиваем репо, в котором обновился подмодуль
Предположим, ваш коллега обновил версию подмодуля в вашем репозитории. Вам нужно, чтобы обновились оба репозитория: и основной, и подмодуль. Теоретически, должна сработать такая команда (since Git 2.14):
git pull --recurse-submodules
Более олдскульный способ:
git pull
git submodule update --init --recursive
Флаг --init добавляется на тот случай, если в репозитории появились новые подмодули, которые у вас ещё не были добавлены.
В случае, если существующие подмодули поменяли урлы, придётся сделать так:
git submodule sync --recursive
git submodule update --init --recursive
Откатываем изменения в подмодуле
В документации описано, как изменять код подмодуля прямо в том месте, где он подключён в наш репозиторий.
Но предположим, мы этого не хотим, но случайно что-то в нём поменяли,
например обновился package-lock.json. В этой ситуации git diff нам покажет «dirty» обновление:
@@ -1 +1 @@
-Subproject commit 296b088d2821058a2e305de143b7824508430eb2
+Subproject commit 296b088d2821058a2e305de143b7824508430eb2-dirty
которое мы хотим откатить:
cd <folder/of/submodule>
git checkout -- .
То же самое можно сделать сразу для всех подмодулей:
git submodule foreach "git checkout -- ."
Кроме того, можно добавить поле ignore в настройки подмодуля:
git config -f .gitmodules submodule.<folder/of/submodule>.ignore dirty
Тогда ваш репо будет инорить изменения в подмодуле. Только я пока не решил, лучше иметь эту настройку или не иметь.