Как переместить существующий подмодуль Git в репозиторий Git? - PullRequest
319 голосов
/ 05 января 2011

Я бы хотел изменить имя каталога подмодуля 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"]

Ответы [ 10 ]

317 голосов
/ 10 июня 2011

Примечание: Как уже упоминалось в комментариях, этот ответ относится к шагам, необходимым для более старых версий git. Git теперь имеет встроенную поддержку для перемещения подмодулей:

Начиная с git 1.8.5, git mv old/submod new/submod работает как положено и выполняет всю сантехнику за вас. Возможно, вы захотите использовать git 1.9.3 или новее, поскольку он включает исправления для перемещения подмодуля.


Это похоже на удаление субмодуля (см. Как удалить субмодуль? ):

  1. Отредактируйте .gitmodules и измените путь подмодуля соответствующим образом и поместите его в индекс с помощью git add .gitmodules.
  2. При необходимости создайте родительский каталог для нового местоположения подмодуля (mkdir -p new/parent).
  3. Переместить весь контент из старого каталога в новый (mv -vi old/parent/submodule new/parent/submodule).
  4. Убедитесь, что Git отслеживает этот каталог (git add new/parent).
  5. Удалите старый каталог с помощью git rm --cached old/parent/submodule.
  6. Переместить каталог .git/modules/old/parent/submodule со всем его содержимым в .git/modules/new/parent/submodule.
  7. Отредактируйте файл .git/modules/new/parent/config, убедитесь, что элемент рабочего дерева указывает на новые местоположения, поэтому в этом примере это должно быть worktree = ../../../../../new/parent/module. Обычно в прямом пути в этом месте должно быть еще две .. директории.
  8. Отредактируйте файл 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
    #
    
  9. Наконец, внесите изменения.

211 голосов
/ 16 июля 2014

Самый современный ответ, взятый из комментария Валлорика выше:

  1. Обновление до Git 1.9.3 (или 2.18, если подмодуль содержит вложенные подмодули )
  2. git mv old/submod new/submod
  3. После этого .gitmodules и каталог подмодулей уже подготовлены для фиксации (вы можете проверить это с помощью git status.)
  4. Передайте изменения с помощью git commit и все готово!

Готово!

55 голосов
/ 28 апреля 2012

В моем случае я хотел переместить подмодуль из одного каталога в подкаталог, например, «AFNetworking» -> «ext / AFNetworking».Вот шаги, которые я выполнил:

  1. Редактировать .gitmodules, изменяя имя и путь подмодуля на «ext / AFNetworking»
  2. Переместить каталог git подмодуля из «.git / modules / AFNetworking»в ".git / modules / ext / AFNetworking"
  3. Переместить библиотеку из "AFNetworking" в "ext / AFNetworking"
  4. Edit ".git / modules / ext / AFNetworking / config" и исправитьлиния [core] worktree.Моя поменялась с ../../../AFNetworking на ../../../../ext/AFNetworking
  5. Отредактируйте "ext / AFNetworking / .git" и исправьте gitdir.Шахта изменилась с ../.git/modules/AFNetworking на ../../git/modules/ext/AFNetworking
  6. git add .gitmodules
  7. git rm --cached AFNetworking
  8. 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 вуаля.Приведенный выше пример не меняет глубину каталога, что сильно влияет на сложность задачи, и не меняет имя подмодуля (что может и не быть необходимым, но я сделал это, чтобы соответствовать тому, чтопроизойдет, если я добавлю новый модуль по этому пути.)

18 голосов
/ 19 сентября 2013

[Обновление: 2014-11-26] Поскольку Яр подводит итоги ниже, , прежде чем что-либо делать, убедитесь, что вы знаете 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"
11 голосов
/ 14 ноября 2012

Похоже, хитрость заключается в том, что каталог .git для подмодулей теперь хранится в главном репозитории под .git/modules, и у каждого подмодуля есть файл .git, который указывает на него.Вот процедура, которая вам нужна:

  • Переместите подмодуль в его новый дом.
  • Отредактируйте файл .git в рабочем каталоге подмодуля и измените путь, который он содержитчто он указывает на правильный каталог в каталоге .git/modules главного репозитория.
  • Войдите в каталог .git/modules главного репозитория и найдите каталог, соответствующий вашему подмодулю.
  • Отредактируйте config file, обновляя путь worktree так, чтобы он указывал на новое местоположение рабочего каталога подмодуля.
  • Отредактируйте файл .gitmodules в корне главного репозитория, обновив путь к рабочему каталогусубмодуля.
  • git add -u
  • git add <parent-of-new-submodule-directory> (Важно добавить родительский , а не сам каталог подмодуля.)

Несколько примечаний:

  • Строки [submodule "submodule-name"] в .gitmodules и .git/config должны соответствовать друг другу, но не соответствуют ничему другому.
  • Подмодуль рабочего каталога и .gitкаталог должен правильно указывать друг на друга.
  • Файлы .gitmodules и .git/config должны быть синхронизированы.
9 голосов
/ 19 декабря 2012

Вы можете просто добавить новый подмодуль и удалить старый подмодуль, используя стандартные команды. (должен предотвращать любые случайные ошибки внутри .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
...
8 голосов
/ 05 января 2011

Строка в кавычках после "[submodule" не имеет значения.Вы можете изменить его на «foobar», если хотите.Он используется для поиска подходящей записи в «.git / config».

Поэтому, если вы внесете изменения до запуска «git submodule init», все будет работать нормально.Если вы внесете изменение (или получите его с помощью слияния), вам нужно будет либо вручную отредактировать .git / config, либо снова запустить «git submodule init».Если вы сделаете последнее, у вас останется безобидная «застрявшая» запись со старым именем в .git / config.

2 голосов
/ 15 апреля 2014

Я только что прошел это испытание вчера, и этот ответ сработал отлично.Вот мои шаги для ясности:

  1. Убедитесь, что субмодуль зарегистрирован и отправлен на свой сервер.Вам также нужно знать, в какой ветке он находится.
  2. Вам нужен URL вашего подмодуля! Используйте more .gitmodules, потому что после удаления подмодуля его уже не будет
  3. Теперь вы можете использовать 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 этого не делает.На всех.

2 голосов
/ 22 июля 2013

Просто используйте скрипт оболочки git-submodule-move .

2 голосов
/ 26 апреля 2012

Данное решение не сработало у меня, однако аналогичная версия сработала ...

Это с клонированным репозиторием, поэтому подмодульные репозитории git содержатся в верхних репозиториях .git dir. Все катионы из верхнего хранилища:

  1. Отредактируйте .gitmodules и измените настройку «путь =» для рассматриваемого подмодуля. (Нет необходимости ни менять метку, ни добавлять этот файл в индекс.)

  2. Отредактируйте .git / modules / name / config и измените настройку "worktree =" для рассматриваемого подмодуля

  3. пробег:

    mv submodule newpath/submodule
    git add -u
    git add newpath/submodule
    

Интересно, будет ли разница, если репозитории являются атомарными или относительными подмодулями, в моем случае это было относительно (submodule / .git - это ссылка на topproject / .git / modules / submodule)

...