web-dev-qa-db-fra.com

Comment déplacer un sous-module Git existant dans un référentiel Git?

J'aimerais changer le nom de répertoire d'un sous-module Git dans mon superprojet Git.

Supposons que j'ai l'entrée suivante dans mon fichier .gitmodules:

[submodule ".emacs.d/vimpulse"]  
path = .emacs.d/vimpulse  
url = git://gitorious.org/vimpulse/vimpulse.git

Qu'est-ce que je dois taper pour déplacer le répertoire .emacs.d/vimpulse vers .emacs.d/vendor/vimpulse sans le supprimer d'abord (expliqué ici et ici ), puis en rajoutant il.

Git a-t-il vraiment besoin de l'intégralité du chemin dans la balise de sous-module?

[submodule ".emacs.d/vimpulse"]

ou est-il également possible de stocker uniquement le nom du sous-projet?

[submodule "vimpulse"]
325
thisch

Remarque: Comme mentionné dans les commentaires, cette réponse fait référence aux étapes nécessaires avec les anciennes versions de git. Git a maintenant un support natif pour le déplacement de sous-modules:

Depuis git 1.8.5, git mv old/submod new/submod fonctionne comme prévu et effectue toute la plomberie pour vous. Vous voudrez peut-être utiliser git 1.9.3 ou plus récent, car il inclut des correctifs pour le déplacement de sous-modules.


Cela ressemble à la façon dont vous supprimez un sous-module (voir Comment puis-je supprimer un sous-module? ):

  1. Editez .gitmodules et modifiez le chemin du sous-module en conséquence, puis insérez-le dans l'index avec git add .gitmodules.
  2. Si nécessaire, créez le répertoire parent du nouvel emplacement du sous-module (mkdir -p new/parent).
  3. Déplacez tout le contenu de l'ancien répertoire vers le nouveau répertoire (mv -vi old/parent/submodule new/parent/submodule).
  4. Assurez-vous que Git suit ce répertoire (git add new/parent).
  5. Supprimez l'ancien répertoire avec git rm --cached old/parent/submodule.
  6. Déplacez le répertoire .git/modules/old/parent/submodule avec tout son contenu dans .git/modules/new/parent/submodule.
  7. Editez le fichier .git/modules/new/parent/config, assurez-vous que l'élément de la structure de travail pointe vers les nouveaux emplacements. Dans cet exemple, il devrait donc s'agir de worktree = ../../../../../new/parent/module. En règle générale, il devrait y avoir deux autres répertoires .., puis dans le chemin direct à cet endroit.
  8. Editez le fichier new/parent/module/.git, assurez-vous que son chemin pointe vers le nouvel emplacement correct dans le dossier du projet principal .git. Dans cet exemple, gitdir: ../../../.git/modules/new/parent/submodule.

    git status la sortie ressemble à ceci pour moi par la suite:

    # On branch master
    # Changes to be committed:
    #   (use "git reset HEAD <file>..." to unstage)
    #
    #       modified:   .gitmodules
    #       renamed:    old/parent/submodule -> new/parent/submodule
    #
    
  9. Enfin, validez les modifications.

324
Axel Beckert

La réponse la plus moderne, tirée du commentaire de Valloric ci-dessus:

  1. Passez à Git 1.9.3 (ou 2.18 si le sous-module contient des sous-modules imbriqués )
  2. git mv old/submod new/submod
  3. Ensuite, les répertoires .gitmodules et le sous-module sont déjà préparés pour une validation (vous pouvez le vérifier avec git status.)
  4. Validez les modifications avec git commitet vous voilà prêt à partir!

Terminé!

212
phatmann

Dans mon cas, je souhaitais déplacer un sous-module d’un répertoire vers un sous-répertoire, par exemple. "AFNetworking" -> "ext/AFNetworking". Ce sont les étapes que j'ai suivies:

  1. Editez .gitmodules en changeant le nom du sous-module et son chemin en "ext/AFNetworking"
  2. Déplacez le répertoire git du sous-module de ".git/modules/AFNetworking" à ".git/modules/ext/AFNetworking"
  3. Déplacer la bibliothèque de "AFNetworking" vers "ext/AFNetworking"
  4. Éditez ".git/modules/ext/AFNetworking/config" et corrigez la ligne [core] worktree. Le mien est passé de ../../../AFNetworking à ../../../../ext/AFNetworking
  5. Éditez "ext/AFNetworking/.git" et corrigez gitdir. Le mien est passé de ../.git/modules/AFNetworking à ../../git/modules/ext/AFNetworking
  6. git add .gitmodules
  7. git rm --cached AFNetworking
  8. git submodule add -f <url> ext/AFNetworking

Enfin, j'ai vu dans le statut de 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 voilà. L'exemple ci-dessus ne modifie pas la profondeur du répertoire, ce qui a une grande incidence sur la complexité de la tâche et sur le nom du sous-module (ce qui n'est peut-être pas vraiment nécessaire, mais je l'ai fait pour être cohérent avec ce que se produirait si j’ajoutais un nouveau module sur ce chemin.)

55
Matt Connolly

[Mise à jour: 2014-11-26] Comme Yar résume bien ci-dessous, avant de faire quoi que ce soit, assurez-vous de connaître l'URL de le sous-module. Si inconnu, ouvrez .git/.gitmodules et examinez la clé submodule.<name>.url .

Ce qui a fonctionné pour moi a été de supprimer l'ancien sous-module en utilisant _git submodule deinit <submodule>_ suivi de _git rm <submodule-folder>_. Ajoutez ensuite le sous-module avec le nouveau nom de dossier et validez. Vérifier l'état de git avant de valider montre l'ancien sous-module renommé avec le nouveau nom et le .gitmodule modifié.

_$ 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"
_
19
Mark Mikofski

L'astuce semble comprendre que le répertoire .git des sous-modules est maintenant conservé dans le référentiel maître, sous .git/modules, et que chaque sous-module comporte un fichier .git qui le pointe. C'est la procédure dont vous avez besoin maintenant:

  • Déplacez le sous-module dans sa nouvelle maison.
  • Editez le fichier .git dans le répertoire de travail du sous-module et modifiez le chemin qu'il contient pour qu'il pointe vers le répertoire de droite dans le répertoire .git/modules du référentiel maître.
  • Entrez le répertoire .git/modules du référentiel maître et recherchez le répertoire correspondant à votre sous-module.
  • Editez le fichier config en mettant à jour le chemin worktree afin qu'il pointe vers le nouvel emplacement du répertoire de travail du sous-module.
  • Editez le fichier .gitmodules à la racine du référentiel maître, en mettant à jour le chemin d'accès au répertoire de travail du sous-module.
  • git add -u
  • git add <parent-of-new-submodule-directory> (Il est important que vous ajoutiez le parent, et non le répertoire du sous-module lui-même.)

Quelques notes:

  • Les lignes [submodule "submodule-name"] dans .gitmodules et .git/config doivent être identiques, mais ne correspondent à rien d'autre.
  • Le répertoire de travail du sous-module et le répertoire .git doivent se désigner correctement.
  • Les fichiers .gitmodules et .git/config doivent être synchronisés.
11
Paul Gideon Dann

Vous pouvez simplement ajouter un nouveau sous-module et supprimer l'ancien sous-module à l'aide de commandes standard. (devrait empêcher toute erreur accidentelle à l'intérieur de .git)

Exemple d'installation:

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>

Examinez le mouvement 'jquery' vers '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}"

Méthode bonus pour les grands sous-modules:

Si le sous-module est volumineux et que vous préférez ne pas attendre le clone, vous pouvez créer le nouveau sous-module en utilisant l'ancien en tant qu'origine, puis basculer l'origine.

Exemple (utilisez le même exemple d'installation)

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
...
9
Lance Rushing

La chaîne entre guillemets après "[submodule" n'a pas d'importance. Vous pouvez le changer en "foobar" si vous voulez. Il est utilisé pour trouver l'entrée correspondante dans ".git/config".

Par conséquent, si vous effectuez la modification avant d'exécuter "git submodule init", cela fonctionnera correctement. Si vous apportez la modification (ou prenez la modification par une fusion), vous devrez soit modifier manuellement le fichier .git/config, soit exécuter à nouveau "git submodule init". Si vous faites cela, vous aurez une entrée inoffensive "échouée" avec l'ancien nom dans .git/config.

8
Bob Bell

Je viens de traverser cette épreuve hier et cette réponse a parfaitement fonctionné. Voici mes étapes, pour plus de clarté:

  1. Assurez-vous que le sous-module est archivé et transmis à son serveur. Vous devez également savoir quelle branche est active.
  2. Vous avez besoin de l'URL de votre sous-module! Utilisez more .gitmodules car une fois que vous supprimez le sous-module, il ne sera plus disponible.
  3. Maintenant, vous pouvez utiliser deinit, rm puis submodule add

EXEMPLE

COMMANDES

    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 

NOTE: git mv ne le fait pas. Du tout.

2
Dan Rosenstark

Utilisez simplement le script shell git-submodule-move .

2
Flimm

La solution proposée n'a pas fonctionné pour moi, cependant une version similaire a fonctionné ...

Il s’agit d’un référentiel cloné; par conséquent, les dépôts git du sous-module sont contenus dans les référentiels supérieurs .git dir. Tous les cations proviennent du référentiel supérieur:

  1. Modifiez .gitmodules et modifiez le paramètre "path =" pour le sous-module en question. (Pas besoin de changer l'étiquette, ni d'ajouter ce fichier à l'index.)

  2. Editez .git/modules/name/config et modifiez le paramètre "worktree =" pour le sous-module en question

  3. courir:

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

Je me demande si cela fait une différence si les référentiels sont atomiques, ou des sous-modules relatifs, dans mon cas, il était relatif (submodule/.git est une référence pour renvoyer à topproject/.git/modules/submodule)

2
arand