Comment supprimer un sous-module?

3540

Comment supprimer un sous-module Git?

Au fait, y a-t-il une raison pour laquelle je ne peux pas simplement le faire git submodule rm whatever?

R. Martinho Fernandes
la source
109
La réponse simple stackoverflow.com/a/21211232/94687 est maintenant la bonne et doit être marquée ainsi. Maintenant, c'est simplement git rm modulenameetrm -rf .git/modules/modulename
imz - Ivan Zakharyaschev
10
Ce n'est en fait pas vrai. Cette réponse ne concerne pas la suppression de l'entrée du sous-module .git/config. La réponse acceptée montre la manière la plus récente de supprimer complètement un sous-module. Il est également expliqué plus succinctement dans cette réponse: stackoverflow.com/a/36593218/1562138
fvgs
J'ai trouvé cet article très utile pour supprimer des sous-modules. Il comprend des informations sur la suppression des entrées dans le lien des
Ri_
12
S'il vous plaît, économisez du temps et passez directement à la réponse qui fonctionne (en 2017): stackoverflow.com/a/36593218/528313
Vincenzo Pii
J'ai lutté contre des problèmes de sous-modules pendant deux jours. La percée est survenue lorsque j'ai trouvé ceci: forums.developer.apple.com/thread/13102 . Fondamentalement, Xcode, et peut-être d'autres applications, ont du mal à étendre les URL contenant «~». Une fois que j'ai changé ssh: //[email protected]/~/git/MyRepo.git en ssh: //[email protected]/home/username/git/MyRepo.git (recherchez le chemin réel sur votre serveur), toute l'étrangeté a disparu en dix minutes. Voir aussi stackoverflow.com/questions/32833100/…
Elise van Looij

Réponses:

2216

Depuis git1.8.3 (22 avril 2013) :

Il n'y avait pas de façon Porcelaine de dire "Je ne suis plus intéressé par ce sous-module", une fois que vous exprimez votre intérêt pour un sous-module avec " submodule init".
" submodule deinit" est le moyen de le faire.

Le processus de suppression utilise également git rm(depuis git1.8.5 octobre 2013).

Sommaire

Le processus de suppression en 3 étapes serait alors:

0. mv a/submodule a/submodule_tmp

1. git submodule deinit -f -- a/submodule    
2. rm -rf .git/modules/a/submodule
3. git rm -f a/submodule
# Note: a/submodule (no trailing slash)

# or, if you want to leave it in your working tree and have done step 0
3.   git rm --cached a/submodule
3bis mv a/submodule_tmp a/submodule

Explication

rm -rf: Ceci est mentionné dans la réponse de Daniel Schroeder et résumé par Eonil dans les commentaires :

Cela reste .git/modules/<path-to-submodule>/inchangé.
Donc, si vous supprimez une fois un sous-module avec cette méthode et les ajoutez à nouveau, ce ne sera pas possible car le référentiel a déjà été corrompu.


git rm: Voir commit 95c16418 :

L'utilisation actuelle de " git rm" sur un sous-module supprime l'arborescence de travail du sous-module de celle du superprojet et le gitlink de l'index.
Mais la section du sous-module dans .gitmodulesest laissée intacte, ce qui est un reste du sous-module maintenant supprimé et pourrait irriter les utilisateurs (par opposition à la configuration .git/config, cela doit rester comme un rappel que l'utilisateur a montré de l'intérêt pour ce sous-module afin qu'il soit repeuplé plus tard lorsqu'un ancien commit est extrait).

Laissez " git rm" aider l 'utilisateur en supprimant non seulement le sous - module de l' arborescence de travail, mais en supprimant également la submodule.<submodule name>section " " du .gitmodulesfichier et mettez en scène les deux.


git submodule deinit: Il découle de ce patch :

Avec " git submodule init", l'utilisateur peut dire à git qu'il se soucie d'un ou de plusieurs sous-modules et souhaite qu'il soit rempli lors du prochain appel à " git submodule update".
Mais actuellement, il n'y a aucun moyen facile de dire à git qu'il ne se soucie plus d'un sous-module et veut se débarrasser de l'arbre de travail local (à moins que l'utilisateur en sache beaucoup sur les éléments internes du sous-module et supprime le submodule.$name.urlparamètre " " de l' .git/configensemble du travail) arbre lui-même).

Aidez ces utilisateurs en fournissant une deinitcommande ' '.
Cela supprime la submodule.<name>section entière .git/configsoit pour le ou les sous-modules donnés (ou pour tous ceux qui ont été initialisés si ' .' est donné).
Échec si l'arborescence de travail actuelle contient des modifications, sauf si forcé.
Se plaindre quand pour un sous-module donné sur la ligne de commande, le paramètre d'URL est introuvable .git/config, mais néanmoins n'échoue pas.

Cela prend soin si les étapes de (dé) initialisation ( .git/configet .git/modules/xxx)

Depuis git1.8.5, le git rmprend également en charge:

  • ' add' étape qui enregistre l'url d'un sous-module dans le .gitmodulesfichier: il faut le supprimer pour vous.
  • l' entrée spéciale du sous-module (comme illustré par cette question ): le git rm le supprime de l'index:
    git rm --cached path_to_submodule(pas de barre oblique de fin)
    Cela supprimera ce répertoire stocké dans l'index avec un mode spécial "160000", le marquant comme un répertoire racine de sous-module .

Si vous oubliez cette dernière étape et essayez d'ajouter ce qui était un sous-module en tant que répertoire normal, vous obtiendrez un message d'erreur comme:

git add mysubmodule/file.txt 
Path 'mysubmodule/file.txt' is in submodule 'mysubmodule'

Remarque: depuis Git 2.17 (Q2 2018), le sous-module git deinit n'est plus un script shell.
C'est un appel à une fonction C.

Voir commit 2e61273 , commit 1342476 (14 janvier 2018) par Prathamesh Chavan ( pratham-pc) .
(Fusionné par Junio ​​C Hamano - gitster- en commit ead8dbe , 13 févr.2018 )

git ${wt_prefix:+-C "$wt_prefix"} submodule--helper deinit \
  ${GIT_QUIET:+--quiet} \
  ${prefix:+--prefix "$prefix"} \
  ${force:+--force} \
  ${deinit_all:+--all} "$@"
VonC
la source
18
Pouvez-vous donner un exemple d'utilisation pour submodule deinit?
zakdances
5
@yourfriendzak voici un exemple d'utilisation réussie: stackoverflow.com/a/16161950/6309 . Mais gardez à l'esprit que, contrairement à ce que je pensais à l'origine, 1.8.3 n'est pas encore sorti! Sous Unix, vous pouvez le compiler à partir des sources.
VonC
2
@HamishDowner l'entrée spéciale devrait être partie (le répertoire n'est plus un sous-module), et .gitmodulesdevrait être ok, mais je revérifierais tout avec le .gitrépertoire (c'est-à-dire la configuration locale , dans votre référentiel local: ce n'est pas modifié par a git pull)
VonC
2
@Jayen oui, si vous validez la suppression de l' .gitmodulesentrée et la suppression de l'entrée spéciale dans l'index, et que vous appuyez sur ce dépôt, d'autres peuvent le retirer et ce sous-module disparaîtra.
VonC
3
Dans git actuel (v1.9 +), plain old git rm submodulefait exactement ce que vous voulez, comme d'autres l'ont déjà dit.
Pete Peterson
3445

Via la page Tutoriel du sous-module Git :

Pour supprimer un sous-module, vous devez:

  1. Supprimez la section appropriée du .gitmodulesfichier.
  2. Mettez en scène les .gitmoduleschangements:
    git add .gitmodules
  3. Supprimez la section appropriée de .git/config.
  4. Supprimez les fichiers de sous-module de l'arborescence de travail et de l'index:
    git rm --cached path_to_submodule(pas de barre oblique de fin).
  5. Supprimez le .gitrépertoire du sous-module :
    rm -rf .git/modules/path_to_submodule
  6. Validez les modifications:
    git commit -m "Removed submodule <name>"
  7. Supprimez les fichiers de sous-module désormais non suivis:
    rm -rf path_to_submodule

Voir aussi : étapes alternatives ci-dessous .

John Douthat
la source
410
"Et au fait, y a-t-il une raison pour laquelle je ne peux pas simplement lancer un sous-module rm?" ?
abernier
48
@abernier Une réponse brève pourrait être "car aucune commande de ce type n'existe". Je suppose qu'ils essaient de rendre la suppression des fichiers de sous-module vs la configuration de sous-module explicite pour éviter la perte accidentelle de données. Peut-être qu'une personne penserait que cela git submodule rmsupprime simplement l'enregistrement du sous-module et serait surprise si la commande supprimait également le référentiel local. Tout changement local serait irrémédiablement perdu. Et peut-être qu'une autre personne penserait que seuls les fichiers seraient supprimés.
John Douthat
119
Franchement, je ne sais pas pourquoi. J'espère cependant qu'ils ajouteront une commande. Ces 4 étapes sont trop compliquées.
John Douthat
25
Voici un script bash qui supprime un sous-module, il suffit de créer un alias git pour submodule-rm;) gist.github.com/2491147
Capi Etheriel
33
également besoin de rm -rf .git \ modules \ nom du sous-module?
rogerdpack
484

Juste une note. Depuis git 1.8.5.2, deux commandes feront l'affaire:

git rm the_submodule
rm -rf .git/modules/the_submodule

Comme l'a correctement souligné la réponse de @Mark Cheverton, si la deuxième ligne n'est pas utilisée, même si vous avez supprimé le sous-module pour l'instant, le dossier .git / modules / the_submodule restant empêchera le même sous-module d'être ajouté ou remplacé à l'avenir . En outre, comme l'a mentionné @VonC, la git rmplupart du travail sera effectué sur un sous-module.

--Mise à jour (07/05/2017) -

Juste pour clarifier, the_submoduleest le chemin relatif du sous-module à l'intérieur du projet. Par exemple, c'est subdir/my_submodulesi le sous-module se trouve dans un sous-répertoire subdir.

Comme indiqué correctement dans les commentaires et autres réponses , les deux commandes (bien que fonctionnellement suffisantes pour supprimer un sous-module), laissent une trace dans la [submodule "the_submodule"]section .git/config(à partir de juillet 2017), qui peut être supprimée à l'aide d'une troisième commande:

git config -f .git/config --remove-section submodule.the_submodule 2> /dev/null
tinlyx
la source
5
Je suis sur la version 2.4.9 de git (Apple Git-60) et tout ce que j'avais à faire était de rm the_submodule. J'ai poussé puis ajouté un dossier nommé le même que le sous-module et cela a fonctionné sans problème.
David Silva Smith
19
Cela ne supprime pas l'entrée de sous-module de .git/config. Voir stackoverflow.com/a/36593218/1562138 pour la méthode complète de suppression d'un sous-module.
fvgs
2
@drevicko Je viens de tester cela avec Git 2.11.1 et j'observe le même comportement qu'auparavant. git init && git submodule add <repository> && git rm <name>laisse l' .git/configentrée et le .git/modules/<name>répertoire et son contenu. Peut-être n'avez-vous pas initialisé le sous-module avant de le retirer?
fvgs
2
je me sens plus en sécurité en exécutant cette première .. git submodule deinit -f the_submodule
danday74
1
@JarrodSmith Oui, c'est le chemin. veuillez consulter la mise à jour.
tinlyx
479

La majorité des réponses à cette question sont obsolètes, incomplètes ou inutilement complexes.

Un sous-module cloné à l'aide de git 1.7.8 ou plus récent laissera au plus quatre traces de lui-même dans votre dépôt local. Le processus de suppression de ces quatre traces est donné par les trois commandes ci-dessous:

# Remove the submodule entry from .git/config
git submodule deinit -f path/to/submodule

# Remove the submodule directory from the superproject's .git/modules directory
rm -rf .git/modules/path/to/submodule

# Remove the entry in .gitmodules and remove the submodule directory located at path/to/submodule
git rm -f path/to/submodule
fvgs
la source
39
Pourquoi cette réponse a-t-elle si peu de votes positifs? Toutes ces réponses populaires manquent quelque chose, c'est la seule qui supprime vraiment toutes les traces d'un sous-module, de la manière la plus simple possible. Et notez: l'ordre des commandes est important.
mbdevpl
2
Pour répondre à ma propre question: stackoverflow.com/questions/97875/rm-rf-equivalent-for-windows
Thomas
5
@mbdevpl est venu 3 ans après la réponse acceptée, et je suppose que personne n'a réussi à convaincre le PO d'accepter celle-ci
Andy
10
CECI est la réponse pas compliquée en 2018?
Warren P
9
le fichier .gitmodules ne semble toujours pas affecté par l'exécution de ces commandes
Fractalf
206

Étapes simples

  1. Supprimez les entrées de configuration:
    git config -f .git/config --remove-section submodule.$submodulename
    git config -f .gitmodules --remove-section submodule.$submodulename
  2. Supprimer le répertoire de l'index:
    git rm --cached $submodulepath
  3. Commettre
  4. Supprimer les fichiers inutilisés:
    rm -rf $submodulepath
    rm -rf .git/modules/$submodulename

Remarque: $submodulepath ne contient pas de barres obliques de début ou de fin.

Contexte

Lorsque vous le faites git submodule add, il ne fait que l'ajouter .gitmodules, mais une fois que vous l'avez fait git submodule init, il l'ajoute à .git/config.

Donc, si vous souhaitez supprimer les modules, mais pouvoir les restaurer rapidement, procédez comme suit:

git rm --cached $submodulepath
git config -f .git/config --remove-section submodule.$submodulepath

C'est une bonne idée de faire d' git rebase HEADabord et git commit à la fin, si vous mettez cela dans un script.

Consultez également la réponse à Puis-je dépeupler un sous-module Git? .

erreurs
la source
1
J'avais beaucoup de sous-modules (et un plus gros gâchis) donc j'ai dû les passer par une boucle for. Étant donné que la plupart d'entre eux se trouvaient sous un répertoire spécifique et que la sortie ls contenait des barres obliques de fin. J'ai fait quelque chose comme ça for dir in directory/*; do git rm --cached $dir; done.
Pablo Olmos de Aguilera C.
Pour obtenir cela, la liste qui peut être utilisée dans le script pour la suppression récursive - git config -f .git/config -l | cut -d'=' -f1 | grep "submodule.$MODPATH" | sed 's/^submodule\.//' | sed 's/\.url$//'- - semble que vous devez vraiment le faire au cas où quelque chose ne fonctionnerait pas, sinon justegit submodule | grep -v '^+' | cut -d' ' -f3
errordeveloper
2
pour obtenir la liste des modules où aucune modification locale n'a été apportée -git submodule | grep '^+' | cut -d' ' -f2
errordeveloper
note, je devais inclure submodulenamedes guillemets doubles "submodulename". renvoyant le .git/configfichier
muon
Facile. Efficace. Dans 2.25.0, après l'étape 1, vous devez mettre en place les changements de .gitmodules avant l'étape 2.
Michel Donais
83

En plus des recommandations, je devais aussi rm -Rf .git/modules/path/to/submodulepouvoir ajouter un nouveau sous-module du même nom (dans mon cas je remplaçais une fourche par l'original)

Mark Cheverton
la source
1
J'avais aussi des problèmes avec ça. Si vous essayez de réinstaller un sous-module sur le même chemin, il conserve les informations de branche mises en cache à l'emplacement que vous avez mentionné, ce qui gâche les choses.
jangosteve
Merci, j'en avais aussi besoin. @Anton, je suis d'accord et j'ai modifié la réponse la mieux notée pour ajouter ces informations.
William Denniss
J'ai utilisé l'option --name pour faire fonctionner le remplacement ... voir stackoverflow.com/questions/14404704/…
joseph.hainline
60

Pour supprimer un sous-module ajouté à l'aide de:

git submodule add [email protected]:repos/blah.git lib/blah

Courir:

git rm lib/blah

C'est ça.

Pour les anciennes versions de git (environ ~ 1.8.5), utilisez:

git submodule deinit lib/blah
git rm lib/blah
git config -f .gitmodules --remove-section submodule.lib/blah
Doug
la source
1
+1 en effet. C'est la seule bonne réponse à partir de git 1.8.3. Doit être accepté comme le bon.
Xananax
6
git rmlaisse encore des trucs dedans .git/modules/. (2.5.4)
Rudolf Adamkovič
1
@RudolfAdamkovic ça marche pour moi? Notez qu'il ne supprime l'entrée du sous-module que si le chemin exact correspond; si vous avez déplacé un sous-module et que git rmvous ne l' utilisez pas ensuite; Un test rapide avec 2.5.4 sur mon mac met à jour le fichier .gitmodules, comme décrit dans la documentation ici: git-scm.com/docs/git-rm#_submodules ... mais si vous avez trouvé une sorte de combinaison de plateforme / version où cela ne se produit pas, vous devriez probablement en corriger un bogue.
Doug
2
Cette réponse n'est pas entièrement correcte. git rmlaisse des trucs dans .git/modules/dir et .git/configfile (ubuntu, git 2.7.4). L'autre réponse fonctionne à 100%: stackoverflow.com/a/36593218/4973698
mbdevpl
50

Vous devez supprimer l'entrée dans .gitmoduleset .git/config, et supprimer le répertoire du module de l'historique:

git rm --cached path/to/submodule

Si vous écrivez sur la liste de diffusion de git, quelqu'un fera probablement un script shell pour vous.

Carmine Paolino
la source
Aucun script shell n'est nécessaire, une autre réponse contient des commandes pour supprimer toutes les traces d'un sous-module: stackoverflow.com/a/36593218/4973698
mbdevpl
42

Vous pouvez utiliser un alias pour automatiser les solutions fournies par d'autres:

[alias]
  rms = "!f(){ git rm --cached \"$1\";rm -r \"$1\";git config -f .gitmodules --remove-section \"submodule.$1\";git config -f .git/config --remove-section \"submodule.$1\";git add .gitmodules; }; f"

Mettez cela dans votre configuration git, et ensuite vous pouvez faire: git rms path/to/submodule

Charles
la source
-1 car c'est tout simplement trop faux. PREMIER: Cela suppose que le nom et le chemin du sous-module sont identiques, ce qui n'est le plus souvent pas le cas . IE git clone https://github.com/hilbix/empty.git; cd empty; git submodule add https://github.com/hilbix/empty.git one; git mv one two; git rms two. DEUXIÈME: Vous devez l'exécuter à partir du chemin correct. gitles alias doivent fonctionner n'importe où dans l'arborescence (ou échouer correctement). TROISIÈME: git config -f .git/configéchoue dans les sous-modules, comme c'est .gitgénéralement le cas là-bas.
Tino
42

Pour résumer, voici ce que vous devez faire:

  1. Définir path_to_submodulevar (pas de barre oblique de fin):

    path_to_submodule=path/to/submodule

  2. Supprimez la ligne appropriée du fichier .gitmodules:

    git config -f .gitmodules --remove-section submodule.$path_to_submodule

  3. Supprimez la section pertinente de .git / config

    git config -f .git/config --remove-section submodule.$path_to_submodule

  4. Décompresser et supprimer $ path_to_submodule uniquement de l'index (pour éviter de perdre des informations)

    git rm --cached $path_to_submodule

  5. Suivre les modifications apportées aux .gitmodules

    git add .gitmodules

  6. Validez le superprojet

    git commit -m "Remove submodule submodule_name"

  7. Supprimer les fichiers de sous-module désormais non suivis

    rm -rf $path_to_submodule

    rm -rf .git/modules/$path_to_submodule

luissquall
la source
donc tous ceux qui retirent ma modification devront exécuter rm -rf $ path_to_submodule rm -rf .git / modules / $ path_to_submodule pour supprimer le cache du sous-module?
j2emanue
Je recommande à mettre à jour git submodule update. Et si les chemins des sous-modules n'étaient pas mis à jour correctement (git lance une erreur), supprimez-les:rm -rf .git/modules/<submodule> && rm -rf <submodule> && git submodule update
luissquall
40

Si le sous-module a été accidentellement ajouté parce que vous avez ajouté, validé et poussé un dossier qui était déjà un référentiel Git (contenu .git), vous n'aurez pas de .gitmodulesfichier à modifier, ni quoi que ce soit dedans .git/config. Dans ce cas, il vous suffit de :

git rm --cached subfolder
git add subfolder
git commit -m "Enter message here"
git push

FWIW , j'ai également supprimé le .gitdossier avant de faire le git add.

Oli Studholme
la source
exactement mon cas
zhekaus
37

J'ai trouvé que les deinitœuvres me convenaient:

git submodule deinit <submodule-name>    
git rm <submodule-name>

De git docs :

deinit

Désenregistrez les sous-modules donnés, c'est-à-dire supprimez la submodule.$name section entière de .git / config avec leur arbre de travail.

Damjan Pavlica
la source
D'accord trouvé la même solution. C'est le meilleur moyen aujourd'hui en 2018)
woto
1
il n'a pas supprimé .git / modules / ... Vous devez les supprimer, voir la réponse de @fvgs
Vilém Kurz
Je ne sais pas pourquoi cette solution simple et facile n'est pas le numéro 1
Marc Magon
AFAICS cela semble être la réponse la plus sûre pour les nouveaux gits qui connaissent de deinit, comme l'autre réponse supprime le .git/modules/submodulerépertoire trop tôt, ce qui semble faire plus récent gits d'échouer maintenant ou alors. De plus (voir mon commentaire là-bas), la suppression .git/modules/submodulepeut être le mauvais chemin, c'est donc une étape dangereuse, à prendre plus tard uniquement lorsque gitvous vous plaignez (ou si vous êtes sûr à 299% que ce que vous voulez, est le bon chemin et vraiment nécessaire).
Tino
J'avais également besoin git commitde valider des changements par étapes dans dir: modified .gitmoduleset deleted <submodule-path>.
Yuriy Pozniak
20

Après avoir expérimenté toutes les différentes réponses sur ce site, je me suis retrouvé avec cette solution:

#!/bin/sh
path="$1"
if [ ! -f "$path/.git" ]; then
  echo "$path is no valid git submodule"
  exit 1
fi
git submodule deinit -f $path &&
git rm --cached $path &&
rm -rf .git/modules/$path &&
rm -rf $path &&
git reset HEAD .gitmodules &&
git config -f .gitmodules --remove-section submodule.$path

Cela restaure exactement le même état qu'avant l'ajout du sous-module. Vous pouvez tout de suite ajouter à nouveau le sous-module, ce qui n'était pas possible avec la plupart des réponses ici.

git submodule add $giturl test
aboveScript test

Cela vous laisse une caisse claire sans aucune modification à valider.

Cela a été testé avec:

$ git --version
git version 1.9.3 (Apple Git-50)
udondan
la source
Pourquoi utilisez-vous git rm --cached $pathalors rm -rf $pathau lieu de git rm -r $path?
bfontaine
-1 Ne fonctionne pas si vous essayez de supprimer un sous-module dans un sous-module (le sous-module peut former des arbres!). De plus, c'est dangereusement buggé en raison de l'absence de devis! Exemple git submodule add https://github.com/hilbix/empty.git 'dangerous .. submodule'-> lorsque vous essayez de supprimer «dangereux .. sous-module» avec votre script, cette volonté rm -rf ..n'est probablement pas ce que vous voulez ..
Tino
17

Ce que je fais actuellement en décembre 2012 (combine la plupart de ces réponses):

oldPath="vendor/example"
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 src (optional)
rm -rf ".git/modules/${oldPath}" ## cleanup gitdir (optional housekeeping)
git add .gitmodules
git commit -m "Removed ${oldPath}"
Lance Rushing
la source
15

Voici ce que j'ai fait :

1.) Supprimez la section appropriée du fichier .gitmodules. Vous pouvez utiliser la commande ci-dessous:

git config -f .gitmodules --remove-section "submodule.submodule_name"

2.) Mettre en scène les .gitmoduleschangements

git add .gitmodules

3.) Supprimer la section pertinente de .git/config. Vous pouvez utiliser la commande ci-dessous:

git submodule deinit -f "submodule_name"

4.) Retirez le gitlink (pas de barre oblique de fin):

git rm --cached path_to_submodule

5.) Nettoyez .git/modules:

rm -rf .git/modules/path_to_submodule

6.) S'engager:

git commit -m "Removed submodule <name>"

7.) Supprimez les fichiers de sous-module non suivis

rm -rf path_to_submodule
Ishan Liyanage
la source
Merci pour cela. Pour moi, j'ai dû réorganiser l'ordre des trois premières étapes en 3), 1), 2). Faire 1) a d'abord donné fatal: no submodule mapping found in .gitmodules for path 'submodule_name'à l'étape 3. Les deux étapes étaient cependant nécessaires. (git v2.8.2)
U007D
13

J'ai récemment découvert un projet git qui inclut de nombreuses commandes utiles liées à git: https://github.com/visionmedia/git-extras

Installez-le et tapez:

git-delete-submodule submodule

Ensuite, les choses se font. Le répertoire du sous-module sera supprimé de votre référentiel et existera toujours dans votre système de fichiers. Vous pouvez alors engager le changement comme: git commit -am "Remove the submodule".

Chien-Wei Huang
la source
Vous pouvez appeler cela comme git delete-submodule, car il git-extrasdoit être sur le chemin du travail. Notez également que je recommande de ne pas l'utilisergit-extras , car de nombreuses parties sont extrêmement buggées et dangereuses . IE git-delete-submodulesupprime éventuellement le mauvais chemin ci .git/modules/*- dessous , car il suppose que le module et le chemin sont identiques (ce qui n'est souvent pas le cas), et cela ne fonctionne pas correctement si vous essayez de supprimer un sous-module dans un sous-module. git-extraspeut être utile à 99%, mais ne vous plaignez pas si les choses tournent mal en l'utilisant. TU ÉTAIS PRÉVENU!
Tino
10

J'ai dû prendre les étapes de John Douthat un peu plus loin et cddans le répertoire du sous-module, puis supprimer le référentiel Git:

cd submodule
rm -fr .git

Ensuite, je pouvais valider les fichiers en tant que partie du référentiel Git parent sans l'ancienne référence à un sous-module.

Kyle Clegg
la source
J'ai dû le faire aussi pour éviter une erreur "fatale: pas un dépôt git:" lors de la tentative git rm --cache.
RickDT
9

Voici les 4 étapes que j'ai trouvées nécessaires ou utiles (les plus importantes en premier):

git rm -f the_submodule
rm -rf .git/modules/the_submodule
git config -f .git/config --remove-section submodule.the_submodule
git commit -m "..."

En théorie , git rmà l' étape 1, il faut s'en occuper. Espérons que la deuxième partie de la question OP puisse recevoir une réponse positive un jour (que cela puisse être fait en une seule commande).

Mais à partir de juillet 2017, l' étape 2 est nécessaire pour supprimer les données .git/modules/, sinon vous ne pouvez pas par exemple ajouter le sous-module à l'avenir.

Vous pouvez probablement vous en sortir avec les deux étapes ci-dessus pour git 1.8.5+ comme l'a noté la réponse de tinlyx , car toutes les git submodulecommandes semblent fonctionner.

L'étape 3 supprime la section pour the_submoduledans le fichier .git/config. Cela devrait être fait pour être complet. (L'entrée peut causer des problèmes pour les anciennes versions de git, mais je n'en ai pas à tester).

Pour cela, la plupart des réponses suggèrent d'utiliser git submodule deinit. Je le trouve plus explicite et moins déroutant à utiliser git config -f .git/config --remove-section. Selon la documentation git-sous - module , git deinit:

Annuler l'enregistrement des sous-modules donnés ... Si vous voulez vraiment supprimer un sous-module du référentiel et valider, utilisez plutôt git-rm [1] .

Dernier point mais non le moindre, si vous ne le faites pas git commit, vous obtiendrez / risquez d'obtenir une erreur en faisant git submodule summary(à partir de git 2.7):

fatal: Not a git repository: 'the_submodule/.git'
* the_submodule 73f0d1d...0000000:

Cela indépendamment du fait que vous effectuez les étapes 2 ou 3.

laser
la source
7
project dir:     ~/foo_project/
submodule:       ~/foo_project/lib/asubmodule
- - - - - - - - - - - - - - - - - - - - - - - - -
run:
  1.   cd ~/foo_project
  2.   git rm lib/asubmodule && 
          rm .git/modules/lib/asubmodule && 
            git submodule lib/asubmodule deinit --recursive --force

la source
7

Je viens de trouver le fichier caché .submodule (nom exact oublié), il a une liste ... vous pouvez les effacer individuellement de cette façon. Je viens d'en avoir un, donc je l'ai supprimé. C'est simple, mais ça pourrait gâcher Git, car je ne sais pas si quelque chose est attaché au sous-module. Semble correct jusqu'à présent, à part le problème de mise à niveau habituel de libetpan, mais ce n'est (espérons-le) pas lié.

Personne n'a remarqué d'effacement manuel, donc ajouté

Stephen J
la source
C'est.gitmodules
Arialdo Martini le
7

Avec git 2.17 et supérieur, c'est juste:

git submodule deinit -f {module_name}
git add {module_name}
git commit
Albert Tobac
la source
N'a pas fonctionné, ni pour git 2.17.1ni git 2.20.1. Cependant en utilisant git rmau lieu de git addtravaillé pour les deux. Remarques: -fn'est pas nécessaire si les choses sont propres. Assurez-vous de ne jamais utiliser d'options avec gitsi vous souhaitez vous protéger contre la perte de données involontaire. Notez également que cela laisse .git/modules/{module_name}en place. Il est préférable de le conserver car ilgit imprime l'aide (!) Correcte sur la façon de procéder si quelque chose est bloqué pour cette raison.
Tino
4

Si vous venez d'ajouter le sous-module, et par exemple, vous avez simplement ajouté le mauvais sous-module ou vous l'avez ajouté au mauvais endroit, git stashsupprimez simplement le dossier. Cela suppose que l'ajout du sous-module est la seule chose que vous avez faite dans le dépôt récent.

botbot
la source
3

Pour le bénéfice du lecteur, ceci ici essaie de le résumer et de donner un guide étape par étape sur la façon de le faire si les choses ne fonctionnent pas comme prévu. Voici la manière testée et sûre pour les gitversions 2.17et supérieures de se débarrasser d'un sous-module :

submodule="path/to/sub"              # no trailing slash!
git submodule deinit -- "$submodule"
git rm -- "$submodule"
  • Si cela ne fonctionne pas pour vous, voir ci-dessous.
  • Aucune option. Rien de dangereux. Et n'envisagez même pas d'en faire plus!
  • Testé avec Debian Buster 2.20.1et Ubuntu 18.04 2.17.1.
  • "$submodule" est juste de souligner où mettre le nom, et que vous devez faire attention aux espaces et autres
  • Si sous Windows, ignorez la première ligne et remplacez "$submodule"par la méthode Windows d'un chemin d'accès correctement spécifié au sous-module. (Je ne suis pas Windows)

Attention!

Ne touchez jamais vous-même l'intérieur du .gitrépertoire! Le montage à l'intérieur .gitentre dans le côté obscur. Restez à l'écart à tout prix!

Et oui, vous pouvez en être responsable git, car il manquait beaucoup de choses pratiques gitdans le passé. Comme une bonne façon de retirer à nouveau les sous-modules.

Je pense qu'il y a une partie très dangereuse dans la documentation de git submodule. Il recommande de $GIT_DIR/modules/<name>/vous retirer . À ma connaissance, ce n'est pas seulement faux, c'est extrêmement dangereux et provoque des maux de tête majeurs à l'avenir! Voir ci-dessous.

Notez que

git module deinit

est l'inverse direct de

git module init

mais

git submodule deinit -- module
git rm -- module

est également tout à fait l'inverse de

git submodule add -- URL module
git submodule update --init --recursive -- module

parce que certaines commandes doivent faire plus que juste une seule chose:

  • git submodule deinit -- module
    • (1) mises à jour .git/config
  • git rm
    • (2) supprime les fichiers du module
    • (3) supprime ainsi récursivement les sous-modules du sous-module
    • (4) mises à jour .gitmodules
  • git submodule add
    • tire dans les données .git/modules/NAME/
    • (1) le fait git submodule init, donc les mises à jour.git/config
    • (2) vérifie de git submodule updatefaçon non récursive le module
    • (4) mises à jour .gitmodules
  • git submodule update --init --recursive -- module
    • extrait d'autres données si nécessaire
    • (3) vérifie récursivement les sous-modules du sous-module

Cela ne peut pas être entièrement symétrique, car le garder strictement symétrique n'a pas beaucoup de sens. Il n'y a tout simplement pas besoin de plus de deux commandes. «Extraire les données» est également implicite, car vous en avez besoin, mais la suppression des informations mises en cache n'est pas effectuée, car cela n'est pas du tout nécessaire et pourrait effacer des données précieuses.

C'est vraiment déroutant pour les nouveaux arrivants, mais c'est fondamentalement une bonne chose: fait gitsimplement ce qui est évident et le fait correctement, et n'essaie même pas d'en faire plus. gitest un outil qui doit faire un travail fiable, au lieu d'être juste un autre "Eierlegende Wollmilchsau" ("Eierlegende Wollmilchsau" se traduit pour moi par "une version maléfique d'un couteau suisse").

Je comprends donc les plaintes des gens, en disant "Pourquoi ne fait-il pas gitla chose évidente pour moi". En effet, «évident» dépend ici du point de vue. La fiabilité dans chaque situation est beaucoup plus importante. Par conséquent, ce qui est évident pour vous souvent n'est pas la bonne chose dans toutes les situations techniques possibles. N'oubliez pas que: l'AFAICS gitsuit la voie technique, pas la voie sociale. (D'où le nom intelligent: git)

Si cela échoue

Les commandes ci-dessus peuvent échouer en raison des éléments suivants:

  • Tu gites trop vieux. Utilisez ensuite un nouveau git. (Voir ci-dessous comment.)
  • Vous avez des données non validées et risquez de perdre des données. Mieux vaut ensuite les engager en premier.
  • Votre sous-module n'est pas propre dans un git cleansens. Ensuite, nettoyez d'abord votre sous-module à l'aide de cette commande. (Voir ci-dessous.)
  • Vous avez fait quelque chose dans le passé qui n'est pas soutenu par git. Ensuite, vous êtes du côté obscur et les choses deviennent laides et compliquées. (Peut-être que l'utilisation d'une autre machine le corrige.)
  • Il y a peut-être plus de façons d'échouer que je ne connais pas (je suis juste un grand gitutilisateur).

Les correctifs possibles suivent.

Utilisez un nouveau git

Si votre machine est trop vieille, il n'y submodule deiniten a pas git. Si vous ne voulez pas (ou pouvez) mettre à jour votre git, alors utilisez simplement une autre machine avec une plus récente git! gitest censé être entièrement distribué, vous pouvez donc en utiliser un autre gitpour faire le travail:

  • workhorse:~/path/to/worktree$ git status --porcelain ne doit rien sortir! Si c'est le cas, nettoyez d'abord les choses!
  • workhorse:~/path/to/worktree$ ssh account@othermachine
  • othermachine:~$ git clone --recursive me@workhorse path/to/worktree/.git TMPWORK && cd TMPWORK
  • Maintenant, fais le sous-module
  • othermachine:~/TMPWORK$ git commit . -m . && exit
  • workhorse:~/path/to/worktree$ git fetch account@othermachine:TMPWORK/.git
  • workhorse:~/path/to/worktree$ git merge --ff-only FETCH_HEAD. Si cela ne fonctionne pas, utilisezgit reset --soft FETCH_HEAD
  • Maintenant, git statusnettoyez les choses, jusqu'à ce que ce soit à nouveau propre. Vous pouvez le faire, car vous l'avez déjà fait nettoyer, grâce à la première étape.

Cela othermachinepeut être une machine virtuelle ou un WSL Ubuntu sous Windows, peu importe. Même un chroot(mais je suppose que vous n'êtes pas root, car si vous l'êtes, rootil devrait être plus facile de mettre à jour vers le plus récent git).

Notez que si vous ne pouvez pas sshentrer, il existe de nombreuses façons de transporter les gitréférentiels. Vous pouvez copier votre arbre de travail sur une clé USB (y compris le .gitrépertoire) et cloner à partir de la clé. Clonez la copie, juste pour remettre les choses en ordre. Il peut s'agir d'un PITA, au cas où vos sous-modules ne seraient pas directement accessibles depuis une autre machine. Mais il existe également une solution:

git config --add url.NEWURLPREFIX.insteadOf ORIGINALURLPREFIX

Vous pouvez utiliser cette multiplication et celle-ci est enregistrée dans $HOME/.gitconfig. Quelque chose comme

git config --add 'url./mnt/usb/repo/.insteadof' https://github.com/

réécrit les URL comme

https://github.com/XXX/YYY.git

dans

/mnt/usb/repo/XXX/YYY.git

C'est facile si vous commencez à vous habituer à des gitfonctionnalités puissantes comme celle-ci.

Nettoyer les choses d'abord

Le nettoyage manuel est bon, car de cette façon, vous pouvez peut-être détecter certaines choses que vous avez oubliées.

  • Si git se plaint de choses non enregistrées, validez et poussez-le dans un endroit sûr.
  • Si git se plaint de quelques restes git statuset git clean -ixfdest votre ami
  • Essayez de vous abstenir rmet deinitaussi longtemps que vous le pouvez. Les options (comme -f) gitsont bonnes si vous êtes un pro. Mais comme vous êtes venu ici, vous n'êtes probablement pas aussi expérimenté dans la submodulerégion. Il vaut donc mieux être en sécurité que désolé.

Exemple:

$ git status --porcelain
 M two
$ git submodule deinit two
error: the following file has local modifications:
    two
(use --cached to keep the file, or -f to force removal)
fatal: Submodule work tree 'two' contains local modifications; use '-f' to discard them
$ cd two
$ git submodule deinit --all
error: the following file has local modifications:
    md5chk
(use --cached to keep the file, or -f to force removal)
fatal: Submodule work tree 'md5chk' contains local modifications; use '-f' to discard them
$ cd md5chk
$ git submodule deinit --all
error: the following file has local modifications:
    tino
(use --cached to keep the file, or -f to force removal)
fatal: Submodule work tree 'tino' contains local modifications; use '-f' to discard them
$ cd tino
$ git status --porcelain
?? NEW
$ git clean -i -f -d
Would remove the following item:
  NEW
*** Commands ***
    1: clean                2: filter by pattern    3: select by numbers    4: ask each
    5: quit                 6: help
What now> 1
Removing NEW
$ cd ../../..
$ git status --porcelain
$ git submodule deinit two
Cleared directory 'two'
Submodule 'someunusedname' (https://github.com/hilbix/src.git) unregistered for path 'two'

Vous voyez, il n'y en a pas -fbesoin submodule deinit. Si les choses sont propres, dans un git cleansens. Notez également que ce git clean -xn'est pas nécessaire. Cela signifie qu'il git submodule deinitsupprime inconditionnellement les fichiers non suivis qui sont ignorés. C'est généralement ce que vous voulez, mais n'oubliez pas. Parfois, les fichiers ignorés peuvent être précieux, comme les données mises en cache qui nécessitent des heures ou des jours pour être calculées à nouveau.

Pourquoi ne jamais retirer $GIT_DIR/modules/<name>/?

Les gens veulent probablement supprimer le référentiel mis en cache, car ils ont peur de rencontrer un problème plus tard. C'est vrai, mais rencontrer ce «problème» est la bonne façon de le résoudre! Parce que la correction est facile et bien faite, vous pourrez vivre heureux pour toujours. Cela évite des problèmes plus encombrants que lorsque vous supprimez les données vous-même.

Exemple:

mkdir tmptest &&
cd tmptest &&
git init &&
git submodule add https://github.com/hilbix/empty.git two &&
git commit -m . &&
git submodule deinit two &&
git rm two &&
git commit -m . &&
git submodule add https://github.com/hilbix/src.git two

La dernière ligne génère l'erreur suivante:

A git directory for 'two' is found locally with remote(s):
  origin    https://github.com/hilbix/empty.git
If you want to reuse this local git directory instead of cloning again from
  https://github.com/hilbix/src.git
use the '--force' option. If the local git directory is not the correct repo
or you are unsure what this means choose another name with the '--name' option.

Pourquoi cette erreur? Parce que .git/modules/two/précédemment a été rempli à partir de https://github.com/hilbix/empty.git et doit maintenant être re-rempli à partir d'autre chose, à savoir https://github.com/hilbix/src.git . Vous ne le verrez pas si vous le re-remplissez depuis https://github.com/hilbix/empty.git

Que faire maintenant? Eh bien, faites exactement ce qui vous a été dit! Utilisation--name someunusedname

git submodule add --name someunusedname https://github.com/hilbix/src.git two

.gitmodules ressemble alors

[submodule "someunusedname"]
    path = two
    url = https://github.com/hilbix/src.git

ls -1p .git/modules/ donne

someunusedname/
two/

De cette façon, à l'avenir, vous pouvez changer de branche / valider en avant et en arrière et ne plus jamais avoir de problème , car vous aveztwo/ deux référentiels en amont différents (et éventuellement incompatibles). Et le meilleur est: vous conservez également les deux en cache localement.

  • Ce n'est pas seulement vrai pour vous. Cela est également vrai pour tous les autres utilisateurs de votre référentiel.
  • Et vous ne perdez pas l'histoire. Dans le cas où vous avez oublié de pousser la toute dernière version de l'ancien sous-module, vous pouvez entrer la copie locale et le faire plus tard. Notez qu'il est assez courant que quelqu'un oublie de pousser certains sous-modules (car il s'agit d'un PITA pour les nouveaux arrivants, jusqu'à ce qu'ils s'y habituent git).

Cependant, si vous avez supprimé le répertoire mis en cache, les deux extractions différentes tomberont l'une sur l'autre, car vous n'utiliserez pas les --nameoptions, non? Ainsi, chaque fois que vous effectuez le paiement, vous devrez peut-être supprimer le .git/modules/<module>/répertoire encore et encore. Ceci est extrêmement lourd et rend difficile l'utilisation de quelque chose comme git bisect.

Il y a donc une raison très technique de conserver ce répertoire de module comme espace réservé. Les personnes qui recommandent de supprimer quelque chose ci-dessous .git/modules/ne savent pas mieux ou oublient de vous dire que cela rend les fonctionnalités puissantes comme git bisectpresque impossible à utiliser si cela croise une telle incompatibilité de sous-module.

Une autre raison est indiquée ci-dessus. Regardez le ls. Que voyez-vous là?

Eh bien, la 2ème variante de module two/n'est pas en dessous .git/modules/two/, elle est en dessous .git/modules/someunusedname/! Donc, des choses comme ça git rm $module; rm -f .git/module/$modulesont totalement fausses! Vous devez soit consulter, module/.gitsoit .gitmodulestrouver la bonne chose à supprimer!

Donc, non seulement la plupart des autres réponses tombent dans ce piège dangereux, même les gitextensions très populaires avaient ce bug ( il est maintenant corrigé là-bas )! Il vaut donc mieux garder les mains du .git/répertoire si vous ne le faites pas exactement, ce que vous faites!

Et du point de vue philosophique, essuyer l'histoire est toujours faux! Sauf pour la mécanique quantique , comme d'habitude, mais c'est quelque chose de complètement différent.

Pour info vous l'avez probablement deviné: hilbix est mon compte GitHub.

Tino
la source
Cette encyclopédie d'un article doit être divisée en sections plus claires avec des sous-titres plus grands / plus clairs pour indiquer la réponse réelle, et les différentes sections de "dépannage" / etc.
Andrew
2

Pour résumer, voici ce que vous devez faire:

Définissez path_to_submodule var (pas de barre oblique de fin):

path_to_submodule=path/to/submodule

Supprimez la ligne appropriée du fichier .gitmodules:

git config -f .gitmodules --remove-section submodule.$path_to_submodule

Supprimez la section pertinente de .git / config

git config -f .git/config --remove-section submodule.$path_to_submodule

Décompresser et supprimer $ path_to_submodule uniquement de l'index (pour éviter de perdre des informations)

git rm --cached $path_to_submodule

Suivre les modifications apportées aux .gitmodules

git add .gitmodules

Validez le superprojet

git commit -m "Remove submodule submodule_name"

Supprimer les fichiers de sous-module désormais non suivis

rm -rf $path_to_submodule

rm -rf .git/modules/$path_to_submodule

Voir aussi: Lignes directrices alternatives

Rahul Dapke
la source
Pouvez-vous s'il vous plaît étendre cela avec la façon de supprimer un sous-module après un «ajout de sous-module git» mais sans l'avoir jamais validé? Je suppose que dans ce cas, aucun commit n'est nécessaire pour supprimer le sous-module, non?
Carlo Wood
Je pense que vous devez échanger le git rm --cached $path_to_submoduleet git add .gitmodulesnon? J'ai eu une erreur sur la première commande: fatal: Please stage your changes to .gitmodules or stash them to proceedparce que j'avais apporté des modifications non programmées à .gitmodules. Faire le git add .gitmodulespremier résout cela.
Carlo Wood
2

C'est facile:

  1. Supprimer la section de .gitmodules
  2. Appel: git add .gitmodules
  3. Appel: git submodule deinit <path to submodule>
  4. Appel: git rm <path to submodule>
  5. Valider et pousser

Vous devrez supprimer manuellement les fichiers de module de votre projet.

Noir
la source
2
Pour moi, il suffisait d'appeler git submodule deinit <submodule_name>et git rm <path_to_submodule>. La dernière commande supprime automatiquement l'entrée à l'intérieur du .gitmodules. Git 2.17
Dmytro Ovdiienko
1

J'ai créé un script bash pour faciliter le processus de suppression. Il vérifie également s'il y a des changements dans le dépôt non enregistrés et demande une confirmation. Il a été testé sur os xserait intéressant de savoir si cela fonctionne également sur les distributions Linux courantes:

https://gist.github.com/fabifrank/cdc7e67fd194333760b060835ac0172f

Techradar
la source
0

Dans le dernier git, seulement 4 opérations sont nécessaires pour retirer le sous-module git.

  • Supprimer l'entrée correspondante dans .gitmodules
  • Changements d'étape git add .gitmodules
  • Supprimer le répertoire du sous-module git rm --cached <path_to_submodule>
  • Engagez-le git commit -m "Removed submodule xxx"
rashok
la source
0

Dans le cas où vous devez le faire en une seule ligne de commande avec le script bash comme ci-dessous:

$ cd /path/to/your/repo && /bin/bash $HOME/remove_submodule.sh /path/to/the/submodule

Créez un fichier de script bash dans le répertoire $HOMEnommé ie remove_submodule.sh:

#!/bin/bash

git config -f .gitmodules --remove-section submodule.$1
git config -f .git/config --remove-section submodule.$1
git rm --cached $1
git add .gitmodules
git commit -m "Remove submodule in $1"
rm -rf $1
rm -rf .git/modules/$1
git push origin $(git rev-parse --abbrev-ref HEAD) --force --quiet

Chetabahana
la source
0
  • Un sous-module peut être supprimé en exécutant git rm <submodule path> && git commit. Cela peut être annulé en utilisant git revert.
    • La suppression supprime les données de suivi du superprojet, qui sont à la fois l'entrée gitlink et la section du .gitmodulesfichier.
    • Le répertoire de travail du sous-module est supprimé du système de fichiers, mais le répertoire Git est conservé car il permet de récupérer les validations passées sans nécessiter la récupération à partir d'un autre référentiel.
  • Pour supprimer complètement un sous-module, supprimez également manuellement$GIT_DIR/modules/<name>/ .

La source: git help submodules

Nikhil
la source
-1

Suppression du sous-module Git

Pour supprimer un gitsous-module en dessous de 4 étapes sont nécessaires.

  1. Supprimez l'entrée correspondante dans le .gitmodulesfichier. L'entrée peut être comme mentionnée ci-dessous
[submodule "path_to_submodule"]
    path = path_to_submodule
    url = url_path_to_submodule
  1. Changements d'étape git add .gitmodules
  2. Supprimez le répertoire du sous-module git rm --cached <path_to_submodule>.
  3. Engagez-le git commit -m "Removed submodule xxx"et poussez.

2 étapes supplémentaires mentionnées ci-dessous sont nécessaires pour nettoyer complètement le sous-module dans la copie clonée locale.

  1. Supprimez l'entrée correspondante dans le .git/configfichier. L'entrée peut être comme mentionnée ci-dessous
[submodule "path_to_submodule"]
    url = url_path_to_submodule
  1. Faire rm -rf .git/modules/path_to_submodule

Ces 5e et 6e étapes ne créent aucun changement qui doit être validé.

rashok
la source
Ce serait beaucoup plus facile si vous git submodule deinit utilisiez git-scm.com/docs/git-submodule#Documentation/…
Black