Как переместить существующий подмодуль 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 выше:

  1. Обновление до Git 1.9.3 (или 2.18, если подмодуль содержит вложенные подмодули)
  2. git mv old/submod new/submod
  3. После этого .gitmodules и каталог submodule уже подготовлены для фиксации (вы можете проверить это с помощью git status.)
  4. Зафиксируйте изменения с помощью 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 не делает этого. На всех.