93 votes

Restaurer les submodules git à partir de .gitmodules

J'ai un dossier, qui était un dépôt git. Il contient quelques fichiers et le fichier .gitmodules. Maintenant, quand je fais git init et ensuite git submodule init le résultat de cette dernière commande n'est rien. Comment puis-je aider git à voir les submodules, définis dans le fichier .gitmodules, sans exécuter la commande git submodule add à la main à nouveau ?

Mise à jour : voici mon fichier .gitmodules :

[submodule "vim-pathogen"]
    path = vim-pathogen
    url = git://github.com/tpope/vim-pathogen.git
[submodule "bundle/python-mode"]
    path = bundle/python-mode
    url = git://github.com/klen/python-mode.git
[submodule "bundle/vim-fugitive"]
    path = bundle/vim-fugitive
    url = git://github.com/tpope/vim-fugitive.git
[submodule "bundle/ctrlp.vim"]
    path = bundle/ctrlp.vim
    url = git://github.com/kien/ctrlp.vim.git
[submodule "bundle/vim-tomorrow-theme"]
    path = bundle/vim-tomorrow-theme
    url = git://github.com/chriskempson/vim-tomorrow-theme.git

et voici la liste de ce directeur :

drwxr-xr-x  4 evgeniuz 100 4096   29 12:06 .
drwx------ 60 evgeniuz 100 4096   29 11:43 ..
drwxr-xr-x  2 evgeniuz 100 4096   29 10:03 autoload
drwxr-xr-x  7 evgeniuz 100 4096   29 12:13 .git
-rw-r--r--  1 evgeniuz 100  542   29 11:45 .gitmodules
-rw-r--r--  1 evgeniuz 100  243   29 11:18 .vimrc

donc, définitivement, il est au niveau supérieur. le répertoire git n'est pas modifié, seulement git init est fait

0 votes

Les submodules sont-ils déjà présents, en ce sens que si vous passez dans un répertoire de submodule, des fichiers sont présents, et git rev-parse --show-toplevel vous donne le répertoire du sous-module plutôt que celui du "supermodule" ?

0 votes

Non, les répertoires de sous-modules ne sont pas présents. imaginez que ce dossier soit complètement vide avec seulement .gitmodules fichier

0 votes

Ah, je vois quel est le problème - j'ai mis à jour ma réponse.

121voto

Mark Longair Points 93104

git submodule init ne considère que les submodules qui sont déjà dans l'index (c'est-à-dire "staged") pour l'initialisation. J'écrirais un court script qui analyserait .gitmodules et pour chaque url y path la paire fonctionne :

git submodule add <url> <path>

Par exemple, vous pouvez utiliser le script suivant :

#!/bin/sh

set -e

git config -f .gitmodules --get-regexp '^submodule\..*\.path$' |
    while read path_key path
    do
        url_key=$(echo $path_key | sed 's/\.path/.url/')
        url=$(git config -f .gitmodules --get "$url_key")
        git submodule add $url $path
    done

Ceci est basé sur la façon dont le git-submodule.sh script analyse lui-même les .gitmodules fichier.

4 votes

Voulez-vous dire git submodule update --init ? toutes ces commandes échouent en silence. Il semble que git ne voit pas les modules définis uniquement dans le fichier .gitmodules

0 votes

Après le git submodule init est-ce que vous voyez une sortie de git config --list | grep submodule ? (Comme le dit la documentation, git submodule init devrait "Initialiser les submodules, c'est-à-dire enregistrer chaque nom de submodule et url trouvés dans .gitmodules dans le fichier .git/config ".)

0 votes

Non, rien. git config --list ne donne que des valeurs standard, aucune mention des sous-modules

15voto

Kevin C. Points 1072

En développant la réponse de @Mark Longair, j'ai écrit un bash script pour automatiser les étapes 2 & 3 du processus suivant :

  1. Cloner un repo "boilerplate" pour commencer un nouveau projet
  2. Supprimez le dossier .git et réinitialisez-le en tant que nouveau dépôt.
  3. Réinitialiser les sous-modules, en demandant une saisie avant de supprimer les dossiers.

#!/bin/bash

set -e
rm -rf .git
git init

git config -f .gitmodules --get-regexp '^submodule\..*\.path$' > tempfile

while read -u 3 path_key path
do
    url_key=$(echo $path_key | sed 's/\.path/.url/')
    url=$(git config -f .gitmodules --get "$url_key")

    read -p "Are you sure you want to delete $path and re-initialize as a new submodule? " yn
    case $yn in
        [Yy]* ) rm -rf $path; git submodule add $url $path; echo "$path has been initialized";;
        [Nn]* ) exit;;
        * ) echo "Please answer yes or no.";;
    esac

done 3<tempfile

rm tempfile

Remarque : les sous-modules seront extraits à l'extrémité de leur branche principale au lieu du même commit que le repo boilerplate, vous devrez donc le faire manuellement.

Le fait de canaliser la sortie de git config dans la boucle de lecture causait des problèmes avec l'invite d'entrée, donc il la sort dans un fichier temporaire à la place. Toute amélioration de mon premier bash script serait la bienvenue :)


Un grand merci à Mark, https://stackoverflow.com/a/226724/193494 , bash : lecture interactive imbriquée dans une boucle qui utilise aussi read et tnettenba @ chat.freenode.net pour m'avoir aidé à trouver cette solution !

8voto

mauron85 Points 665

Extension de l'excellente réponse de @Mark Longair pour ajouter un sous-module respectant le nom de la branche et du repo.

#!/bin/sh

set -e

git config -f .gitmodules --get-regexp '^submodule\..*\.path$' |
    while read path_key path
    do
        name=$(echo $path_key | sed 's/\submodule\.\(.*\)\.path/\1/')
        url_key=$(echo $path_key | sed 's/\.path/.url/')
        branch_key=$(echo $path_key | sed 's/\.path/.branch/')
        url=$(git config -f .gitmodules --get "$url_key")
        branch=$(git config -f .gitmodules --get "$branch_key" || echo "master")
        git submodule add -b $branch --name $name $url $path || continue
    done

3voto

f1r3br4nd Points 1024

Une version mise à jour du script par @mark-longair . Celle-ci supporte également les branches, gère le cas où certains des sous-modules existent déjà dans .git/config et, si nécessaire, sauvegarde les répertoires existants du même nom que les chemins des sous-modules.

git config -f .gitmodules --get-regexp '^submodule\..*\.path$' |
    while read path_key path
    do
        url_key=$(echo $path_key | sed 's/\.path/.url/');
        branch_key=$(echo $path_key | sed 's/\.path/.branch/');
        # If the url_key doesn't yet exist then backup up the existing
        # directory if necessary and add the submodule
        if [ ! $(git config --get "$url_key") ]; then
            if [ -d "$path" ] && [ ! $(git config --get "$url_key") ]; then
                mv "$path" "$path""_backup_""$(date +'%Y%m%d%H%M%S')";
            fi;
            url=$(git config -f .gitmodules --get "$url_key");
            # If a branch is specified then use that one, otherwise
            # default to master
            branch=$(git config -f .gitmodules --get "$branch_key");
            if [ ! "$branch" ]; then branch="master"; fi;
            git submodule add -f -b "$branch" "$url" "$path";
        fi;
    done;

# In case the submodule exists in .git/config but the url is out of date

git submodule sync;

# Now actually pull all the modules. I used to use this...
#
# git submodule update --init --remote --force --recursive
# ...but the submodules would check out in detached HEAD state and I 
# didn't like that, so now I do this...

git submodule foreach --recursive 'git checkout $(git config -f $toplevel/.gitmodules submodule.$name.branch || echo master)';

3voto

Henry Points 117

J'ai eu un problème similaire. git submodule init s'effondrait en silence.

Quand je l'ai fait :

git submodule add <url> <path>

J'ai eu :

The following path is ignored by one of your .gitignore files: ...

Je pense que les chemins .gitignore(d) peuvent en être la cause.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X