¿Cómo elimino un submódulo?

3539

¿Cómo elimino un submódulo Git?

Por cierto, ¿hay alguna razón que no pueda simplemente hacer git submodule rm whatever?

R. Martinho Fernandes
fuente
109
La respuesta simple stackoverflow.com/a/21211232/94687 es ahora la correcta y debe marcarse así. Ahora, es simple git rm modulenameyrm -rf .git/modules/modulename
imz - Ivan Zakharyaschev
10
Eso en realidad no es cierto. Esa respuesta no aborda la eliminación de la entrada de submódulo de .git/config. La respuesta aceptada muestra la forma actualizada de eliminar completamente un submódulo. También se explica más sucintamente en esta respuesta: stackoverflow.com/a/36593218/1562138
fvgs
Este artículo me pareció muy útil para eliminar submódulos. Incluye información sobre la eliminación de entradas en los .gitsubmodules y .git / archivos de configuración enlazan
Ri_
12
Ahorre algo de tiempo y vaya directamente a la respuesta que funciona (en 2017): stackoverflow.com/a/36593218/528313
Vincenzo Pii
He luchado con problemas de submódulos durante dos días. El avance se produjo cuando encontré esto: forum.developer.apple.com/thread/13102 . Básicamente, Xcode, y quizás otras aplicaciones, luchan por expandir las URL que contienen '~'. Una vez que cambié ssh: //[email protected]/~/git/MyRepo.git a ssh: //[email protected]/home/username/git/MyRepo.git (busque la ruta real en su servidor), toda la rareza desapareció con diez minutos. Ver también stackoverflow.com/questions/32833100/…
Elise van Looij

Respuestas:

2216

Desde git1.8.3 (22 de abril de 2013) :

No había forma de porcelana de decir "Ya no estoy interesado en este submódulo", una vez que expresas tu interés en un submódulo con " submodule init".
" submodule deinit" es la forma de hacerlo.

El proceso de eliminación también utiliza git rm (desde git1.8.5 de octubre de 2013).

Resumen

El proceso de eliminación de 3 pasos sería:

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

Explicación

rm -rf: Esto se menciona en la respuesta de Daniel Schroeder y Eonil lo resume en los comentarios :

Esto deja .git/modules/<path-to-submodule>/sin cambios.
Entonces, si una vez elimina un submódulo con este método y lo vuelve a agregar, no será posible porque el repositorio ya está dañado.


git rm: Ver commit 95c16418 :

Actualmente, el uso de " git rm" en un submódulo elimina el árbol de trabajo del submódulo del superproyecto y el gitlink del índice.
Pero la sección del submódulo .gitmodulesse deja intacta, lo que es un remanente del submódulo ahora eliminado y puede irritar a los usuarios (a diferencia de la configuración .git/config, esto debe permanecer como un recordatorio de que el usuario mostró interés en este submódulo, por lo que se repoblará más tarde cuando una confirmación más antigua está desprotegida).

Deje que " git rm" ayude al usuario no solo eliminando el submódulo del árbol de trabajo, sino también eliminando la submodule.<submodule name>sección " " del .gitmodulesarchivo y organice ambos.


git submodule deinit: Se deriva de este parche :

Con " git submodule init" el usuario puede decirle a git que se preocupa por uno o más submódulos y quiere que se complete en la próxima llamada a " git submodule update".
Pero actualmente no hay una manera fácil de decirle a git que ya no se preocupan por un submódulo y quieren deshacerse del árbol de trabajo local (a menos que el usuario sepa mucho sobre las partes internas del submódulo y elimine la submodule.$name.urlconfiguración " " .git/configjunto con el trabajo árbol mismo).

Ayude a esos usuarios proporcionando un deinitcomando ' '.
Esto elimina la submodule.<name>sección completa de .git/configcualquiera de los submódulos dados (o de todos los que se han inicializado si .se da ' ').
Falla si el árbol de trabajo actual contiene modificaciones a menos que sea forzado.
Quejarse cuando para un submódulo dado en la línea de comando no se puede encontrar la configuración de URL .git/config, pero no falla.

Esto tiene cuidado si los pasos de (de) inicialización ( .git/configy.git/modules/xxx )

Desde git1.8.5, la git rmtomas también se preocupan de la:

  • ' add' paso que registra la url de un submódulo en el.gitmodules archivo: es necesario eliminarlo por usted.
  • la entrada especial del submódulo (como se ilustra en esta pregunta ): el git rm lo elimina del índice:
    git rm --cached path_to_submodule(sin barra diagonal)
    Eso eliminará ese directorio almacenado en el índice con un modo especial "160000", marcándolo como un directorio raíz de submódulo .

Si olvida el último paso e intenta agregar lo que era un submódulo como directorio normal, recibirá un mensaje de error como:

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

Nota: desde Git 2.17 (Q2 2018), git submodule deinit ya no es un script de shell.
Es una llamada a una función C.

Ver commit 2e61273 , commit 1342476 (14 de enero de 2018) por Prathamesh Chavan ( pratham-pc) .
(Fusionada por Junio ​​C Hamano - gitster- en 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} "$@"
VonC
fuente
18
¿Puedes dar un ejemplo de uso para submodule deinit?
zakdances
55
@yourfriendzak aquí hay un ejemplo de alguien que lo usó con éxito: stackoverflow.com/a/16161950/6309 . ¡Pero tenga en cuenta que, al contrario de lo que creía originalmente, 1.8.3 aún no se ha lanzado! En Unix, puede compilarlo desde las fuentes.
VonC
2
@HamishDowner, la entrada especial debería desaparecer (el directorio ya no es un submódulo), y .gitmodulesdebería estar bien, pero aún así verificaría dos veces cualquier cosa con el .gitdirectorio (es decir, la configuración local , dentro de su repositorio local: eso no es modificado por a git pull)
VonC
2
@Jayen sí, si confirma la eliminación de la .gitmodulesentrada y la eliminación de la entrada especial en el índice, y empuja ese repositorio, otros pueden extraerlo y ese submódulo desaparecerá.
VonC
3
En git actual (v1.9 +), el viejo git rm submodulehace exactamente lo que quieres como ya han dicho otras personas.
Pete Peterson
3445

A través de la página Git Submodule Tutorial :

Para eliminar un submódulo, debe:

  1. Eliminar la sección relevante de .gitmodules archivo.
  2. Etapa de los .gitmodulescambios:
    git add .gitmodules
  3. Eliminar la sección relevante de .git/config .
  4. Elimine los archivos de submódulos del árbol de trabajo e índice:
    git rm --cached path_to_submodule (sin barra inclinada).
  5. Elimine el .gitdirectorio del submódulo :
    rm -rf .git/modules/path_to_submodule
  6. Cometer los cambios:
    git commit -m "Removed submodule <name>"
  7. Elimine los archivos de submódulos ahora sin seguimiento:
    rm -rf path_to_submodule

Ver también : pasos alternativos a continuación .

John Douthat
fuente
410
"Y, por cierto, ¿hay alguna razón por la que no pueda simplemente interpretar el submódulo rm?" ?
abernier
48
@abernier Una respuesta corta podría ser "porque no existe tal comando". Supongo que están tratando de hacer explícita la eliminación de los archivos de submódulos frente a la configuración de submódulos para evitar la pérdida accidental de datos. Tal vez una persona pensaría que git submodule rmsimplemente elimina el registro de submódulos, y se sorprendería si el comando también eliminara el repositorio local. Cualquier cambio local se perdería irremediablemente. Y tal vez otra persona pensaría que solo se eliminarían los archivos.
John Douthat
119
Francamente, no sé por qué. Sin embargo, espero que agreguen un comando. Estos 4 pasos son demasiado complicados.
John Douthat
25
Aquí hay un script bash que elimina un submódulo, simplemente cree un alias git para submodule-rm;) gist.github.com/2491147
Capi Etheriel
33
también necesita rm -rf .git \ modules \ submodule name?
rogerdpack
484

Solo una nota. Desde git 1.8.5.2, dos comandos harán:

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

Como señaló correctamente la respuesta de @Mark Cheverton, si la segunda línea no se usa, incluso si eliminó el submódulo por ahora, la carpeta remanente .git / modules / the_submodule evitará que el mismo submódulo se vuelva a agregar o reemplazar en el futuro . Además, como mencionó @VonC,git rm hará la mayor parte del trabajo en un submódulo.

--Actualización (07/05/2017) -

Solo para aclarar, the_submodulees la ruta relativa del submódulo dentro del proyecto. Por ejemplo, es subdir/my_submodulesi el submódulo está dentro de un subdirectorio subdir.

Como se señaló correctamente en los comentarios y otras respuestas , los dos comandos (aunque funcionalmente suficientes para eliminar un submódulo), dejan un rastro en la [submodule "the_submodule"]sección .git/config(a partir de julio de 2017), que se puede eliminar con un tercer comando:

git config -f .git/config --remove-section submodule.the_submodule 2> /dev/null
tinlyx
fuente
55
Estoy en git versión 2.4.9 (Apple Git-60) y todo lo que tuve que hacer fue rm the_submodule. Empujé eso y luego volví a agregar una carpeta llamada igual que el submódulo y funcionó sin problemas.
David Silva Smith
19
Esto no elimina la entrada de submódulo de .git/config. Consulte stackoverflow.com/a/36593218/1562138 para ver la forma completa de eliminar un submódulo.
fvgs
2
@drevicko Acabo de probar esto con Git 2.11.1 y observo el mismo comportamiento que antes. git init && git submodule add <repository> && git rm <name>deja atrás la .git/configentrada y el .git/modules/<name>directorio y sus contenidos. ¿Quizás no inicializó el submódulo antes de eliminarlo?
fvgs
2
me siento más seguro al ejecutar esto primero .. git submodule deinit -f the_submodule
danday74
1
@JarrodSmith Sí, es el camino. por favor vea la actualización.
tinlyx
479

La mayoría de las respuestas a esta pregunta son obsoletas, incompletas o innecesariamente complejas.

Un submódulo clonado usando git 1.7.8 o posterior dejará como máximo cuatro rastros de sí mismo en su repositorio local. El proceso para eliminar esos cuatro rastros viene dado por los tres comandos a continuación:

# 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
fuente
39
¿Por qué esta respuesta tiene tan pocos votos a favor? Todas esas respuestas populares pierden algo, esta es la única que realmente elimina todos los rastros de un submódulo, de la manera más simple posible. Y nota: el orden de los comandos es importante.
mbdevpl
2
Para responder a mi propia pregunta: stackoverflow.com/questions/97875/rm-rf-equivalent-for-windows
Thomas
55
@mbdevpl llegó 3 años después de la respuesta aceptada, y supongo que nadie logró convencer al OP para que aceptara esta
Andy
10
¿ESTA es la respuesta no complicada en 2018?
Warren P
99
el archivo .gitmodules todavía no parece afectado al ejecutar estos comandos
Fractalf
206

Pasos simples

  1. Eliminar entradas de configuración:
    git config -f .git/config --remove-section submodule.$submodulename
    git config -f .gitmodules --remove-section submodule.$submodulename
  2. Eliminar directorio del índice:
    git rm --cached $submodulepath
  3. Cometer
  4. Eliminar archivos no utilizados:
    rm -rf $submodulepath
    rm -rf .git/modules/$submodulename

Tenga en cuenta: $submodulepath no contiene barras inclinadas iniciales o finales.

Antecedentes

Cuando lo hace git submodule add, solo lo agrega .gitmodules, pero una vez que lo hizo git submodule init, lo agregó .git/config.

Entonces, si desea eliminar los módulos, pero poder restaurarlo rápidamente, haga lo siguiente:

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

Es una buena idea hacer git rebase HEADprimero y git commit al final, si pones esto en un script.

También eche un vistazo a una respuesta a ¿Puedo despoblar un submódulo Git? .

errores
fuente
1
Tenía muchos submódulos (y un lío más grande), así que tuve que pasarlos por un bucle for. Dado que la mayoría de ellos estaban bajo un directorio específico y la salida ls contenía barras diagonales finales. Hice algo parecido for dir in directory/*; do git rm --cached $dir; done.
Pablo Olmos de Aguilera C.
Para obtener esto, la lista que se puede usar en el script para la eliminación recursiva - git config -f .git/config -l | cut -d'=' -f1 | grep "submodule.$MODPATH" | sed 's/^submodule\.//' | sed 's/\.url$//'- - parece que realmente tiene que hacer esto en caso de que haya algo desordenado, de lo contrario, sologit submodule | grep -v '^+' | cut -d' ' -f3
errordeveloper
2
para obtener la lista de módulos donde no se han realizado cambios localesgit submodule | grep '^+' | cut -d' ' -f2
errordeveloper
nota, he tenido que incluir submodulenameentre comillas dobles "submodulename".. refiriéndose al .git/configarchivo
muón
Simple. Eficiente. En 2.25.0, después del paso 1, debe realizar cambios en los módulos .gitmodules antes del paso 2.
Michel Donais
83

Además de las recomendaciones, también tuve que rm -Rf .git/modules/path/to/submodulepoder agregar un nuevo submódulo con el mismo nombre (en mi caso, estaba reemplazando un tenedor con el original)

Mark Cheverton
fuente
1
Estaba teniendo problemas con esto también. Si intenta reinstalar un submódulo en la misma ruta, mantiene la información de la sucursal en caché en la ubicación que mencionó, lo que complica las cosas.
jangosteve
Gracias, yo también necesitaba esto. @Anton, estoy de acuerdo, y he editado la respuesta más votada para agregar esta información.
William Denniss
Usé la opción --name para hacer que el reemplazo funcione ... ver stackoverflow.com/questions/14404704/…
joseph.hainline
60

Para eliminar un submódulo agregado usando:

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

Correr:

git rm lib/blah

Eso es.

Para versiones antiguas de git (alrededor de ~ 1.8.5) use:

git submodule deinit lib/blah
git rm lib/blah
git config -f .gitmodules --remove-section submodule.lib/blah
Doug
fuente
1
+1 de hecho. Esta es la única respuesta correcta desde git 1.8.3 en adelante. Debe ser aceptado como el correcto.
Xananax
66
git rmTodavía deja cosas adentro .git/modules/. (2.5.4)
Rudolf Adamkovič el
1
@RudolfAdamkovic, ¿funciona para mí? Observe que solo elimina la entrada del submódulo si la ruta exacta coincide; si ha movido un submódulo y luego lo usa git rm, no lo hace; Una prueba rápida con 2.5.4 en mi mac actualiza el archivo .gitmodules, como se describe en la documentación aquí: git-scm.com/docs/git-rm#_submodules ... pero si ha encontrado algún tipo de combinación de plataforma / versión donde esto no sucede, probablemente deberías presentar un error al respecto.
Doug
2
Esta respuesta no es del todo correcta. git rmdeja cosas en .git/modules/dir y .git/configfile (ubuntu, git 2.7.4). Otra respuesta funciona al 100%: stackoverflow.com/a/36593218/4973698
mbdevpl
50

Debe eliminar la entrada en .gitmodulesy .git/config, y eliminar el directorio del módulo del historial:

git rm --cached path/to/submodule

Si escribes en la lista de correo de git, probablemente alguien hará un script de shell por ti.

Carmine Paolino
fuente
No hay necesidad de ningún script de shell, otra respuesta tiene comandos para eliminar todos los rastros de un submódulo: stackoverflow.com/a/36593218/4973698
mbdevpl
42

Puede usar un alias para automatizar las soluciones proporcionadas por otros:

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

Pon eso en tu configuración de git, y luego puedes hacer: git rms path/to/submodule

Charles
fuente
-1 ya que esto es demasiado incorrecto. PRIMERO: Esto supone que el nombre y la ruta del submódulo son idénticos, lo que a menudo no es el 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. SEGUNDO: debe ejecutar esto desde la ruta correcta. gitlos alias deberían funcionar en cualquier parte del árbol de trabajo (o fallar con gracia). TERCERO: git config -f .git/configfalla dentro de los submódulos, ya que .gitgeneralmente hay un archivo allí.
Tino
42

Para resumir, esto es lo que debe hacer:

  1. Establecer path_to_submodulevar (sin barra inclinada):

    path_to_submodule=path/to/submodule

  2. Elimine la línea relevante del archivo .gitmodules:

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

  3. Eliminar la sección relevante de .git / config

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

  4. Desensamblar y eliminar $ path_to_submodule solo del índice (para evitar perder información)

    git rm --cached $path_to_submodule

  5. Rastree los cambios realizados en .gitmodules

    git add .gitmodules

  6. Cometer el superproyecto

    git commit -m "Remove submodule submodule_name"

  7. Eliminar los archivos de submódulos ahora sin seguimiento

    rm -rf $path_to_submodule

    rm -rf .git/modules/$path_to_submodule

luissquall
fuente
Entonces, ¿todos los que despliegan mi cambio tendrán que ejecutar rm -rf $ path_to_submodule rm -rf .git / modules / $ path_to_submodule para eliminar el caché del submódulo?
j2emanue
Recomiendo a actualizar git submodule update. Y si las rutas de los submódulos no se actualizaron correctamente (git arroja un error), elimínelas:rm -rf .git/modules/<submodule> && rm -rf <submodule> && git submodule update
luissquall
40

Si el submódulo se agregó accidentalmente porque agregó, confirmó y empujó una carpeta que ya era un repositorio Git (contenido .git), no tendrá un .gitmodulesarchivo para editar ni nada .git/config. En este caso todo lo que necesitas es:

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

FWIW , también eliminé la .gitcarpeta antes de hacer el git add.

Oli Studholme
fuente
exactamente mi caso
zhekaus
37

Encontré deinittrabajos buenos para mí:

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

De git docs :

deinit

Anule el registro de los submódulos dados, es decir, elimine toda la submodule.$name sección de .git / config junto con su árbol de trabajo.

Damjan Pavlica
fuente
De acuerdo encontró la misma solución. Es la mejor manera hoy en 2018)
woto
1
no eliminó .git / modules / ... Deberías eliminarlos, mira la respuesta de @fvgs
Vilém Kurz
No sé por qué esta solución simple y fácil no es la número 1
Marc Magon
AFAICS esto parece ser la respuesta más segura para los nuevos gits , que saben de deinit, como la otra respuesta quita el .git/modules/submoduledirectorio demasiado pronto, lo que parece hacer más reciente gits fallar ahora o después. Además (vea mi comentario allí), la eliminación .git/modules/submodulepodría ser la ruta incorrecta, por lo que este es un paso peligroso, que se tomará más adelante solo cuando se gitqueje (o si está 299% seguro de que lo que quiere es la ruta correcta y realmente necesaria).
Tino
También necesitaba git commitconfirmar cambios por etapas en el directorio de trabajo: modified .gitmodulesy deleted <submodule-path>.
Yuriy Pozniak
20

Después de experimentar con todas las diferentes respuestas en este sitio, terminé con esta solución:

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

Esto restaura exactamente el mismo estado que antes de agregar el submódulo. Puede agregar de inmediato el submódulo nuevamente, lo que no fue posible con la mayoría de las respuestas aquí.

git submodule add $giturl test
aboveScript test

Esto te deja con un pago limpio sin cambios para confirmar.

Esto fue probado con:

$ git --version
git version 1.9.3 (Apple Git-50)
udondan
fuente
¿Por qué usas git rm --cached $pathentonces en rm -rf $pathlugar de git rm -r $path?
bfontaine
-1 No funciona si intenta eliminar un submódulo dentro de un submódulo (¡el submódulo puede formar árboles!). ¡Además, esto es peligrosamente defectuoso debido a la falta de citas! Ejemplo git submodule add https://github.com/hilbix/empty.git 'dangerous .. submodule'-> cuando intentas eliminar 'submódulo peligroso ...' con tu script, rm -rf ..lo más probable es que no sea lo que quieres ...
Tino
17

Lo que estoy haciendo actualmente en diciembre de 2012 (combina la mayoría de estas respuestas):

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
fuente
15

Aquí esta lo que hice :

1.) Eliminar la sección relevante del archivo .gitmodules. Puede usar el siguiente comando:

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

2.) Etapa los .gitmodulescambios

git add .gitmodules

3.) Eliminar la sección relevante de .git/config. Puede usar el siguiente comando:

git submodule deinit -f "submodule_name"

4.) Elimine el gitlink (sin barra inclinada):

git rm --cached path_to_submodule

5.) Limpieza de .git/modules:

rm -rf .git/modules/path_to_submodule

6.) Comprometerse:

git commit -m "Removed submodule <name>"

7.) Eliminar los archivos de submódulos ahora sin seguimiento

rm -rf path_to_submodule
Ishan Liyanage
fuente
Gracias por esto. Para mí, tuve que reorganizar el orden de los primeros tres pasos a 3), 1), 2). Hacer 1) primero dio fatal: no submodule mapping found in .gitmodules for path 'submodule_name'en el paso 3. Sin embargo, ambos pasos fueron necesarios. (git v2.8.2)
U007D
13

Recientemente descubrí un proyecto git que incluye muchos comandos útiles relacionados con git: https://github.com/visionmedia/git-extras

Instálalo y escribe:

git-delete-submodule submodule

Entonces las cosas están hechas. El directorio de submódulos se eliminará de su repositorio y seguirá existiendo en su sistema de archivos. A continuación, puede confirmar el cambio como: git commit -am "Remove the submodule".

Chien-Wei Huang
fuente
Puede llamar a esto como git delete-submodule, ya que git-extrasdebe estar en el camino al trabajo. También tenga en cuenta que recomiendo no usargit-extras , ya que muchas partes son extremadamente defectuosas y peligrosas . Es git-delete-submoduleposible que IE elimine la ruta incorrecta a continuación .git/modules/*, ya que supone que el módulo y la ruta son idénticos (que a menudo no es el caso), y no funciona correctamente si intenta eliminar un submódulo dentro de un submódulo. git-extraspuede ser útil al 99%, pero no se queje si las cosas salen mal al usarlo. ¡USTED HA SIDO ADVERTIDO!
Tino
10

Tuve que seguir los pasos de John Douthat un paso más allá y cden el directorio del submódulo, y luego eliminar el repositorio de Git:

cd submodule
rm -fr .git

Entonces podría confirmar los archivos como parte del repositorio principal de Git sin la referencia anterior a un submódulo.

Kyle Clegg
fuente
Tuve que hacer esto también para superar un error "fatal: No es un repositorio git:" al intentar hacer el git rm --cachepaso.
RickDT 01 de
9

Estos son los 4 pasos que encontré necesarios o útiles (los importantes primero):

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 teoría , git rmen el paso 1 debería ocuparse de ello. Con suerte, la segunda parte de la pregunta de OP se puede responder positivamente un día (que se puede hacer en un comando).

Pero a partir de julio de 2017, paso 2 es necesario para eliminar datos, .git/modules/de lo contrario, por ejemplo, no puede agregar el submódulo en el futuro.

Probablemente pueda salirse con los dos pasos anteriores para git 1.8.5+ como señaló la respuesta de tinlyx , ya que todos los git submodulecomandos parecen funcionar.

El paso 3 elimina la sección para the_submoduleen el archivo .git/config. Esto debe hacerse para completar. (La entrada puede causar problemas para versiones anteriores de git, pero no tengo una para probar).

Para esto, la mayoría de las respuestas sugieren usar git submodule deinit. Me resulta más explícito y menos confuso de usar git config -f .git/config --remove-section. De acuerdo con la documentación de git-submodule , git deinit:

Anular el registro de los submódulos dados ... Si realmente desea eliminar un submódulo del repositorio y confirmar que use git-rm [1] en su lugar .

Por último, pero no menos importante, si no lo hace git commit, recibirá / puede recibir un error al hacerlo git submodule summary(a partir de git 2.7):

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

Esto es independientemente de si realiza los pasos 2 o 3.

láser
fuente
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

fuente
7

Acabo de encontrar el archivo oculto .submodule (olvidé el nombre exacto), tiene una lista ... puedes borrarlos individualmente de esa manera. Acabo de tener uno, así que lo eliminé. Simple, pero podría estropear a Git, ya que no sé si hay algo adjunto al submódulo. Parece correcto hasta ahora, aparte del problema de actualización habitual de libetpan, pero eso (con suerte) no está relacionado.

Noté que nadie publicó borrado manual, así que agregó

Stephen J
fuente
Es.gitmodules
Arialdo Martini
7

Con git 2.17 y superior es solo:

git submodule deinit -f {module_name}
git add {module_name}
git commit
Albert Tobac
fuente
No funcionó, ni para git 2.17.1ni git 2.20.1. Sin embargo, en git rmlugar de git addtrabajar para ambos. Notas: -fno es necesario si las cosas están limpias. Asegúrese de no usar nunca opciones con gitsi desea protegerse contra la pérdida involuntaria de datos. También tenga en cuenta que esto deja .git/modules/{module_name}en su lugar. Es una buena práctica mantenerlo allí porque gitimprime la ayuda correcta (!) Sobre cómo proceder si algo está bloqueado debido a esto.
Tino
4

Si acaba de agregar el submódulo y, por ejemplo, simplemente agregó el submódulo incorrecto o lo agregó al lugar incorrecto, simplemente git stashelimine la carpeta. Esto supone que agregar el submódulo es lo único que hizo en el repositorio reciente.

botbot
fuente
3

Para el beneficio del lector, esto aquí trata de resumirlo y brindar una guía paso a paso sobre cómo hacerlo si las cosas no funcionan como se esperaba. A continuación se muestra la forma probada y segura para la gitversión 2.17y superior para deshacerse de un submódulo :

submodule="path/to/sub"              # no trailing slash!
git submodule deinit -- "$submodule"
git rm -- "$submodule"
  • Si esto no funciona para usted, consulte a continuación.
  • Sin opciones. Nada peligroso ¡Y ni siquiera consideres hacer más!
  • Probado con Debian Buster 2.20.1y Ubuntu 18.04 2.17.1.
  • "$submodule" es solo para enfatizar dónde poner el nombre, y que hay que tener cuidado con los espacios y similares
  • Si está en Windows, ignore la primera línea y reemplácela "$submodule"con la forma de Windows de una ruta de acceso especificada correctamente al submódulo. (No soy Windows)

¡Advertencia!

¡Nunca toque el interior del .gitdirectorio usted mismo! La edición en el interior .gitentra en el lado oscuro. Manténgase alejado a toda costa!

Y sí, puedes culpar gitpor esto, ya que muchas cosas útiles faltaban giten el pasado. Como una forma adecuada de eliminar submódulos nuevamente.

Creo que hay una parte muy peligrosa en la documentación de git submodule. Recomienda eliminarse $GIT_DIR/modules/<name>/. En mi opinión, esto no solo es incorrecto, ¡es extremadamente peligroso y provoca grandes dolores de cabeza en el futuro! Vea abajo.

Tenga en cuenta que

git module deinit

es el inverso directo de

git module init

pero

git submodule deinit -- module
git rm -- module

También es todo lo contrario a

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

porque algunos comandos básicamente necesitan hacer más que una sola cosa:

  • git submodule deinit -- module
    • (1) actualizaciones .git/config
  • git rm
    • (2) elimina los archivos del módulo
    • (3) elimina recursivamente los submódulos del submódulo
    • (4) actualizaciones .gitmodules
  • git submodule add
    • extrae los datos para .git/modules/NAME/
    • (1) sí git submodule init, así que actualizaciones.git/config
    • (2) git submodule update, por lo tanto, extrae el módulo de forma no recursiva
    • (4) actualizaciones .gitmodules
  • git submodule update --init --recursive -- module
    • extrae más datos si es necesario
    • (3) comprueba los submódulos del submódulo de forma recursiva

Esto no puede ser completamente simétrico, ya que mantenerlo estrictamente simétrico no tiene mucho sentido. Simplemente no hay necesidad de más de dos comandos. También "extraer los datos" está implícito, porque lo necesita, pero no se elimina la información almacenada en caché, porque esto no es necesario en absoluto y podría borrar datos valiosos.

Esto realmente es desconcertante para los recién llegados, pero básicamente es algo bueno: gitsimplemente hace lo obvio y lo hace bien, y ni siquiera trata de hacer más. gites una herramienta que debe hacer un trabajo confiable, en lugar de ser simplemente otra "Eierlegende Wollmilchsau" ("Eierlegende Wollmilchsau" se traduce para mí como "una versión malvada de una navaja suiza").

Entonces entiendo las quejas de la gente, diciendo "¿Por qué no hace gitlo obvio por mí?". Esto se debe a que "obvio" aquí depende del punto de vista. La fiabilidad en todas y cada una de las situaciones es mucho más importante. Por lo tanto, lo que es obvio para usted a menudo no es lo correcto en todas las situaciones técnicas posibles. Recuerde que: AFAICS gitsigue el camino técnico, no el social. (De ahí el nombre inteligente: git)

Si esto falla

Los comandos anteriores pueden fallar debido a lo siguiente:

  • Tu gites demasiado viejo. Luego usa uno nuevogit . (Vea a continuación cómo hacerlo).
  • Tiene datos no confirmados y puede perder datos. Entonces mejor comprometerlos primero.
  • Su submódulo no está limpio en un git clean sentido. Luego, primero limpie su submódulo usando ese comando. (Vea abajo.)
  • Has hecho algo en el pasado que no es compatible git. Entonces estás en el lado oscuro y las cosas se ponen feas y complicadas. (Quizás usar otra máquina lo arregle).
  • Tal vez hay más formas de fallar que no conozco (solo soy un gitusuario avanzado).

Posibles soluciones siguen.

Usa una nueva git

Si su máquina es demasiado vieja, no hay submodule deiniten su git. Si no desea (o no puede) actualizar su git, ¡simplemente use otra máquina con una más nueva git! gitestá destinado a estar completamente distribuido, por lo que puede usar otro gitpara hacer el trabajo:

  • workhorse:~/path/to/worktree$ git status --porcelain no debe dar salida a nada! Si es así, ¡primero limpia las cosas!
  • workhorse:~/path/to/worktree$ ssh account@othermachine
  • othermachine:~$ git clone --recursive me@workhorse path/to/worktree/.git TMPWORK && cd TMPWORK
  • Ahora haz las cosas del submódulo
  • 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 esto no funciona, usegit reset --soft FETCH_HEAD
  • Ahora limpie las cosas, hasta que git statusesté limpio nuevamente. Puede hacerlo, porque lo ha tenido limpio antes, gracias al primer paso.

Esto othermachinepuede ser alguna VM, o algún Ubuntu WSL bajo Windows, lo que sea. Incluso un chroot(pero supongo que usted no es root, porque si lo rootfuera, debería ser más fácil actualizar a la más reciente git).

Tenga en cuenta que si no puede sshentrar, existen muchas formas de transportar gitrepositorios. Puede copiar su árbol de trabajo en una memoria USB (incluido el .gitdirectorio) y clonar desde la memoria. Clone la copia, solo para que las cosas vuelvan a estar limpias. Esto podría ser un PITA, en caso de que sus submódulos no sean accesibles directamente desde otra máquina. Pero también hay una solución para esto:

git config --add url.NEWURLPREFIX.insteadOf ORIGINALURLPREFIX

Puede usar esta multiplicación, y esto se guarda en $HOME/.gitconfig. Algo como

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

reescribe URL como

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

dentro

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

Es fácil si comienza a acostumbrarse a gitfunciones potentes como esta.

Primero limpiar las cosas

La limpieza manual es buena, porque de esta manera quizás detecte algunas cosas que olvidó.

  • Si git se queja de cosas no guardadas, comprométalas y empújelas a un lugar seguro.
  • Si git se queja de algunas sobras, git statusy git clean -ixfdes tu amigo
  • Trate de abstenerse de las opciones rmy deinitsiempre que pueda. Las opciones (como -f) para gitson buenas si eres un profesional. Pero como vino aquí, probablemente no tenga tanta experiencia en el submoduleárea. Así que más vale prevenir que curar.

Ejemplo:

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

Ya ves, no hay -fnecesidad de submodule deinit. Si las cosas están limpias, en cierto git cleansentido. También tenga en cuenta que git clean -xno es necesario. Esto significa que git submodule deinitelimina incondicionalmente los archivos no rastreados que se ignoran. Esto suele ser lo que quieres, pero no lo olvides. A veces, los archivos ignorados pueden ser valiosos, como los datos almacenados en caché que tardan horas o días en calcularse nuevamente.

¿Por qué nunca eliminar $GIT_DIR/modules/<name>/?

Probablemente las personas quieran eliminar el repositorio en caché, porque tienen miedo de tener un problema más tarde. Esto es cierto, pero encontrarse con ese "problema" es la forma correcta de resolverlo. Debido a que la solución es fácil y si se hace bien, podrá vivir feliz para siempre. Esto evita problemas más engorrosos que cuando elimina los datos usted mismo.

Ejemplo:

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 última línea muestra el siguiente error:

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.

¿Por qué este error? Porque .git/modules/two/anteriormente se rellenó desde https://github.com/hilbix/empty.git y ahora se volverá a llenar de otra cosa, a saber, https://github.com/hilbix/src.git . No verá esto si lo vuelve a llenar desde https://github.com/hilbix/empty.git

¿Qué hacer ahora? Bueno, ¡haz exactamente lo que te dijeron! Utilizar--name someunusedname

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

.gitmodules entonces parece

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

ls -1p .git/modules/ da

someunusedname/
two/

De esta manera, en el futuro, puede cambiar ramas / commit hacia adelante y hacia atrás y nunca volverá a tener problemas , debido a que two/tiene dos repositorios ascendentes diferentes (y posiblemente incompatibles). Y lo mejor es: también mantiene ambos en caché localmente.

  • Esto no solo es cierto para ti. También es cierto para todos los demás que usan su repositorio.
  • Y no pierdes historia. En caso de que haya olvidado introducir la última versión del antiguo submódulo, puede ingresar la copia local y hacerlo más adelante. Tenga en cuenta que es bastante común que alguien se olvide de presionar algunos submódulos (porque esto es un PITA para los recién llegados, hasta que se acostumbren git).

Sin embargo, si eliminó el directorio almacenado en caché, ambos pagos diferentes se toparán entre sí, porque no utilizará las --nameopciones, ¿verdad? Entonces, cada vez que realice el pago, tal vez tenga que eliminar el .git/modules/<module>/directorio una y otra vez. Esto es extremadamente engorroso y hace que sea difícil usar algo así git bisect.

Por lo tanto, hay una razón muy técnica para mantener este directorio de módulos como marcador de posición. Las personas que recomiendan eliminar algo a continuación .git/modules/no lo saben mejor o se olvidan de decirle que esto hace que las funciones potentes sean git bisectcasi imposibles de usar si cruza esa incompatibilidad de submódulos.

Otra razón se muestra arriba. Mira el ls. Que ves alli

Bueno, la segunda variante del módulo two/no está debajo .git/modules/two/, ¡está debajo .git/modules/someunusedname/! ¡Así que cosas como git rm $module; rm -f .git/module/$moduleestán totalmente mal! ¡Debes consultar module/.gito .gitmodulesencontrar lo correcto para eliminar!

Entonces, no solo la mayoría de las otras respuestas caen en esta peligrosa trampa, incluso las gitextensiones muy populares tenían este error ( ahora está solucionado )! ¡Así que mejor mantenga sus manos en el .git/directorio si no lo hace exactamente, lo que está haciendo!

Y desde el punto de vista filosófico, ¡borrar la historia siempre está mal! Excepto por la mecánica cuántica , como de costumbre, pero esto es algo completamente diferente.

Para tu información, probablemente lo hayas adivinado: hilbix es mi cuenta de GitHub.

Tino
fuente
Esta enciclopedia de una publicación debe dividirse en secciones más claras con subtítulos más grandes / claros para indicar la respuesta real, y las diferentes secciones de "solución de problemas" / etc.
Andrew
2

Para resumir, esto es lo que debe hacer:

Establezca path_to_submodule var (sin barra inclinada):

path_to_submodule=path/to/submodule

Elimine la línea relevante del archivo .gitmodules:

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

Eliminar la sección relevante de .git / config

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

Desensamblar y eliminar $ path_to_submodule solo del índice (para evitar perder información)

git rm --cached $path_to_submodule

Rastree los cambios realizados en .gitmodules

git add .gitmodules

Cometer el superproyecto

git commit -m "Remove submodule submodule_name"

Eliminar los archivos de submódulos ahora sin seguimiento

rm -rf $path_to_submodule

rm -rf .git/modules/$path_to_submodule

Ver también: líneas de guía alternativas

Rahul Dapke
fuente
¿Puede extender esto con cómo eliminar un submódulo después de un 'git submodule add' pero sin haberlo cometido? Supongo que en ese caso no se necesita confirmación para eliminar el submódulo, ¿verdad?
Carlo Wood
Creo que necesitas cambiar el git rm --cached $path_to_submoduley git add .gitmodulesno? Obtuve un error en el primer comando: fatal: Please stage your changes to .gitmodules or stash them to proceedporque tenía cambios no organizados en .gitmodules. Hacer lo git add .gitmodulesprimero resuelve eso.
Carlo Wood
2

Eso es fácil:

  1. Eliminar la sección de .gitmodules
  2. Llamada: git add .gitmodules
  3. Llamada: git submodule deinit <path to submodule>
  4. Llamada: git rm <path to submodule>
  5. Comprometerse y empujar

Tendrá que eliminar los archivos del módulo en su proyecto manualmente.

Negro
fuente
2
Para mí fue suficiente para llamar git submodule deinit <submodule_name>y git rm <path_to_submodule>. El último comando elimina automáticamente la entrada dentro de .gitmodules. Git 2.17
Dmytro Ovdiienko
0

En el último git solo se necesita 4 operaciones para eliminar el submódulo git.

  • Eliminar la entrada correspondiente en .gitmodules
  • Cambios de escenario git add .gitmodules
  • Eliminar el directorio de submódulos git rm --cached <path_to_submodule>
  • Comprometerlo git commit -m "Removed submodule xxx"
rashok
fuente
0

En caso de que necesite hacerlo en un comando de línea con el script bash como se muestra a continuación:

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

Cree un archivo de script bash en el $HOMEdirectorio llamado 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
fuente
0
  • Un submódulo se puede eliminar ejecutando git rm <submodule path> && git commit. Esto se puede deshacer usando git revert.
    • La eliminación elimina los datos de seguimiento del superproyecto, que son tanto la entrada de gitlink como la sección del .gitmodulesarchivo.
    • El directorio de trabajo del submódulo se elimina del sistema de archivos, pero el directorio de Git se mantiene para permitir la comprobación de las confirmaciones anteriores sin requerir la obtención de otro repositorio.
  • Para eliminar completamente un submódulo, adicionalmente elimínelo manualmente$GIT_DIR/modules/<name>/ .

Fuente: git help submodules

Nikhil
fuente
-1

Eliminar el submódulo git

Para eliminar un gitsubmódulo debajo de 4 pasos son necesarios.

  1. Elimine la entrada correspondiente en el .gitmodulesarchivo. La entrada puede ser como se menciona a continuación
[submodule "path_to_submodule"]
    path = path_to_submodule
    url = url_path_to_submodule
  1. Cambios de escenario git add .gitmodules
  2. Elimine el directorio de submódulos git rm --cached <path_to_submodule>.
  3. Compromételo git commit -m "Removed submodule xxx"y empuja.

Se necesitan 2 pasos adicionales adicionales que se mencionan a continuación para limpiar completamente el submódulo en una copia clonada local.

  1. Elimine la entrada correspondiente en el .git/configarchivo. La entrada puede ser como se menciona a continuación
[submodule "path_to_submodule"]
    url = url_path_to_submodule
  1. Hacer rm -rf .git/modules/path_to_submodule

Estos pasos quinto y sexto no crean ningún cambio que deba comprometerse.

rashok
fuente
Sería mucho más fácil si usara git submodule deinit git-scm.com/docs/git-submodule#Documentation/…
Negro