Come rimuovo un sottomodulo?


3539

Come rimuovo un sottomodulo Git?

A proposito, c'è un motivo che non posso semplicemente fare git submodule rm whatever?


109
La semplice risposta stackoverflow.com/a/21211232/94687 è ora quella corretta e deve essere contrassegnata come tale. Ora, è semplicemente git rm modulenameerm -rf .git/modules/modulename
imz - Ivan Zakharyaschev il

10
In realtà non è vero. Tale risposta non riguarda la rimozione della voce del sottomodulo da .git/config. La risposta accettata mostra il modo aggiornato per rimuovere completamente un sottomodulo. E 'anche spiegato più succintamente in questa risposta: stackoverflow.com/a/36593218/1562138
fvgs

Ho trovato questo articolo molto utile nella rimozione dei sottomoduli. Esso include informazioni sulla rimozione di voci nei .gitsubmodules e .git / file di configurazione dei collegamenti
Ri_

12
Per favore, risparmiati un po 'di tempo e vai direttamente alla risposta che funziona (nel 2017): stackoverflow.com/a/36593218/528313
Vincenzo Pii,

Ho lottato con i problemi del sottomodulo per due giorni. La svolta è arrivata quando ho trovato questo: forum.developer.apple.com/thread/13102 . Fondamentalmente, Xcode e forse altre app, fanno fatica ad espandere l'URL contenente '~'. Dopo aver cambiato ssh: //username@server.remoteHost.com/~/git/MyRepo.git in ssh: //username@server.remoteHost.com/home/username/git/MyRepo.git (cercare il percorso effettivo sul tuo server), tutta la stranezza è scomparsa con dieci minuti. Vedere anche stackoverflow.com/questions/32833100/...
Elise van Looij

Risposte:


2216

Da git1.8.3 (22 aprile 2013) :

Non c'era modo di porcellana di dire "Non sono più interessato a questo sottomodulo", una volta che esprimi il tuo interesse per un sottomodulo con " submodule init".
" submodule deinit" è il modo di farlo.

Anche il processo di eliminazione utilizza git rm(da git1.8.5 ottobre 2013).

Sommario

Il processo di rimozione in 3 passaggi sarebbe quindi:

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

Spiegazione

rm -rf: Questo è menzionato nel Daniel Schroeder 's risposta , e riassunto da Eonil nei commenti :

Questo lascia .git/modules/<path-to-submodule>/invariato.
Pertanto, se si elimina una volta un sottomodulo con questo metodo e si aggiunge di nuovo, non sarà possibile perché il repository è già stato danneggiato.


git rm: Vedi commit 95c16418 :

Attualmente l'utilizzo di " git rm" su un sottomodulo rimuove l'albero di lavoro del sottomodulo da quello del superprogetto e il gitlink dall'indice.
Ma la sezione del sottomodulo in .gitmodulesrimane invariata, che è un residuo del sottomodulo ora rimosso e potrebbe irritare gli utenti (al contrario dell'impostazione in .git/config, questo deve rimanere come promemoria che l'utente ha mostrato interesse per questo sottomodulo, quindi verrà ripopolato in seguito quando viene eseguito il checkout di un commit precedente).

Lascia che " git rm" aiuti l'utente non solo rimuovendo il sottomodulo dall'albero di lavoro, ma anche rimuovendo la submodule.<submodule name>sezione " " dal .gitmodulesfile e mettendo in scena entrambi.


git submodule deinit: Deriva da questa patch :

Con " git submodule init" l'utente è in grado di dire a Git che ha a cuore uno o più sottomoduli e vuole farlo popolare alla prossima chiamata a " git submodule update".
Ma al momento non esiste un modo semplice per dire a Git che non si preoccupano più di un sottomodulo e vogliono sbarazzarsi dell'albero di lavoro locale (a meno che l'utente non sappia molto degli interni del sottomodulo e rimuova l' submodule.$name.urlimpostazione " " .git/configinsieme al lavoro albero stesso).

Aiuta quegli utenti fornendo un deinitcomando ' '.
Questo rimuove l'intera submodule.<name>sezione .git/configo per il / i sottomodulo / i (o per tutti quelli che sono stati inizializzati se ' .' è dato).
Fallire se l'albero di lavoro corrente contiene modifiche se non forzate.
Lamentarsi quando per un sottomodulo fornito sulla riga di comando non è possibile trovare l'impostazione dell'URL .git/config, ma non fallire.

Questo si prende cura se le (de) fasi di inizializzazione ( .git/confige .git/modules/xxx)

Da git1.8.5, git rmsi occupa anche di:

  • ' add' passaggio che registra l'URL di un sottomodulo nel .gitmodulesfile: deve essere rimosso per te.
  • la voce speciale del sottomodulo (come illustrato da questa domanda ): git rm la rimuove dall'indice:
    git rm --cached path_to_submodule(nessuna barra finale)
    Rimuoverà quella directory memorizzata nell'indice con una modalità speciale "160000", contrassegnandola come directory root del sottomodulo .

Se si dimentica l'ultimo passaggio e si tenta di aggiungere quello che era un sottomodulo come directory normale, si otterrebbe un messaggio di errore del tipo:

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

Nota: da Git 2.17 (Q2 2018), git submodule deinit non è più uno script di shell.
È una chiamata a una funzione C.

Vedi commit 2e61273 , commit 1342476 (14 gennaio 2018) di Prathamesh Chavan ( pratham-pc) .
(Unito da Junio ​​C Hamano - gitster- in commit ead8dbe , 13 feb 2018)

git ${wt_prefix:+-C "$wt_prefix"} submodule--helper deinit \
  ${GIT_QUIET:+--quiet} \
  ${prefix:+--prefix "$prefix"} \
  ${force:+--force} \
  ${deinit_all:+--all} "$@"

18
Puoi darci un esempio di utilizzo per submodule deinit?
zakdances,

5
@yourfriendzak qui è un esempio di qualcuno che lo utilizza con successo: stackoverflow.com/a/16161950/6309 . Ma tieni presente che, contrariamente a quanto credevo inizialmente, 1.8.3 non è ancora stato rilasciato! Su Unix, puoi compilarlo dai sorgenti.
VonC,

2
@HamishDowner la voce speciale dovrebbe essere scomparsa (la directory non è più un sottomodulo) e .gitmodulesdovrebbe essere ok, ma vorrei comunque ricontrollare qualsiasi cosa con la .gitdirectory (cioè la configurazione locale , all'interno del tuo repository locale: non è modificato da a git pull)
VonC

2
@Jayen sì, se si commette la rimozione della .gitmodulesvoce e la rimozione della voce speciale nell'indice e si spinge quel repository, gli altri possono estrarlo e quel sottomodulo sparirà.
VonC

3
Nell'attuale git (v1.9 +), semplicemente vecchio git rm submodulefa esattamente quello che vuoi come hanno già detto altre persone.
Pete Peterson,

3445

Tramite la pagina Git Submodule Tutorial :

Per rimuovere un sottomodulo è necessario:

  1. Elimina la sezione pertinente dal .gitmodulesfile.
  2. Metti in scena i .gitmodulescambiamenti:
    git add .gitmodules
  3. Elimina la sezione pertinente da .git/config.
  4. Rimuovere i file del sottomodulo dall'albero di lavoro e dall'indice:
    git rm --cached path_to_submodule(nessuna barra finale).
  5. Rimuovere la .gitdirectory del sottomodulo :
    rm -rf .git/modules/path_to_submodule
  6. Conferma le modifiche:
    git commit -m "Removed submodule <name>"
  7. Elimina i file del sottomodulo ora non tracciati:
    rm -rf path_to_submodule

Vedi anche : passaggi alternativi di seguito .


410
"E comunque, c'è un motivo per cui non riesco semplicemente a inviare sottomodulo rm qualunque?" ?
abernier,

48
@abernier Una risposta brusca potrebbe essere "perché non esiste tale comando". La mia ipotesi è che stanno cercando di rendere esplicita la rimozione dei file del sottomodulo rispetto alla configurazione del sottomodulo per evitare la perdita accidentale dei dati. Forse una persona penserebbe che git submodule rmrimuova semplicemente la registrazione del sottomodulo e sarebbe sorpresa se il comando cancellasse anche il repository locale. Eventuali modifiche locali sarebbero irrimediabilmente perse. E forse un'altra persona penserebbe che verranno rimossi solo i file.
John Douthat,

119
Francamente, non so perché. Spero che aggiungano un comando, però. Questi 4 passaggi sono troppo complicati.
John Douthat,

25
Ecco uno script bash che rimuove un sottomodulo, basta creare un alias git per submodule-rm;) gist.github.com/2491147
Capi Etheriel

33
serve anche rm -rf .git \ modules \ nome del sottomodulo?
rogerdpack,

484

Solo una nota. Da git 1.8.5.2, due comandi eseguiranno:

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

Come sottolineato correttamente dalla risposta di @Mark Cheverton, se la seconda riga non viene utilizzata, anche se per ora hai rimosso il sottomodulo, la cartella rimanente .git / modules / the_submodule impedirà che lo stesso sottomodulo venga aggiunto o sostituito in futuro . Inoltre, come accennato da @VonC, git rmfarà la maggior parte del lavoro su un sottomodulo.

- Aggiornamento (07/05/2017) -

Giusto per chiarire, the_submoduleè il percorso relativo del sottomodulo all'interno del progetto. Ad esempio, è subdir/my_submodulese il sottomodulo si trova all'interno di una sottodirectory subdir.

Come sottolineato correttamente nei commenti e nelle altre risposte , i due comandi (sebbene funzionalmente sufficienti per rimuovere un sottomodulo), lasciano una traccia nella [submodule "the_submodule"]sezione di .git/config(a partire da luglio 2017), che può essere rimossa usando un terzo comando:

git config -f .git/config --remove-section submodule.the_submodule 2> /dev/null

5
Sono su git versione 2.4.9 (Apple Git-60) e tutto ciò che dovevo fare era rm the_submodule. Ho spinto che poi ho aggiunto nuovamente una cartella denominata uguale al sottomodulo e ha funzionato senza problemi.
David Silva Smith,

19
Ciò non rimuove la voce del sottomodulo da .git/config. Vedere stackoverflow.com/a/36593218/1562138 per il modo completo di rimuovere un sottomodulo.
fvgs

2
@drevicko Ho appena provato questo con Git 2.11.1 e osservo lo stesso comportamento di prima. git init && git submodule add <repository> && git rm <name>lascia dietro la .git/configvoce e la .git/modules/<name>directory e il suo contenuto. Forse non hai inizializzato il sottomodulo prima di rimuoverlo?
fvgs

2
mi sento più sicuro correndo questo primo .. git submodule deinit -f the_submodule
danday74

1
@JarrodSmith Sì, è il percorso. si prega di consultare l'aggiornamento.
Tinlyx,

478

La maggior parte delle risposte a questa domanda sono obsolete, incomplete o inutilmente complesse.

Un sottomodulo clonato usando git 1.7.8 o successivi lascerà al massimo quattro tracce di se stesso nel repository locale. Il processo per rimuovere queste quattro tracce è dato dai tre comandi seguenti:

# 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

39
Perché questa risposta ha così pochi voti? Tutte quelle risposte popolari mancano qualcosa, questa è l'unica che rimuove davvero tutte le tracce di un sottomodulo, nel modo più semplice possibile. E nota: l'ordine dei comandi è importante.
mbdevpl,


5
@mbdevpl è arrivato 3 anni dopo la risposta accettata, e immagino che nessuno sia riuscito a convincere il PO ad accettarlo
Andy,

10
QUESTA è la risposta non complicata nel 2018?
Warren P

9
il file .gitmodules sembra ancora inalterato eseguendo questi comandi
Fractalf

206

Semplici passaggi

  1. Rimuovi voci di configurazione:
    git config -f .git/config --remove-section submodule.$submodulename
    git config -f .gitmodules --remove-section submodule.$submodulename
  2. Rimuovi directory dall'indice:
    git rm --cached $submodulepath
  3. Commettere
  4. Elimina file non utilizzati:
    rm -rf $submodulepath
    rm -rf .git/modules/$submodulename

Nota: $submodulepath non contiene barre iniziali o finali.

sfondo

Quando lo fai git submodule add , lo aggiunge solo a .gitmodules, ma una volta fatto git submodule init, lo ha aggiunto .git/config.

Quindi, se si desidera rimuovere i moduli, ma essere in grado di ripristinarlo rapidamente, fare proprio questo:

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

È una buona idea fare git rebase HEADprima e git commit alla fine, se lo metti in una sceneggiatura.

Dai anche un'occhiata a una risposta a Posso impopolare un sottomodulo Git? .


1
Avevo molti sottomoduli (e un pasticcio più grande), quindi ho dovuto passarli attraverso un ciclo for. Poiché la maggior parte di essi si trovava in una directory specifica e l'output conteneva barre finali. Ho fatto qualcosa del genere for dir in directory/*; do git rm --cached $dir; done.
Pablo Olmos de Aguilera C.

Per ottenere questo l'elenco che può essere utilizzato nello script per l'eliminazione ricorsiva - git config -f .git/config -l | cut -d'=' -f1 | grep "submodule.$MODPATH" | sed 's/^submodule\.//' | sed 's/\.url$//'- - sembra che tu debba davvero farlo nel caso in cui ci sia qualcosa incasinato, altrimenti sologit submodule | grep -v '^+' | cut -d' ' -f3
errordeveloper

2
per ottenere l'elenco dei moduli in cui non sono state apportate modifiche locali -git submodule | grep '^+' | cut -d' ' -f2
errordeveloper

nota, ho dovuto includere submodulenametra virgolette doppie "submodulename".. facendo riferimento al .git/configfile
muon

Semplice. Efficiente. In 2.25.0, dopo il passaggio 1, è necessario mettere in scena le modifiche .gitmodules prima del passaggio 2.
Michel Donais,

83

Oltre alle raccomandazioni, dovevo anche rm -Rf .git/modules/path/to/submoduleessere in grado di aggiungere un nuovo sottomodulo con lo stesso nome (nel mio caso stavo sostituendo una forcella con l'originale)


1
Ho avuto problemi anche con questo. Se si tenta di reinstallare un sottomodulo sullo stesso percorso, mantiene le informazioni sul ramo memorizzate nella posizione nella posizione menzionata che rovinano le cose.
jangosteve

Grazie, ne avevo bisogno anche io. @Anton, sono d'accordo, e ho modificato la risposta votata per aggiungere queste informazioni.
William Denniss,

Ho usato l'opzione --name per far funzionare la sostituzione ... vedi stackoverflow.com/questions/14404704/...
joseph.hainline

60

Per rimuovere un sottomodulo aggiunto utilizzando:

git submodule add blah@blah.com:repos/blah.git lib/blah

Correre:

git rm lib/blah

Questo è tutto.

Per le vecchie versioni di git (circa ~ 1.8.5) usare:

git submodule deinit lib/blah
git rm lib/blah
git config -f .gitmodules --remove-section submodule.lib/blah

1
+1 davvero. Questa è l'unica risposta corretta da git 1.8.3 in poi. Dovrebbe essere accettato come quello corretto.
Xananax,

6
git rmlascia ancora roba dentro .git/modules/. (2.5.4)
Rudolf Adamkovič,

1
@RudolfAdamkovic funziona per me? Notare che rimuove la voce del sottomodulo solo se il percorso esatto corrisponde; se hai spostato un sottomodulo e poi lo usi git rmnon lo fa; Un rapido test con 2.5.4 sul mio mac aggiorna il file .gitmodules, come descritto nella documentazione qui: git-scm.com/docs/git-rm#_submodules ... ma se hai trovato una sorta di combinazione di piattaforma / versione dove ciò non accade, probabilmente dovresti presentare un bug al riguardo.
Doug,

2
Questa risposta non è del tutto corretta. git rmlascia roba in .git/modules/dir e .git/configfile (ubuntu, git 2.7.4). Altra risposta funziona al 100%: stackoverflow.com/a/36593218/4973698
mbdevpl

50

È necessario rimuovere la voce .gitmodulese .git/config, e rimuovere la directory del modulo dalla storia:

git rm --cached path/to/submodule

Se scriverai sulla mailing list di git, probabilmente qualcuno farà uno script di shell per te.


Non c'è bisogno di alcun script di shell, altra risposta ha i comandi per rimuovere tutte le tracce di un modulo: stackoverflow.com/a/36593218/4973698
mbdevpl

42

È possibile utilizzare un alias per automatizzare le soluzioni fornite da altri:

[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"

Mettilo nella tua config git e poi puoi fare: git rms path/to/submodule


-1 poiché questo è chiaramente troppo sbagliato. PRIMO: ciò presuppone che il nome e il percorso del sottomodulo siano identici, il che spesso non è il caso . 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. SECONDO: è necessario eseguirlo dal percorso corretto. gitgli alias dovrebbero funzionare ovunque nel worktree (o fallire con grazia). TERZO: git config -f .git/configfallisce nei sottomoduli, come di .gitsolito c'è un file lì.
Tino,

42

Per riassumere, questo è ciò che dovresti fare:

  1. Set path_to_submodulevar (nessuna barra finale):

    path_to_submodule=path/to/submodule

  2. Elimina la riga pertinente dal file .gitmodules:

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

  3. Elimina la sezione pertinente da .git / config

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

  4. Rimuovi la scena e rimuovi $ path_to_submodule solo dall'indice (per evitare la perdita di informazioni)

    git rm --cached $path_to_submodule

  5. Tieni traccia delle modifiche apportate a .gitmodules

    git add .gitmodules

  6. Commettere il superprogetto

    git commit -m "Remove submodule submodule_name"

  7. Elimina i file del sottomodulo ora non tracciati

    rm -rf $path_to_submodule

    rm -rf .git/modules/$path_to_submodule


quindi tutti gli altri che eliminano la mia modifica dovranno eseguire rm -rf $ path_to_submodule rm -rf .git / modules / $ path_to_submodule per rimuovere la cache del sottomodulo?
j2emanue,

Vi raccomando di aggiornamento, git submodule update. E se i percorsi dei sottomoduli non sono stati aggiornati correttamente (git genera un errore), rimuovili:rm -rf .git/modules/<submodule> && rm -rf <submodule> && git submodule update
luissquall

40

Se il sottomodulo è stato aggiunto accidentalmente perché hai aggiunto, eseguito il commit e il push di una cartella che era già un repository Git (contenuto .git), non avrai un .gitmodulesfile da modificare o qualcosa in esso .git/config. In questo caso tutto ciò che serve è:

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

FWIW , ho anche rimosso la .gitcartella prima di fare il git add.


esattamente il mio caso
Zhekaus,

37

Ho trovato che deinitfunziona bene per me:

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

Dai documenti git :

deinit

Annullare la registrazione dei sottomoduli indicati, ovvero rimuovere l'intera submodule.$name sezione da .git / config insieme al loro albero di lavoro.


Accetto ha trovato la stessa soluzione. È il modo migliore oggi nel 2018)
woto l'

1
non ha rimosso .git / modules / ... Dovresti rimuoverli, vedi la risposta di @fvgs
Vilém Kurz,

Non so perché questa soluzione semplice e facile non sia la numero 1
Marc Magon,

AFAICS questa sembra essere la risposta più sicura per i nuovi gits che conosciamo deinit, come l'altra risposta rimuove la .git/modules/submoduledirectory troppo presto, che sembra rendere più recente gits per fallire ora o allora. Inoltre (vedi il mio commento lì) la rimozione .git/modules/submodulepotrebbe essere la strada sbagliata, quindi questo è un passo pericoloso, da prendere in seguito solo quando si gitlamenta (o se sei sicuro al 299% che questo è quello che vuoi, è il percorso corretto e davvero necessario).
Tino,

Avevo anche bisogno git commitdi commettere cambiamenti graduali nella directory di lavoro: modified .gitmodulese deleted <submodule-path>.
Yuriy Pozniak,

20

Dopo aver sperimentato tutte le diverse risposte su questo sito, ho finito con questa soluzione:

#!/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

Ciò ripristina lo stesso identico stato di prima dell'aggiunta del sottomodulo. Puoi subito aggiungere nuovamente il sottomodulo, cosa impossibile con la maggior parte delle risposte qui.

git submodule add $giturl test
aboveScript test

Questo ti lascia con un checkout pulito senza modifiche da impegnare.

Questo è stato testato con:

$ git --version
git version 1.9.3 (Apple Git-50)

Perché usi git rm --cached $pathallora rm -rf $pathinvece di git rm -r $path?
bfontaine,

-1 Non funziona se si tenta di rimuovere un sottomodulo all'interno di un sottomodulo (il sottomodulo può formare alberi!). Anche questo è pericolosamente difettoso a causa della mancata citazione! Esempio git submodule add https://github.com/hilbix/empty.git 'dangerous .. submodule'-> quando provi a rimuovere "pericoloso ... sottomodulo" con il tuo script, questo sarà rm -rf ..molto probabilmente non quello che vuoi ..
Tino

17

Cosa sto facendo attualmente dicembre 2012 (combina la maggior parte di queste risposte):

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}"

15

Ecco cosa ho fatto:

1.) Eliminare la sezione pertinente dal file .gitmodules. È possibile utilizzare il comando seguente:

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

2.) Fase le .gitmodulesmodifiche

git add .gitmodules

3.) Eliminare la sezione pertinente da .git/config. È possibile utilizzare il comando seguente:

git submodule deinit -f "submodule_name"

4.) Rimuovere gitlink (nessuna barra finale):

git rm --cached path_to_submodule

5.) Pulisci .git/modules:

rm -rf .git/modules/path_to_submodule

6.) Commettere:

git commit -m "Removed submodule <name>"

7.) Elimina i file del sottomodulo ora non tracciati

rm -rf path_to_submodule

Grazie per questo. Per me, ho dovuto ridisporre l'ordine dei primi tre passi in 3), 1), 2). Fare 1) dapprima dato fatal: no submodule mapping found in .gitmodules for path 'submodule_name'al passaggio 3. Tuttavia, entrambi i passaggi erano necessari. (git v2.8.2)
U007D

13

Recentemente ho scoperto un progetto git che include molti utili comandi relativi a git: https://github.com/visionmedia/git-extras

Installalo e digita:

git-delete-submodule submodule

Quindi le cose sono fatte. La directory del sottomodulo verrà rimossa dal repository ed esiste ancora nel file system. È quindi possibile confermare la modifica come: git commit -am "Remove the submodule".


Puoi chiamarlo come git delete-submodule, come git-extrasdeve essere nel percorso di lavoro. Inoltre, ti consiglio di non utilizzaregit-extras , poiché molte parti sono estremamente difettose e pericolose . git-delete-submoduleProbabilmente IE rimuove il percorso errato di seguito .git/modules/*, dato che presuppone che il modulo e il percorso siano identici (cosa che spesso non è il caso) e non funziona correttamente se si tenta di rimuovere un sottomodulo all'interno di un sottomodulo. git-extraspotrebbe essere utile al 99%, ma per favore non lamentarti se le cose vanno completamente male durante l'uso. SEI STATO AVVERTITO!
Tino,

10

Ho dovuto fare i passi di John Douthat un ulteriore passo avanti e cdnella directory del sottomodulo, quindi rimuovere il repository Git:

cd submodule
rm -fr .git

Quindi potrei eseguire il commit dei file come parte del repository Git padre senza il vecchio riferimento a un sottomodulo.


Ho dovuto fare anche questo per superare un errore "fatale: non un repository git:" quando provavo a fare il git rm --cachepasso.
RickDT

9

Ecco i 4 passaggi che ho trovato necessari o utili (prima quelli importanti):

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

In teoria , git rmnel passaggio 1 dovrebbe occuparsene. Si spera che alla seconda parte della domanda OP possa essere data una risposta positiva un giorno (che ciò può essere fatto in un solo comando).

Ma a partire da luglio 2017, il passaggio 2 è necessario per rimuovere i dati in .git/modules/caso contrario, non è possibile ad esempio aggiungere nuovamente il sottomodulo in futuro.

Probabilmente è possibile cavarsela con i due passaggi precedenti per git 1.8.5+, come notato dalla risposta di tinlyx , poiché tutti i git submodulecomandi sembrano funzionare.

Il passaggio 3 rimuove la sezione per the_submodulenel file .git/config. Questo dovrebbe essere fatto per completezza. (La voce può causare problemi per le versioni precedenti di Git, ma non ne ho una da testare).

Per questo, la maggior parte delle risposte suggerisce di utilizzare git submodule deinit. Lo trovo più esplicito e meno confuso da usare git config -f .git/config --remove-section. In base alla documentazione di git-modulo , git deinit:

Annullare la registrazione i moduli forniti ... Se davvero si vuole rimuovere un modulo dal repository e si impegnano che l'uso git-rm [1] , invece .

Ultimo ma non meno importante, se non lo fai git commit, otterrai / potresti ricevere un errore quando lo fai git submodule summary(a partire da git 2.7):

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

Questo indipendentemente dal fatto che si eseguano i passaggi 2 o 3.


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

7

Ho appena trovato il file nascosto .submodule (ho dimenticato il nome esatto), ha un elenco ... puoi cancellarli singolarmente in quel modo. Ne ho appena avuto uno, quindi l'ho eliminato. Semplice, ma potrebbe confondere Git, dal momento che non so se qualcosa è collegato al sottomodulo. Sembra ok finora, a parte il solito problema di aggiornamento di libetpan, ma questo è (si spera) non correlato.

Ho notato che nessuno ha pubblicato la cancellazione manuale, quindi aggiunto


È.gitmodules
Arialdo Martini il

7

Con git 2.17 e versioni successive è solo:

git submodule deinit -f {module_name}
git add {module_name}
git commit

Non ha funzionato, né per git 2.17.1git 2.20.1. Comunque usando git rminvece di git addlavorato per entrambi. Note: -fnon è necessario se le cose sono pulite. Assicurarsi di non utilizzare le opzioni con gitse si vuole evitare perdite di dati non intenzionale. Si noti inoltre che questo lascia .git/modules/{module_name}al suo posto. È consigliabile mantenerlo lì perché gitstampa l'aiuto (!) Corretto su come procedere se qualcosa è bloccato a causa di ciò.
Tino,

4

Se hai appena aggiunto il sottomodulo e, ad esempio, hai semplicemente aggiunto il sottomodulo sbagliato o l'hai aggiunto nella posizione sbagliata, semplicemente git stashcancella la cartella. Questo presuppone che l'aggiunta del sottomodulo sia l'unica cosa che hai fatto nel recente repository.


3

A beneficio del lettore, questo qui cerca di riassumere e fornire una guida passo-passo su come farlo se le cose non funzionano come previsto. Di seguito è riportato il modo testato e sicuro per la gitversione 2.17e successive per sbarazzarsi di un sottomodulo :

submodule="path/to/sub"              # no trailing slash!
git submodule deinit -- "$submodule"
git rm -- "$submodule"
  • Se questo non funziona per te, vedi sotto.
  • Nessuna opzione Niente di pericoloso. E non considerare nemmeno di fare di più!
  • Testato con Debian Buster 2.20.1e Ubuntu 18.04 2.17.1.
  • "$submodule" è solo per sottolineare dove mettere il nome e che devi stare attento con spazi e simili
  • Se su Windows ignora la prima riga e sostituisci "$submodule"con il modo Windows di un percorso correttamente specificato al sottomodulo. (Non sono Windows)

Avvertimento!

Non toccare mai l'interno della .gitdirectory da soli! La modifica all'interno .gitentra nel lato oscuro. Stai lontano a tutti i costi!

E sì, puoi dare la colpa gita questo, dato che molte cose utili mancavano in gitpassato. Come un modo corretto per rimuovere nuovamente i sottomoduli.

Penso che ci sia una parte molto pericolosa nella documentazione di git submodule. Si consiglia di rimuovere $GIT_DIR/modules/<name>/te stesso. Secondo me questo non è solo un errore, ma è estremamente pericoloso e provoca in futuro grossi mal di testa! Vedi sotto.

Nota che

git module deinit

è l'inverso diretto a

git module init

ma

git submodule deinit -- module
git rm -- module

inoltre è abbastanza il contrario

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

perché alcuni comandi in pratica devono fare più di una sola cosa:

  • git submodule deinit -- module
    • (1) aggiornamenti .git/config
  • git rm
    • (2) rimuove i file del modulo
    • (3) rimuove in tal modo ricorsivamente i sottomoduli del sottomodulo
    • (4) aggiornamenti .gitmodules
  • git submodule add
    • inserisce i dati in .git/modules/NAME/
    • (1) git submodule initsì, quindi aggiorna.git/config
    • (2) git submodule update, quindi, controlla in modo non ricorsivo il modulo
    • (4) aggiornamenti .gitmodules
  • git submodule update --init --recursive -- module
    • inserisce ulteriori dati se necessario
    • (3) verifica ricorsivamente i sottomoduli del sottomodulo

Questo non può essere completamente simmetrico, poiché mantenerlo rigorosamente simmetrico non ha molto senso. Semplicemente non sono necessari più di due comandi. Anche "estrarre i dati" è implicito, perché ne hai bisogno, ma non è possibile rimuovere le informazioni memorizzate nella cache, perché non sono affatto necessarie e potrebbero cancellare dati preziosi.

Questo è davvero sconcertante per i nuovi arrivati, ma fondamentalmente è una buona cosa: gitfa semplicemente la cosa ovviamente e fa bene, e non cerca nemmeno di fare di più. gitè uno strumento che deve fare un lavoro affidabile, invece di essere solo un altro "Eierlegende Wollmilchsau" ("Eierlegende Wollmilchsau" si traduce per me in "una versione malvagia di un coltellino svizzero").

Quindi capisco le lamentele delle persone, dicendo "Perché non fa gitla cosa ovvia per me". Questo perché "ovvio" qui dipende dal punto di vista. L'affidabilità in ogni situazione è molto più importante. Quindi ciò che è ovvio per te spesso non è la cosa giusta in tutte le possibili situazioni tecniche. Ricorda che: AFAICS gitsegue il percorso tecnico, non quello sociale. (Da qui il nome intelligente: git)

Se questo fallisce

I comandi precedenti potrebbero non riuscire a causa di:

  • Sei gittroppo vecchio. Quindi utilizzare un nuovogit . (Vedi sotto come.)
  • Hai dati non impegnati e potresti perdere dati. Quindi meglio impegnarli prima.
  • Il tuo sottomodulo non è pulito in a git clean certo senso. Quindi prima pulisci il tuo sottomodulo usando quel comando. (Vedi sotto.)
  • In passato hai fatto qualcosa che non è supportato da git . Allora sei sul lato oscuro e le cose si fanno brutte e complicate. (Forse usando un'altra macchina lo risolve.)
  • Forse ci sono altri modi per fallire di cui non sono a conoscenza (sono solo un po 'di gitpower-user.)

Seguono possibili correzioni.

Usa un nuovo git

Se la tua macchina è troppo vecchia non ce n'è submodule deinitnella tua git. Se non vuoi (o puoi) aggiornare il tuo git, usa semplicemente un'altra macchina con una nuova git! gitè pensato per essere completamente distribuito, quindi puoi usarne un altro gitper completare il lavoro:

  • workhorse:~/path/to/worktree$ git status --porcelain non deve emettere nulla! In tal caso, prima pulisci le cose!
  • workhorse:~/path/to/worktree$ ssh account@othermachine
  • othermachine:~$ git clone --recursive me@workhorse path/to/worktree/.git TMPWORK && cd TMPWORK
  • Ora fai le cose del sottomodulo
  • 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. Se questo non funziona, utilizzaregit reset --soft FETCH_HEAD
  • Ora git statuspulisci le cose, fino a quando non è di nuovo pulito. Sei in grado di farlo, perché l'hai già pulito prima, grazie al primo passo.

Questo othermachinepuò essere un po 'di VM, o qualche Ubuntu WSL in ambiente Windows, a prescindere. Anche un chroot(ma presumo che tu non sia root, perché se lo sei rootdovrebbe essere più facile aggiornarlo al più recente git).

Nota che se non riesci ssha entrare, ci sono un sacco di modi per trasportare i gitrepository. Puoi copiare il tuo worktree su una chiavetta USB (compresa la .gitdirectory) e clonarlo dalla chiavetta. Clona la copia, solo per riportare le cose in modo pulito. Questo potrebbe essere un PITA, nel caso in cui i sottomoduli non siano accessibili direttamente da altre macchine. Ma c'è anche una soluzione per questo:

git config --add url.NEWURLPREFIX.insteadOf ORIGINALURLPREFIX

È possibile utilizzare questo moltiplicare e questo viene salvato in $HOME/.gitconfig. Qualcosa di simile a

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

riscrive URL come

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

in

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

È facile se inizi ad abituarti a potenti gitfunzionalità come questa.

Pulisci prima le cose

La pulizia manuale è buona, perché in questo modo potresti forse rilevare alcune cose che hai dimenticato.

  • Se git si lamenta di cose non salvate, commetti e spingile in un posto sicuro.
  • Se git si lamenta di alcuni avanzi git statused git clean -ixfdè tuo amico
  • Cerca di astenersi dalle opzioni per rme il deinitpiù a lungo possibile. Le opzioni (come -f) per gitsono buone se sei un professionista. Ma come sei venuto qui, probabilmente non sei così esperto nella submodulezona. Quindi meglio prevenire che curare.

Esempio:

$ 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'

Vedi, non ce n'è -fbisogno submodule deinit. Se le cose sono pulite, in un git cleancerto senso. Si noti inoltre che git clean -xnon è necessario. Ciò significa che git submodule deinitrimuove incondizionatamente i file non monitorati che vengono ignorati. Questo è di solito quello che vuoi, ma non dimenticartene. A volte i file ignorati possono essere preziosi, come i dati memorizzati nella cache che richiedono ore o giorni per essere nuovamente calcolati.

Perché non rimuoverlo mai $GIT_DIR/modules/<name>/?

Probabilmente le persone vogliono rimuovere il repository memorizzato nella cache, perché hanno paura di incorrere in un problema in seguito. Questo è vero, ma imbattersi in quel "problema" è il modo corretto di risolverlo! Perché la correzione è facile e fatta bene sarai in grado di vivere per sempre felici e contenti. Ciò evita problemi più ingombranti rispetto a quando si rimuovono i dati da soli.

Esempio:

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

L'ultima riga genera il seguente errore:

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.

Perché questo errore? Perché in .git/modules/two/precedenza era popolato da https://github.com/hilbix/empty.git e ora deve essere ripopolato da qualcos'altro, vale a dire https://github.com/hilbix/src.git . Non lo vedrai se lo popoli nuovamente da https://github.com/hilbix/empty.git

Cosa fare adesso? Bene, fai esattamente come detto! Uso--name someunusedname

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

.gitmodules allora sembra

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

ls -1p .git/modules/

someunusedname/
two/

In questo modo in futuro puoi cambiare succursale / impegnarti in avanti e indietro e non avrai mai più problemi , a causa di two/due diversi repository (e forse incompatibili) a monte. E il migliore è: tieni anche entrambi memorizzati nella cache locale.

  • Questo non è vero solo per te. È anche vero per tutti gli altri che usano il tuo repository.
  • E non perdi la storia. Nel caso in cui ti sei dimenticato di inviare l'ultima versione del vecchio sottomodulo, puoi inserire la copia locale e farlo in seguito. Si noti che è abbastanza comune che qualcuno si dimentichi di inviare alcuni sottomoduli (perché questa è una PITA per i nuovi arrivati, fino a quando non si sono abituati git).

Tuttavia, se hai rimosso la directory memorizzata nella cache, entrambi i diversi checkout si imbatteranno l'uno nell'altro, perché non utilizzerai le --nameopzioni, giusto? Quindi ogni volta che fai il checkout forse devi rimuovere la .git/modules/<module>/directory ancora e ancora. Questo è estremamente ingombrante e rende difficile usare qualcosa del genere git bisect.

Quindi c'è un motivo molto tecnico per mantenere questa directory del modulo come segnaposto. Le persone che raccomandano di rimuovere qualcosa di seguito .git/modules/o non sanno meglio o dimenticano di dirti che questo rende potenti funzionalità comegit bisect quasi impossibili da usare se attraversasse una tale incompatibilità del sottomodulo.

Un ulteriore motivo è mostrato sopra. Guarda il ls. Cosa vedi lì?

Bene, la seconda variante del modulo two/non è sotto .git/modules/two/, è sotto .git/modules/someunusedname/! Quindi cose del genere git rm $module; rm -f .git/module/$modulesono totalmente sbagliate! È necessario consultare module/.gito .gitmodulesper trovare la cosa giusta da rimuovere!

Quindi non solo la maggior parte delle altre risposte cade in questa pericolosa trappola, anche le gitestensioni molto popolari avevano questo bug ( ora è stato risolto lì )! Quindi meglio tenere le mani della .git/directory se non esattamente, cosa stai facendo!

E dal punto di vista filosofico, cancellare la storia è sempre sbagliato! Tranne la meccanica quantistica , come al solito, ma questo è qualcosa di completamente diverso.

Cordiali saluti, probabilmente lo hai indovinato: Hilbix è il mio account GitHub.


Questa enciclopedia di un post dovrebbe essere suddivisa in sezioni più chiare con sottotitoli più grandi / più chiari per indicare la risposta effettiva e le diverse sezioni "risoluzione dei problemi" / ecc.
Andrew

2

Per riassumere, questo è ciò che dovresti fare:

Imposta path_to_submodule var (nessuna barra finale):

path_to_submodule=path/to/submodule

Elimina la riga pertinente dal file .gitmodules:

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

Elimina la sezione pertinente da .git / config

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

Annulla la messa in scena e rimuovi $ path_to_submodule solo dall'indice (per evitare la perdita di informazioni)

git rm --cached $path_to_submodule

Tieni traccia delle modifiche apportate a .gitmodules

git add .gitmodules

Commettere il superprogetto

git commit -m "Remove submodule submodule_name"

Elimina i file del sottomodulo ora non tracciati

rm -rf $path_to_submodule

rm -rf .git/modules/$path_to_submodule

Vedi anche: Linee guida alternative


Potete per favore estenderlo con come rimuovere un sottomodulo seguendo un 'add god submodule' ma senza averlo mai commesso? Presumo che in quel caso non sia necessario alcun commit per rimuovere il sottomodulo, giusto?
Carlo Wood,

Penso che devi scambiare il git rm --cached $path_to_submodulee git add .gitmodulesno? Ho ricevuto un errore al primo comando: fatal: Please stage your changes to .gitmodules or stash them to proceedperché avevo apportato modifiche non messe in scena a .gitmodules. Fare i git add .gitmodulesprimi risolve questo.
Carlo Wood,

2

Questo è facile:

  1. Rimuovere la sezione da .gitmodules
  2. Chiamata: git add .gitmodules
  3. Chiamata: git submodule deinit <path to submodule>
  4. Chiamata: git rm <path to submodule>
  5. Commettere e spingere

Dovrai eliminare manualmente i file del modulo sul tuo progetto.


2
Per me è stato sufficiente chiamare git submodule deinit <submodule_name>e git rm <path_to_submodule>. L'ultimo comando cancella automaticamente la voce all'interno di .gitmodules. Git 2.17
Dmytro Ovdiienko


0

Nell'ultima versione di git sono necessarie solo 4 operazioni per rimuovere il sottomodulo git.

  • Rimuovi la voce corrispondente in .gitmodules
  • Cambiamenti di scena git add .gitmodules
  • Rimuovere la directory del sottomodulo git rm --cached <path_to_submodule>
  • Commettilo git commit -m "Removed submodule xxx"

0

Nel caso in cui sia necessario farlo con un comando di riga con bash script come di seguito:

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

Creare il file di script bash nella directory $HOMEdenominata 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


0
  • Un sottomodulo può essere eliminato eseguendo git rm <submodule path> && git commit. Questo può essere annullato usando git revert.
    • L'eliminazione rimuove i dati di tracciamento del superprogetto, che sono sia la voce gitlink che la sezione nel .gitmodulesfile.
    • La directory di lavoro del sottomodulo viene rimossa dal file system, ma la directory Git viene mantenuta in circolo in modo da consentire il checkout dei commit passati senza richiedere il recupero da un altro repository.
  • Per rimuovere completamente un sottomodulo, eliminare anche manualmente$GIT_DIR/modules/<name>/ .

Fonte: git help submodules


-1

Rimozione del sottomodulo git

Per rimuovere un gitsottomodulo sotto sono necessari 4 passaggi.

  1. Rimuovere la voce corrispondente nel .gitmodulesfile. La voce potrebbe essere come menzionato di seguito
[submodule "path_to_submodule"]
    path = path_to_submodule
    url = url_path_to_submodule
  1. Cambiamenti di scena git add .gitmodules
  2. Rimuovere la directory del sottomodulo git rm --cached <path_to_submodule>.
  3. Impegnalo git commit -m "Removed submodule xxx"e spingi.

Ulteriori 2 ulteriori passaggi menzionati di seguito sono necessari per pulire completamente il sottomodulo nella copia clonata locale.

  1. Rimuovere la voce corrispondente nel .git/configfile. La voce potrebbe essere come menzionato di seguito
[submodule "path_to_submodule"]
    url = url_path_to_submodule
  1. Fare rm -rf .git/modules/path_to_submodule

Questi passaggi 5 ° e 6 ° non creano alcun cambiamento che necessita di commit.


Sarebbe molto più semplice se git submodule deinit usassi git-scm.com/docs/git-submodule#Documentation/…
Black
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.