git subtree: альтернатива git submodule
Никола Паолуччи
Консультант по разработке
В Интернете полно статей о том, почему не стоит использовать подмодули Git. В отдельных ситуациях подмодули все же полезны, однако не лишены недостатков.
Есть ли альтернативы? Да! Как минимум два инструмента позволят вам отслеживать историю зависимостей ПО в проекте, по-прежнему работая с git:
Поддерево Git
- Репозиторий Google
В этой статье рассматривается команда git subtree
и объясняется, почему это средство хотя и не идеально, но тем не менее лучше git submodule.
Что такое команда git subtree и зачем ее использовать?
git subtree
позволяет вложить один репозиторий в другой в виде подкаталога. Это один из способов управления зависимостями в проектах Git.
git subtree
обладает следующими преимуществами.
- Легко управлять несложными рабочими процессами.
- Поддерживаются предыдущие версии Git (даже старше 1.5.2).
- Код подпроекта доступен сразу после клонирования суперпроекта.
- При использовании
git subtree
пользователям репозитория не нужно осваивать новые навыки. Управление зависимостями с помощьюgit subtree
никак не влияет на их работу. - Использование
git subtree
не приводит к добавлению новых файлов метаданных, в отличие от применения git submodule (файл .gitmodules). - Содержимое модуля может быть изменено без копирования зависимости в отдельный репозиторий.
Недостатки (которые мы в большинстве случаев считаем несущественными) перечислены ниже.
- Придется освоить новую стратегию слияния (команду
git subtree
). - Возвращать код подпроектов в вышестоящий проект немного сложнее.
- Нужно самостоятельно следить за тем, чтобы код суперпроекта и подпроектов в коммитах не смешивался.
Связанные материалы
Перемещение полного репозитория Git
СМ. РЕШЕНИЕ
Изучите Git с помощью Bitbucket Cloud
Использование git subtree
Команда git subtree
доступна в стандартной версии Git с мая 2012 года (т. е. начиная с версии 1.7.11). В версии, которую устанавливает утилита Homebrew в OS X, команда subtree уже настроена, но на некоторых платформах может понадобиться выполнить инструкции по установке.
Ниже приведен классический пример того, как можно отслеживать плагин vim с помощью git subtree
.
Быстрый, но неоптимальный способ без удаленного отслеживания
Если вас интересуют однострочные скрипты, которые можно просто скопировать и вставить, достаточно будет прочитать этот раздел. Сначала добавьте git subtree
в папку с указанным префиксом:
git subtree add --prefix .vim/bundle/tpope-vim-surround https://bitbucket.org/vim-plugins-mirror/vim-surround.git main --squash
(Обычно в главном репозитории не хранят полную историю подпроекта, но если вы захотите ее оставить, то просто не используйте флаг --squash.)
Вывод приведенной выше команды:
git fetch https://bitbucket.org/vim-plugins-mirror/vim-surround.git main
warning: no common commits
remote: Counting objects: 338, done.
remote: Compressing objects: 100% (145/145), done.
remote: Total 338 (delta 101), reused 323 (delta 89)
Receiving objects: 100% (338/338), 71.46 KiB, done.
Resolving deltas: 100% (101/101), done.
From https://bitbucket.org/vim-plugins-mirror/vim-surround.git
* branch main -} FETCH_HEAD
Added dir '.vim/bundle/tpope-vim-surround'
Как видите, в результате создан коммит слияния путем склеивания коммитов по всей истории репозитория vim-surround:
1bda0bd [3 minutes ago] (HEAD, stree) Merge commit 'ca1f4da9f0b93346bba9a430c889a95f75dc0a83' as '.vim/bundle/tpope-vim-surround' [Nicola Paolucci]
ca1f4da [3 minutes ago] Squashed '.vim/bundle/tpope-vim-surround/' content from commit 02199ea [Nicola Paolucci]
Если позднее вы захотите обновить код плагина содержимым из вышестоящего репозитория, можете просто осуществить pull в git subtree
:
git subtree pull --prefix .vim/bundle/tpope-vim-surround https://bitbucket.org/vim-plugins-mirror/vim-surround.git main --squash
В этом нет ничего сложного, кроме того, что команды довольно длинные, из-за чего их трудно запомнить. Укоротим их, добавив подпроект как удаленное подключение.
Добавление подпроекта в качестве удаленного подключения
Добавив поддерево subtree в виде удаленного подключения, мы сможем ссылаться на него в краткой форме:
git remote add -f tpope-vim-surround https://bitbucket.org/vim-plugins-mirror/vim-surround.git
Теперь, как и раньше, добавим subtree, только на этот раз ссылка на удаленный репозиторий будет краткой:
git subtree add --prefix .vim/bundle/tpope-vim-surround tpope-vim-surround main --squash
Команда для последующего обновления подпроекта будет выглядеть так:
git fetch tpope-vim-surround main
git subtree pull --prefix .vim/bundle/tpope-vim-surround tpope-vim-surround main --squash
Отправка кода в вышестоящую ветку
Теперь исправления можно беспрепятственно отправить в подпроект, находящийся в локальном рабочем каталоге. Когда придет время вернуть код в вышестоящий проект, нужно будет создать форк проекта и добавить его в качестве удаленного подключения:
git remote add durdn-vim-surround ssh://git@bitbucket.org/durdn/vim-surround.git
Теперь можно выполнить команду subtree push:
git subtree push --prefix=.vim/bundle/tpope-vim-surround/ durdn-vim-surround main
git push using: durdn-vim-surround main
Counting objects: 5, done.
Delta compression using up to 4 threads.
Compressing objects: 100% (3/3), done.
Writing objects: 100% (3/3), 308 bytes, done.
Total 3 (delta 2), reused 0 (delta 0)
To ssh://git@bitbucket.org/durdn/vim-surround.git
02199ea..dcacd4b dcacd4b21fe51c9b5824370b3b224c440b3470cb -} main
Все готово, и можно открывать запрос pull для специалиста, сопровождающего пакет.
Можно ли сделать то же самое без команды git subtree?
Конечно! git subtree
и слияние поддерева — разные стратегии. Слияние можно использовать, даже если по какой-то причине команда git subtree
недоступна. Порядок действий следующий.
Добавим зависимость как простое удаленное подключение Git
:
git remote add -f tpope-vim-surround https://bitbucket.org/vim-plugins-mirror/vim-surround.git
Прежде чем считать в репозиторий содержимое зависимости, важно записать слияние, чтобы получить возможность отслеживать полную историю дерева плагина вплоть до настоящего момента:
git merge -s ours --no-commit tpope-vim-surround/main
Вывод команды будет следующим:
Automatic merge went well; stopped before committing as requested
Считаем содержимое последнего дерева из репозитория плагина в рабочий каталог, готовый к коммиту:
git read-tree --prefix=.vim/bundle/tpope-vim-surround/ -u tpope-vim-surround/main
Теперь можно выполнить коммит (это будет коммит слияния, при котором сохранится история считанного дерева):
git ci -m"[subtree] adding tpope-vim-surround"
[stree 779b094] [subtree] adding tpope-vim-surround
Чтобы обновить проект, можно осуществить pull, используя стратегию слияния git subtree
:
git pull -s subtree tpope-vim-surround main
git subtree — отличная альтернатива
Поработав с git submodule, вы заметите, что многих проблем можно избежать, перейдя на git subtree
. Но конечно, как и с другими функциями Git, придется потратить время и силы на освоение этой возможности, чтобы использовать ее максимально эффективно.
Подпишитесь на меня в Twitter (@durdn), чтобы пополнять свои знания о Git. А если вы ищете хороший инструмент для управления репозиториями Git, советую попробовать Atlassian Bitbucket.
Обновление: опубликовав эту статью, я написал еще одну — о мощных возможностях git subtree.
Поделитесь этой статьей
Следующая тема
Рекомендуемые статьи
Добавьте эти ресурсы в закладки, чтобы изучить типы команд DevOps или получать регулярные обновления по DevOps в Atlassian.