¿Cómo muevo un submódulo Git existente dentro de un repositorio Git?
Me gustaría cambiar el nombre del directorio de un submódulo de Git en mi superproyecto de Git.
Supongamos que tengo la siguiente entrada en mi .gitmodules
archivo:
[submodule ".emacs.d/vimpulse"]
path = .emacs.d/vimpulse
url = git://gitorious.org/vimpulse/vimpulse.git
¿Qué tengo que escribir para mover el .emacs.d/vimpulse
directorio .emacs.d/vendor/vimpulse
sin borrarlo primero (explicado
aquí y aquí ) y luego volver a agregarlo?
¿Git realmente necesita la ruta completa en la etiqueta del submódulo?
[submodule ".emacs.d/vimpulse"]
¿O también es posible almacenar solo el nombre del subproyecto?
[submodule "vimpulse"]
Versiones más nuevas de git
Git ahora tiene soporte nativo para mover submódulos:
Desde git 1.8.5,
git mv old/submod new/submod
funciona como se esperaba y hace todo el trabajo por usted. Es posible que desees utilizar git 1.9.3 o posterior, porque incluye correcciones para el movimiento de submódulos.
Versiones anteriores de git
Como se menciona en los comentarios, esta respuesta se refiere a los pasos necesarios con versiones anteriores de git.
El proceso es similar a cómo eliminaría un submódulo (consulte ¿ Cómo elimino un submódulo? ):
Edite
.gitmodules
y cambie la ruta del submódulo adecuadamente y colóquelo en el índice congit add .gitmodules
.Si es necesario, cree el directorio principal de la nueva ubicación del submódulo (
mkdir -p new/parent
).Mueva todo el contenido del directorio antiguo al nuevo (
mv -vi old/parent/submodule new/parent/submodule
).Asegúrese de que Git rastree este directorio (
git add new/parent
).Elimine el directorio antiguo con
git rm --cached old/parent/submodule
.Mueva el directorio
.git/modules/old/parent/submodule
con todo su contenido a.git/modules/new/parent/submodule
.Edite el
.git/modules/new/parent/config
archivo, asegúrese de que el elemento del árbol de trabajo apunte a las nuevas ubicaciones, por lo que en este ejemplo debería serworktree = ../../../../../new/parent/module
. Normalmente debería haber dos..
directorios más en la ruta directa en ese lugar.Edite el archivo
new/parent/module/.git
, asegúrese de que la ruta que contiene apunte a la nueva ubicación correcta dentro de la.git
carpeta principal del proyecto, como en este ejemplogitdir: ../../../.git/modules/new/parent/submodule
.git status
La salida se ve así para mí después:# On branch master # Changes to be committed: # (use "git reset HEAD <file>..." to unstage) # # modified: .gitmodules # renamed: old/parent/submodule -> new/parent/submodule #
Finalmente, confirme los cambios.
La respuesta más moderna, tomada del comentario anterior de Valloric:
- Actualice a Git 1.9.3 (o 2.18 si el submódulo contiene submódulos anidados )
git mv old/submod new/submod
- Luego, los .gitmodules y el directorio del submódulo ya están preparados para una confirmación (puedes verificar esto con
git status
.) - Confirma los cambios
git commit
y ¡listo!
¡Hecho!
En mi caso, quería mover un submódulo de un directorio a un subdirectorio, por ejemplo, "AFNetworking" -> "ext/AFNetworking". Estos son los pasos que seguí:
- Edite .gitmodules cambiando el nombre y la ruta del submódulo para que sea "ext/AFNetworking"
- Mueva el directorio git del submódulo de ".git/modules/AFNetworking" a ".git/modules/ext/AFNetworking"
- Mover la biblioteca de "AFNetworking" a "ext/AFNetworking"
- Edite ".git/modules/ext/AFNetworking/config" y corrija la
[core] worktree
línea. El mio cambio de../../../AFNetworking
a../../../../ext/AFNetworking
- Edite "ext/AFNetworking/.git" y corrija
gitdir
. El mío cambió de../.git/modules/AFNetworking
a../../git/modules/ext/AFNetworking
git add .gitmodules
git rm --cached AFNetworking
git submodule add -f <url> ext/AFNetworking
Finalmente, vi en el estado de git:
matt$ git status
# On branch ios-master
# Changes to be committed:
# (use "git reset HEAD <file>..." to unstage)
#
# modified: .gitmodules
# renamed: AFNetworking -> ext/AFNetworking
Y listo. El ejemplo anterior no cambia la profundidad del directorio, lo que marca una gran diferencia en la complejidad de la tarea, y no cambia el nombre del submódulo (que puede que no sea realmente necesario, pero lo hice para ser coherente con lo que sucedería si agregara un nuevo módulo en esa ruta).
[Actualización: 2014-11-26] Como Yar resume muy bien a continuación, antes de hacer cualquier cosa, asegúrese de conocer la URL del submódulo. Si la desconoce, abra .git/.gitmodules
y examine la clave submodule.<name>.url
.
Lo que funcionó para mí fue eliminar el submódulo antiguo usando git submodule deinit <submodule>
seguido de git rm <submodule-folder>
. Luego agregue el submódulo nuevamente con el nuevo nombre de la carpeta y confirme. Verificar el estado de git antes de confirmar muestra el antiguo submódulo renombrado al nuevo nombre y .gitmodule modificado.
$ git submodule deinit foo
$ git rm foo
$ git submodule add https://bar.com/foo.git new-foo
$ git status
renamed: foo -> new-foo
modified: .gitmodules
$ git commit -am "rename foo submodule to new-foo"
El truco parece ser comprender que el .git
directorio de los submódulos ahora se guarda en el repositorio principal, en .git/modules
, y cada submódulo tiene un .git
archivo que apunta a él. Este es el procedimiento que necesitas ahora:
- Mueva el submódulo a su nuevo hogar.
- Edite el
.git
archivo en el directorio de trabajo del submódulo y modifique la ruta que contiene para que apunte al directorio correcto en el.git/modules
directorio del repositorio maestro. - Ingrese al
.git/modules
directorio del repositorio maestro y busque el directorio correspondiente a su submódulo. - Edite el
config
archivo, actualizando laworktree
ruta para que apunte a la nueva ubicación del directorio de trabajo del submódulo. - Edite el
.gitmodules
archivo en la raíz del repositorio maestro, actualizando la ruta al directorio de trabajo del submódulo. git add -u
git add <parent-of-new-submodule-directory>
(Es importante que agregue el directorio principal y no el directorio del submódulo en sí).
Algunas notas:
- Las
[submodule "submodule-name"]
líneas en.gitmodules
y.git/config
deben coincidir entre sí, pero no corresponden a nada más. - El directorio de trabajo del submódulo y
.git
el directorio deben apuntar correctamente entre sí. - Los archivos
.gitmodules
y.git/config
deben estar sincronizados.