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.
git rm modulenameyrm -rf .git/modules/modulename