Как переместить существующий подмодуль Git в репозиторий Git?
Я хотел бы изменить имя каталога подмодуля Git в моем суперпроекте Git.
Предположим, что у меня есть следующая запись в файле .gitmodules
:
[submodule ".emacs.d/vimpulse"]
path = .emacs.d/vimpulse
url = git://gitorious.org/vimpulse/vimpulse.git
Что мне нужно напечатать, чтобы переместить каталог .emacs.d/vimpulse
в .emacs.d/vendor/vimpulse
, не удалив его сначала (пояснил здесь и здесь), а затем повторно добавьте его.
Действительно ли Git нужен весь путь в теге подмодуля
[submodule ".emacs.d/vimpulse"]
или можно также сохранить только имя подпроекта?
[submodule "vimpulse"]
Ответы
Ответ 1
Примечание. Как упоминается в комментариях, этот ответ относится к шагам, которые необходимы для более старых версий git. Git теперь имеет встроенную поддержку движущихся подмодулей:
Так как Git 1.8.5, git mv old/submod new/submod
работает так, как ожидалось, и делает всю сантехнику для вас. Возможно, вы захотите использовать Git 1.9.3 или новее, потому что он содержит исправления для перемещения подмодулей.
Схожая с тем, как вы удаляете подмодуль (см. Как удалить подмодуль?):
- Измените
.gitmodules
и соответствующим образом измените путь подмодуля и поместите его в индекс с помощью git add .gitmodules
.
- При необходимости создайте родительский каталог нового местоположения подмодуля (
mkdir -p new/parent
).
- Переместить весь контент из старого в новый каталог (
mv -vi old/parent/submodule new/parent/submodule
).
- Убедитесь, что Git отслеживает этот каталог (
git add new/parent
).
- Удалите старый каталог с
git rm --cached old/parent/submodule
.
- Переместите каталог
.git/modules/old/parent/submodule
со всем содержимым до .git/modules/new/parent/submodule
.
- Отредактируйте файл
.git/modules/new/parent/config
, убедитесь, что элемент worktree указывает на новые местоположения, поэтому в этом примере это должно быть worktree = ../../../../../new/parent/module
. Как правило, должно быть еще два ..
, а затем каталоги в прямом пути в этом месте.
-
Отредактируйте файл new/parent/module/.git
, убедитесь, что путь в нем указывает на правильное новое местоположение внутри основной папки проекта .git
, поэтому в этом примере gitdir: ../../../.git/modules/new/parent/submodule
.
Результат git status
выглядит следующим образом:
# On branch master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: .gitmodules
# renamed: old/parent/submodule -> new/parent/submodule
#
-
Наконец, зафиксируйте изменения.
Ответ 2
Самый современный ответ, взятый из комментария Valloric выше:
- Обновление до Git 1.9.3 (или 2.18, если подмодуль содержит вложенные подмодули)
-
git mv old/submod new/submod
- После этого .gitmodules и каталог submodule уже подготовлены для фиксации (вы можете проверить это с помощью
git status
.) - Зафиксируйте изменения с помощью
git commit
и вы готовы!
Готово!
Ответ 3
В моем случае я хотел переместить подмодуль из одного каталога в подкаталог, например. "AFNetworking" → "ext/AFNetworking" . Это следующие шаги:
- Изменить .gitmodules, изменяя имя и путь подмодуля, чтобы быть "ext/AFNetworking"
- Переместить подмодуль git из каталога .git/modules/AFNetworking "в".git/modules/ext/AFNetworking "
- Переместить библиотеку из "AFNetworking" в "ext/AFNetworking"
- Изменить ".git/modules/ext/AFNetworking/config" и исправить строку
[core] worktree
. Шахта изменилась с ../../../AFNetworking
на ../../../../ext/AFNetworking
- Изменить "ext/AFNetworking/.git" и исправить
gitdir
. Шахта изменилась с ../.git/modules/AFNetworking
на ../../git/modules/ext/AFNetworking
-
git add .gitmodules
-
git rm --cached AFNetworking
-
git submodule add -f <url> ext/AFNetworking
Наконец, я видел в статусе git:
matt$ git status
# On branch ios-master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: .gitmodules
# renamed: AFNetworking -> ext/AFNetworking
Et voila. Приведенный выше пример не меняет глубины каталога, что существенно влияет на сложность задачи и не изменяет имя подмодуля (что может и не быть действительно необходимым, но я сделал это, чтобы оно соответствовало тому, что произойдет, если я добавлю новый модуль на этом пути.)
Ответ 4
[Обновить: 2014-11-26]. Как Yar подытоживает ниже, , прежде чем что-либо сделать, убедитесь, что вы знаете URL-адрес подмодуль. Если неизвестно, откройте .git/.gitmodules
и просмотрите ключ submodule.<name>.url
.
Для меня работала удалить старый подмодуль с помощью git submodule deinit <submodule>
, а затем git rm <submodule-folder>
. Затем добавьте подмодуль снова с новым именем папки и фиксацией. Проверка состояния git перед фиксацией показывает, что старый подмодуль переименован в новое имя и модифицирован .gitmodule.
$ git submodule deinit foo
$ git rm foo
$ git submodule add https://bar.com/foo.git new-foo
$ git status
renamed: foo -> new-foo
modified: .gitmodules
$ git commit -am "rename foo submodule to new-foo"
Ответ 5
Кажется, что трюк понимает, что каталог .git
для подмодулей теперь хранится в основном репозитории под .git/modules
, и каждый подмодуль имеет файл .git
, который указывает на него. Это процедура, которая вам нужна сейчас:
- Переместите подмодуль в новый дом.
- Отредактируйте файл
.git
в рабочем каталоге подмодуля и измените его путь, чтобы он указывал на правый каталог в каталоге основного репозитория .git/modules
.
- Войдите в каталог основного репозитория
.git/modules
и найдите каталог, соответствующий вашему подмодулю.
- Отредактируйте файл
config
, обновив путь worktree
так, чтобы он указывал на новое местоположение рабочего каталога подмодуля.
- Отредактируйте файл
.gitmodules
в корне главного хранилища, обновив путь к рабочему каталогу подмодуля.
-
git add -u
-
git add <parent-of-new-submodule-directory>
(Важно, чтобы вы добавили родительский, а не сам каталог подмодулей.)
Несколько примечаний:
- Строки
[submodule "submodule-name"]
в .gitmodules
и .git/config
должны соответствовать друг другу, но не соответствуют чему-либо еще.
- Рабочий каталог подмодуля и каталог
.git
должны правильно указывать друг на друга.
- Файлы
.gitmodules
и .git/config
должны быть синхронизированы.
Ответ 6
Вы можете просто добавить новый подмодуль и удалить старый подмодуль с помощью стандартных команд. (необходимо предотвратить случайные ошибки внутри .git)
Пример настройки:
mkdir foo; cd foo; git init;
echo "readme" > README.md; git add README.md; git commit -m "First"
## add submodule
git submodule add git://github.com/jquery/jquery.git
git commit -m "Added jquery"
## </setup example>
Экзамен переместить 'jquery' в 'vendor/jquery/jquery':
oldPath="jquery"
newPath="vendor/jquery/jquery"
orginUrl=`git config --local --get submodule.${oldPath}.url`
## add new submodule
mkdir -p `dirname "${newPath}"`
git submodule add -- "${orginUrl}" "${newPath}"
## remove old submodule
git config -f .git/config --remove-section "submodule.${oldPath}"
git config -f .gitmodules --remove-section "submodule.${oldPath}"
git rm --cached "${oldPath}"
rm -rf "${oldPath}" ## remove old src
rm -rf ".git/modules/${oldPath}" ## cleanup gitdir (housekeeping)
## commit
git add .gitmodules
git commit -m "Renamed ${oldPath} to ${newPath}"
Бонусный метод для больших подмодулей:
Если подмодуль большой и вы предпочитаете не ждать клона, вы можете создать новый подмодуль, используя старый как источник, а затем переключить начало.
Пример (используйте тот же пример установки)
oldPath="jquery"
newPath="vendor/jquery/jquery"
baseDir=`pwd`
orginUrl=`git config --local --get submodule.${oldPath}.url`
# add new submodule using old submodule as origin
mkdir -p `dirname "${newPath}"`
git submodule add -- "file://${baseDir}/${oldPath}" "${newPath}"
## change origin back to original
git config -f .gitmodules submodule."${newPath}".url "${orginUrl}"
git submodule sync -- "${newPath}"
## remove old submodule
...
Ответ 7
Строка в кавычках после слова "[подмодуль" не имеет значения. Вы можете изменить его на "foobar", если хотите. Он использовал, чтобы найти соответствующую запись в ".git/config".
Поэтому, если вы внесете изменения перед запуском "git subodule init", он будет работать нормально. Если вы внесете изменение (или запишите изменение с помощью слияния), вам нужно либо вручную отредактировать .git/config, либо снова запустить "git subodule init". Если вы сделаете последнее, вы останетесь с безвредной "многожильной" записью со старым именем в .git/config.
Ответ 8
Данное решение не сработало для меня, однако аналогичная версия сделала...
Это с клонированным репозиторием, поэтому подмодуль git repos содержится в верхних репозиториях .git dir. Все катионы из верхнего хранилища:
-
Измените .gitmodules и измените настройку "path =" для рассматриваемого подмодуля. (Нет необходимости менять метку или добавлять этот файл в индекс.)
-
Измените .git/modules/name/config и измените настройку "worktree =" для рассматриваемого подмодуля
-
пробег:
mv submodule newpath/submodule
git add -u
git add newpath/submodule
Интересно, имеет ли значение, если репозитории являются атомарными или относительными подмодулями, в моем случае это относительный (подмодуль/.git - это возврат обратно в topproject/.git/modules/subodule)
Ответ 9
Просто используйте оболочку script git-submodule-move.
Ответ 10
Я только что пережил это испытание вчера и этот ответ работал отлично. Вот мои шаги, для ясности:
- Убедитесь, что подмодуль проверен и нажат на его сервер. Вам также нужно знать, на чем его ветвь.
- Вам нужен URL-адрес вашего подмодуля! Используйте
more .gitmodules
, потому что как только вы удалите подмодуль, он не будет вокруг
- Теперь вы можете использовать
deinit
, rm
, а затем submodule add
Пример
КОМАНДА
git submodule deinit Classes/lib/mustIReally
git rm foo
git submodule add http://developer.audiob.us/download/SDK.git lib/AudioBus
# do your normal commit and push
git commit -a
ПРИМЕЧАНИЕ: git mv не делает этого. На всех.