Как добавить подмодуль в подкаталог?

310

У меня есть git-репо ~/.janus/с кучей подмодулей в нем. Я хочу добавить субмодуль ~/.janus/snipmate-snippets/snippets/, но при запуске git submodule add <git@github.com:...>в snipmate-snippetsкаталоге я получаю следующее сообщение об ошибке:

You need to run this command from the toplevel of the working tree.

Итак, вопрос: как мне добавить подмодуль в snipmate-snippetsкаталог?

Роберт Ауди
источник
Переход к корневому каталогу git-репо для команд подмодуля больше не будет требоваться (скоро). Смотрите мой ответ ниже
VonC
3
git submodule add -b <branch> <url> <relative_path_4m_root>
parasrish

Ответы:

439

Вы входите ~/.janusи бежите:

git submodule add <git@github ...> snipmate-snippets/snippets/

Если вам нужна дополнительная информация о подмодулях (или git в целом), ProGit довольно полезен.

BergmannF
источник
кажется хорошей идеей добавить ветку при добавлении, иначе HEAD легко отсоединяется: git submodule add -b <branch> <repository> [<submodule-path>]
deann
1
Для меня это было причиной 'subprojects' already exists in the index (я использовал подпроекты в качестве имени каталога) . Вместо этого, что помогло, ответ VonC ниже, то есть делать cd subprojects, а затем git submodule add <get@github …>без пути.
Привет, Ангел,
83

Обратите внимание, что начиная с git1.8.4 (июль 2013 г.), вам больше не нужно возвращаться в корневой каталог.

 cd ~/.janus/snipmate-snippets
 git submodule add <git@github ...> snippets

( Bouke Versteegh комментирует, что вы не должны использовать /., как в snippets/.: snippetsдостаточно)

Смотрите коммит 091a6eb0feed820a43663ca63dc2bc0bb247bbae :

субмодуль: отбросить требование верхнего уровня

Используйте новую rev-parse --prefixопцию, чтобы обработать все пути, указанные для команды submodule, отбросив требование, что она запускается из верхнего уровня хранилища.

Поскольку интерпретация относительного URL-адреса субмодуля зависит от того, remote.origin.urlнастроен ли "" или нет , явно блокируйте относительные URL-адреса в " git submodule add", если они не находятся на верхнем уровне рабочего дерева.

Подписано: Джон Кепинг

Зависит от коммита 12b9d32790b40bf3ea49134095619700191abf1f

Это заставляет ' git rev-parse' вести себя так, как если бы он был вызван из указанного подкаталога репозитория, с той разницей, что любые пути к файлам, которые он печатает, имеют префикс полного пути из вершины рабочего дерева .

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

VonC
источник
Большое спасибо! Я заметил, что трейлинг /.не нужен, git создаст фрагменты каталогов без него.
Бук Верстех
@BoukeVersteegh Интересно. Я включил ваш комментарий в ответ для большей наглядности.
VonC
Я на GIT версии 2.7.4, но все равно я получаю это сообщение об ошибке Relative path can only be used from the toplevel of the working tree. Я делаюgit submodule add ../../../functest
FlyingAura
@ user3426358 да, это ожидаемо: ответ выше о возможности создания подмодуля git из любой подпапки основного репо, а не только из его корневой папки. Речь не идет о ссылке на субмодуль удаленного репо с относительным путем. Если вы это сделаете, вы получите сообщение об ошибке, которое вы видите.
VonC
@ user3426358 И, кстати, это сообщение об ошибке (которое вы видите: " Relative path can only be used from the toplevel of the working tree") не является тем из исходного вопроса (" You need to run this command from the toplevel of the working tree")
VonC
17

У меня была похожая проблема, но я загнал себя в угол с помощью инструментов GUI.

У меня был подпроект с несколькими файлами в нем, который я до сих пор просто копировал вместо того, чтобы регистрироваться в их собственном git-репо. Я создал репо в подпапке, был в состоянии совершить, подтолкнуть и т. Д. Просто отлично. Но в родительском репо подпапка не рассматривалась как подмодуль, а ее файлы все еще отслеживались родительским репо - ничего хорошего.

Чтобы выйти из этого беспорядка, я должен был сказать Git прекратить отслеживать подпапку (без удаления файлов):

proj> git rm -r --cached ./ui/jslib

Затем я должен был сказать, что там был субмодуль (что вы не можете сделать, если что-то там отслеживается git):

proj> git submodule add ./ui/jslib

Обновить

Идеальный способ справиться с этим - еще пара шагов. В идеале, существующее хранилище перемещается в собственный каталог, без каких-либо родительских модулей git, фиксируется и отправляется, а затем добавляется в виде подмодуля, например:

proj> git submodule add git@bitbucket.org:user/jslib.git ui/jslib

Это приведет к клонированию репозитория git в качестве подмодуля - который включает в себя стандартные шаги клонирования, а также несколько других более непонятных шагов конфигурации, которые git предпринимает от вашего имени, чтобы заставить этот подмодуль работать. Самое важное отличие состоит в том, что он помещает туда простой файл .git, а не каталог .git, который содержит ссылку на путь, по которому живет настоящий git dir - обычно в корневом каталоге родительского проекта .git / modules / jslib.

Если вы не сделаете так, они будут работать нормально для вас, но как только вы сделаете коммит и нажмете родителя, а другой разработчик потянет этого родителя, вы просто усложнили им жизнь. Им будет очень трудно воспроизвести структуру, имеющуюся на вашем компьютере, если у вас есть полный каталог .git в подпапке каталога, который содержит собственный каталог .git.

Итак, переместить, нажать, добавить подмодуль git, это самый чистый вариант.

Крис Москини
источник
16

Для тех из вас, кто разделяет мою странную любовь к ручному редактированию файлов конфигурации, добавление (или изменение) следующего также поможет.

.git / config (личный конфиг)

[submodule "cookbooks/apt"]
    url = https://github.com/opscode-cookbooks/apt

.gitmodules (совершенная общая конфигурация)

[submodule "cookbooks/apt"]
    path = cookbooks/apt
    url = https://github.com/opscode-cookbooks/apt

Смотрите также это - разница между .gitmodules и указанием подмодулей в .git / config?

yoniLavi
источник
2

однострочный сценарий bash, чтобы помочь Крису ответить выше, так как я нарисовал себя в углу, используя обновления Vundle для моих сценариев .vim. DESTпуть к каталогу, содержащему ваши подмодули. Сделайте это после выполненияgit rm -r $DEST

DEST='path'; for file in `ls ${DEST}`; do git submodule add `grep url ${DEST}/${file}/.git/config|awk -F= '{print $2}'` ${DEST}/${file}; done

ура

Рик Р
источник