- PVSM.RU - https://www.pvsm.ru -
Проект git-subrepo [1] существует достаточно давно, однако упоминаний о нем незаслуженно мало. Автором git-subrepo является Ingy döt Net [2].
Если посмотреть на историю комитов master-ветки проекта, то может показаться, что проект остановился в развитии 2 года назад. Однако работы над проектом ведутся и хочется надеяться, что скоро будет выпущена версия 0.4.0 [3].
Важным свойством данного средства является то, что на стороне пользователя нет необходимости устанавливать git-subrepo до тех пор, пока пользователь не решит делать комиты в upstream-репозитории подпроектов. Кроме того, пользователь получает полностью готовое и настроенное дерево исходного кода в момент копирования основного репозитория посредством стандартной команды git-clone(1).
Выбирая средства поддержки подмодулей/поддеревьев/подпроектов основного репозитория-контейнера, разработчик прежде всего определяет спектр возможностей, которое предоставляет тот или иной механизм и дает ответы на следующие вопросы:
Разумеется, данный перечень вопросов не может отразить всю полноту входных параметров, необходимых для правильного выбора, но для предварительного рассмотрения существующих средств, он вполне достаточен и, мы, говоря о проекте git-subrepo, призываем читателя рассматривать данный проект именно с этих позиций.
Пакет git-subrepo, на стороне разработчика, может быть установлен как локально, в своем домашнем каталоге, так и на системном уровне.
В первом случае, достаточно клонировать репозиторий git-subrepo в нужный каталог, например, ~/bin:
bash-4.4$ cd ~/bin
bash-4.4$ git clone https://github.com/ingydotnet/git-subrepo.git
и настроить переменные окружения
bash-4.4$ vim subrepo-env.sh
#!/bin/sh
export GIT_SUBREPO_ROOT="/home/username/bin/git-subrepo"
export PATH="/home/username/bin/git-subrepo/lib:$PATH"
export MANPATH="/home/username/bin/git-subrepo/man:$MANPATH"
:wq
bash-4.4$ source ./subrepo-env.sh
Если посмотреть переменные, определенные в Make-файле git-subrepo:
# Install variables:
PREFIX ?= /usr/local
INSTALL_LIB ?= $(DESTDIR)$(shell git --exec-path)
INSTALL_EXT ?= $(INSTALL_LIB)/$(NAME).d
INSTALL_MAN1 ?= $(DESTDIR)$(PREFIX)/share/man/man1
то легко выяснить, что на системном уровне git-subrepo устанавливается в каталог, где располагается Git:
bash-4.4$
bash-4.4$ git --exec-path
/usr/libexec/git-core
bash-4.4$
Таким образом команда для инсталляции git-subrepo может выглядеть, например, следующим образом:
bash-4.4$ make PREFIX=/usr install
Наличие переменной DESTDIR позволяет без дополнительных усилий (разумеется, если мы находимся не в cross-окружении) сделать пакет для любого дистрибутива Linux, что может быть полезно для DevOps инженеров.
Инсталлируем git-subrepo от имени суперпользователя:
bash-4.4$
bash-4.4$ cd git-subrepo/
bash-4.4$ make PREFIX=/usr install
install -C -d -m 0755 /usr/libexec/git-core/
install -C -m 0755 lib/git-subrepo /usr/libexec/git-core/
install -C -d -m 0755 /usr/libexec/git-core/git-subrepo.d/
install -C -m 0755 lib/git-subrepo.d/help-functions.bash lib/git-subrepo.d/bash+.bash /usr/libexec/git-core/git-subrepo.d/
install -C -d -m 0755 /usr/share/man/man1/
install -C -m 0644 man/man1/git-subrepo.1 /usr/share/man/man1/
bash-4.4$
Для анализа возможностей git-subrepo нам понадобится простое тестовое окружение, где мы сможем воспроизвести стандартные сценарии работы.
Создадим три каталога owner, remote, user, в которых разместим модели upstream- и локальных репозиториев разработчика и пользователя.
bash-4.4$ vim _init.sh
#!/bin/sh
CWD=`pwd`
mkdir remote owner user
cd remote
git init --bare build-system.git
git init --bare platform.git
cd ../owner
git clone $CWD/remote/build-system.git
git clone $CWD/remote/platform.git
cd build-system
echo -e "n[master] build-system 1.0.0n" >README
git add README
git commit -m "init build-system master 1.0.0"
git push
cd ../platform
echo -e "n[master] platform 1.0.0n" >README
git add README
git commit -m "init platform master 1.0.0"
git push
cd ../../user
git clone $CWD/remote/build-system.git
git clone $CWD/remote/platform.git
cd $CWD
:wq
bash-4.4$
bash-4.4$ ./_init.sh
bash-4.4$
Здесь,
| owner | — | рабочий каталог автора проектов ; |
| remote | — | каталог представляющий сервер автора проектов, на котором располагаются upstream-репозитории основного проекта platform.git и подпроекта build-system.git ; |
| user | — | рабочий каталог пользователя или участника команды разработчиков. |
Автор проекта и пользователи имеют собственные копии upstream-репозиториев на своих машинах, представленные в нашем примере в каталогах owner и user соответствено.
Задача автора состоит в том, чтобы включив подпроект builld-system в основное дерево platform обеспечить пользователям и участникам проекта следующие возможности:
Рассмотрим действия автора, которые он должен осуществить для реализации данных требований.
Для подключения нового поддерева следует воспользоваться командой git subrepo clone, которая по своему назначению похожа на команду git-clone(1). Обязательным параметром команды служит URL удаленного репозитория. Также можно указать каталог в котором будет располагаться подпроект и ветку удаленного репозитория. Мы будем работать с master-ветками, поэтому, в нашем примере, мы опускаем ненужные параметры комманд.
Итак, автор проекта, на своей рабочей машине, может подключить подпроект build-system с помощью команды git subrepo clone ../../remote/build-system.git/ build-system:
bash-4.4$
bash-4.4$ cd owner/platform/
bash-4.4$ git subrepo clone ../../remote/build-system.git/ build-system
Subrepo '../../remote/build-system.git' (master) cloned into 'build-system'.
bash-4.4$
Рассмотрим, какие изменения произошли в локальном репозитории platform:
bash-4.4$
bash-4.4$ git status
On branch master
Your branch is ahead of 'origin/master' by 1 commit.
(use "git push" to publish your local commits)
nothing to commit, working tree clean
bash-4.4$
bash-4.4$
bash-4.4$ git subrepo status
1 subrepo:
Git subrepo 'build-system':
Remote URL: ../../remote/build-system.git
Upstream Ref: b2f5079
Tracking Branch: master
Pulled Commit: b2f5079
Pull Parent: b5e76a7
bash-4.4$
История подпроекта build-system не поставляется в основное дерево, мы имеем лишь один squashed-комит, который сопровождается справочной информацией. Данная информация поступает под версионный контроль в файле ./build-system/.gitrepo/config:
[subrepo]
remote = ../../remote/build-system.git
branch = master
commit = b2f507918f2821cb7dd90c33223ed5cc3c9922a2
parent = b5e76a713f895565b06ee3ccfa29f19131ba06dd
method = merge
cmdver = 0.4.1
Информацию о подпроектах можно получать с помощью команды git subrepo config, например узнать ревизию upstream-проекта remote/build-system.git, которая только что пришла в основной репозиторий, можно в помощью команды:
bash-4.4$
bash-4.4$ git subrepo config build-system commit
Subrepo 'build-system' option 'commit' has value 'b2f507918f2821cb7dd90c33223ed5cc3c9922a2'.
bash-4.4$
Следует упомянуть о том, что оригинальный пакет git-subrepo сохраняет информацию о подпроектах не в файле .gitrepo/config, а в файле .gitrepo. Если вы предпочитаете хранить информацию в скрытом подкаталоге, то можете выбрать ветку git-subrepo-0.3.2 или git-subrepo-0.4.1 дочернего репозитория git-subrepo [4].
Итак, мы получили последнюю версию master-ветки upstream-репозитория remote/build-system.git и поместили ее в подкаталог build-system основного проекта platform.
Для поставки этих изменений в upstream-репозиторий remote/platform.git, автору необходимо выполнить команду git push:
bash-4.4$
bash-4.4$ git push
Enumerating objects: 7, done.
Counting objects: 100% (7/7), done.
Delta compression using up to 4 threads
Compressing objects: 100% (4/4), done.
Writing objects: 100% (6/6), 849 bytes | 849.00 KiB/s, done.
Total 6 (delta 0), reused 0 (delta 0)
To /home/prog/0.4.1/remote/platform.git
<font color="#8b0000">b5e76a7..6b831e4</font> master -> master
bash-4.4$
Более подробную информацию о командах git subrepo можно получить из файла ReadMe.pod [1] или в командной строке
bash-4.4$ git subrepo help <command>
например:
bash-4.4$ git subrepo help clone
Рассмотрим теперь все происходящее со стороны пользователя.
На данный момент, когда пользователь еще не получил обновления upstream-репозитория platform.git, его копия содержит один файл README
bash-4.4$
bash-4.4$ cd user/platform/
bash-4.4$ ls
README
bash-4.4$
содержащий одну строку:
bash-4.4$
bash-4.4$ cat README
[master] platform 1.0.0
bash-4.4$
После снятия изменений upstream-репозитория
bash-4.4$
bash-4.4$ git pull
remote: Enumerating objects: 7, done.
remote: Counting objects: 100% (7/7), done.
remote: Compressing objects: 100% (4/4), done.
remote: Total 6 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (6/6), done.
From /home/prog/0.4.1/remote/platform
b5e76a7..6b831e4 master -> origin/master
Updating <font color="#8b0000">b5e76a7..6b831e4</font>
Fast-forward
build-system/.gitrepo/config | 12 ++++++++++++
build-system/README | 3 +++
2 files changed, 15 insertions(+)
create mode 100644 build-system/.gitrepo/config
create mode 100644 build-system/README
bash-4.4$
пользователь будет иметь в своем распоряжении код подпроекта build-system именно той ревизии, которую определил автор проекта. Пользователь может в любой момент уточнить текущую ревизию с помощью команды config:
bash-4.4$
bash-4.4$ git subrepo config build-system/ commit
Subrepo 'build-system' option 'commit' has value 'b2f507918f2821cb7dd90c33223ed5cc3c9922a2'.
bash-4.4$
Примечательно то, что у пользователя нет необходимости осуществлять дополнительные настройки и он может положиться на то, что автор проекта поставил ему именно ту ревизию build-system, которая необходима для работы текущей версии platform.
Именно этого добивался автор проекта.
Допустим теперь, что наш пользователь является участником проекта и ему разрешено поставлять изменения не только в upstream-репозиторий remote/platform.git, но еще и в upstream-репозиторий подпроекта remote/build-system.git.
Тогда, если пользователь сделает изменения:
bash-4.4$
bash-4.4$ cd build-system/
bash-4.4$ vim README
bash-4.4$ cat README
[master] build-system 1.0.1
bash-4.4$
bash-4.4$ git commit -a -m "update BS version to 1.0.1"
[master d30b001] update BS version to 1.0.1
1 file changed, 1 insertion(+), 1 deletion(-)
bash-4.4$
bash-4.4$ cd ..
bash-4.4$ git log
commit d30b001286b08708f5c30c1f5346a90e4339f969 (HEAD -> master)
Author: user <___@_____>
Date: Tue Oct 30 10:49:32 2018 +0300
update BS version to 1.0.1
. . .
bash-4.4$
он сможет поставить их в upstream-репозитории следующим образом:
bash-4.4$
bash-4.4$ git subrepo push build-system/
Subrepo 'build-system' pushed to '../../remote/build-system.git' (master).
bash-4.4$
Поскольку файлы конфигурации подпроектов .gitrepo/config хранятся под версионным контролем, пользователю необходимо отослать изменения статуса подпроекта в upstream-репозиторий основного проекта remote/platform.git.
То есть пользователь не должен забывать о проверке статуса локального репозитория и вовремя выполнять команду git-push(1).
bash-4.4$
bash-4.4$ git status
On branch master
Your branch is ahead of 'origin/master' by 2 commits.
(use "git push" to publish your local commits)
nothing to commit, working tree clean
bash-4.4$
bash-4.4$ git push
Enumerating objects: 14, done.
Counting objects: 100% (14/14), done.
Delta compression using up to 4 threads
Compressing objects: 100% (7/7), done.
Writing objects: 100% (9/9), 992 bytes | 992.00 KiB/s, done.
Total 9 (delta 1), reused 0 (delta 0)
To /home/prog/0.4.1/remote/platform.git
d00be9f..deccb66 master -> master
bash-4.4$
В противном случае, при последующем снятии изменений upstream-репозитория, он получит merge-конфликт.
Разумеется, здесь нет ни чего необычного, однако, после выполнения команды git subrepo push ..., легко забыть о состоянии локальной копии основного репозитория.
Рассмотрим теперь, что произошло в upstream-репозитории remote/build-system.git
bash-4.4$
bash-4.4$ cd owner/build-system/
bash-4.4$
bash-4.4$ git pull
remote: Enumerating objects: 5, done.
remote: Counting objects: 100% (5/5), done.
remote: Total 3 (delta 0), reused 0 (delta 0)
Unpacking objects: 100% (3/3), done.
From /home/prog/0.4.1/remote/build-system
b2f5079..d229920 master -> origin/master
Updating b2f5079..d229920
Fast-forward
README | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
bash-4.4$
bash-4.4$ git log
commit d229920c7de34405bc7b8d47f36d420987687908 (HEAD -> master, origin/master)
Author: user <___@_____>
Date: Tue Oct 30 10:49:32 2018 +0300
update BS version to 1.0.1
commit b2f507918f2821cb7dd90c33223ed5cc3c9922a2
Author: user <___@_____>
Date: Tue Oct 30 10:05:30 2018 +0300
init build-system master 1.0.0
bash-4.4$
То есть автор проекта получил изменения, внесенные участником проекта.
Разумеется, автор может вносить изменения непосредственно в upstream-репозиторий проекта build-system:
bash-4.4$
bash-4.4$ cd owner/build-system/
bash-4.4$
bash-4.4$ vim README
bash-4.4$ cat README
[master] build-system 1.0.2
bash-4.4$ git commit -a -m "update build-system version to 1.0.2"
[master 8255f59] update build-system version to 1.0.2
1 file changed, 1 insertion(+), 1 deletion(-)
bash-4.4$ git push
Enumerating objects: 5, done.
Counting objects: 100% (5/5), done.
Writing objects: 100% (3/3), 281 bytes | 281.00 KiB/s, done.
Total 3 (delta 0), reused 0 (delta 0)
To /home/prog/0.4.1/remote/build-system.git
d229920..8255f59 master -> master
bash-4.4$
И все участники, а также пользователи основного проекта смогут получать эти изменения с помощью команды git subrepo pull
bash-4.4$
bash-4.4$ cd owner/platform/
bash-4.4$
bash-4.4$ git subrepo pull build-system/
Subrepo 'build-system' pulled from '../../remote/build-system.git' (master).
bash-4.4$ git status
On branch master
Your branch is ahead of 'origin/master' by 1 commit.
(use "git push" to publish your local commits)
nothing to commit, working tree clean
bash-4.4$ git push
Enumerating objects: 11, done.
Counting objects: 100% (11/11), done.
Delta compression using up to 4 threads
Compressing objects: 100% (4/4), done.
Writing objects: 100% (6/6), 670 bytes | 670.00 KiB/s, done.
Total 6 (delta 1), reused 0 (delta 0)
To /home/prog/0.4.1/remote/platform.git
6b831e4..b6f4a7b master -> master
bash-4.4$
Если у разработчика нет необходимости хранить истории подпроектов в основном репозитории и, при поставке кода он оперирует ветками, а не фиксированными тегами, то git-subrepo вполне подходит для организации повседневной работы.
Условно, к числу недостатков git-subrepo можно отнести то обстоятельство, что операция git subrepo clone возможна только по отношению к веткам подпроекта. Иными словами, пользователь не может подключить подпроект ссылаясь на его фиксированный тэг или определенную ревизию, то есть команды типа
bash-4.4$ git subrepo clone ../../remote/build-system.git build-system -t 1.0.1
bash-4.4$ git subrepo clone ../../remote/build-system.git build-system 7f5d1113eb0bc6
не допустимы.
Автор: rcl
Источник [9]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/git/297798
Ссылки в тексте:
[1] git-subrepo: https://github.com/ingydotnet/git-subrepo
[2] Ingy döt Net: http://resume.ingy.net/
[3] 0.4.0: https://github.com/ingydotnet/git-subrepo/tree/release/0.4.0
[4] дочернего репозитория git-subrepo: https://github.com/radix-platform/git-subrepo
[5] Git — Subtree Merging: https://git-scm.com/book/en/v1/Git-Tools-Subtree-Merging
[6] Mastering Git subtrees: https://medium.com/@porteneuve/mastering-git-subtrees-943d29a798ec
[7] Mastering Git submodules: https://medium.com/@porteneuve/mastering-git-submodules-34c65e940407
[8] Модель ветвления и управления модулями git для большого проекта: https://habr.com/company/relex/blog/258505/
[9] Источник: https://habr.com/post/428493/?utm_campaign=428493
Нажмите здесь для печати.