¿Cómo agrego un submódulo a un subdirectorio?

310

Tengo un repositorio de git ~/.janus/con un montón de submódulos. Quiero agregar un submódulo ~/.janus/snipmate-snippets/snippets/, pero cuando ejecuto git submodule add <[email protected]:...>en el snipmate-snippetsdirectorio, aparece el siguiente mensaje de error:

You need to run this command from the toplevel of the working tree.

Entonces la pregunta es: ¿Cómo agrego un submódulo al snipmate-snippetsdirectorio?

Robert Audi
fuente
Ir al directorio raíz de un repositorio de git para comandos de submódulo ya no será un requisito (pronto). Vea mi respuesta a continuación
VonC 01 de
3
git submodule add -b <branch> <url> <relative_path_4m_root>
parroquial

Respuestas:

439

Entras ~/.janusy corres:

git submodule add <git@github ...> snipmate-snippets/snippets/

Si necesita más información sobre submódulos (o git en general) ProGit es bastante útil.

BergmannF
fuente
parece una buena idea agregar una rama cuando se agrega; de lo contrario, HEAD se separa fácilmente: git submodule add -b <branch> <repository> [<submodule-path>]
deann
1
Para mí esto estaba causando 'subprojects' already exists in the index (estaba usando subproyectos como el nombre del directorio) . En cambio, lo que ayudó, es la respuesta de VonC a continuación, es decir cd subprojects, hacer , y luego git submodule add <get@github …>sin el camino.
Hola Ángel, el
83

Tenga en cuenta que a partir de git1.8.4 (julio de 2013), ya no tendrá que volver al directorio raíz.

 cd ~/.janus/snipmate-snippets
 git submodule add <git@github ...> snippets

( Bouke Versteegh comenta que no tiene que usar /., como en snippets/.: snippetses suficiente)

Ver commit 091a6eb0feed820a43663ca63dc2bc0bb247bbae :

submódulo: elimine el requisito de nivel superior

Use la nueva rev-parse --prefixopción para procesar todas las rutas dadas al comando del submódulo, eliminando el requisito de que se ejecute desde el nivel superior del repositorio.

Dado que la interpretación de una URL de submódulo relativa depende de si " remote.origin.url" está configurado o no , bloquee explícitamente las URL relativas en " git submodule add" cuando no esté en el nivel superior del árbol de trabajo.

Firmado por: John Keeping

Depende de commit 12b9d32790b40bf3ea49134095619700191abf1f

Esto hace que ' git rev-parse' se comporte como si fuera invocado desde el subdirectorio especificado de un repositorio, con la diferencia de que cualquier ruta de archivo que imprima tiene el prefijo de la ruta completa desde la parte superior del árbol de trabajo .

Esto es útil para los scripts de shell donde podemos querer llegar a cdla parte superior del árbol de trabajo pero necesitamos manejar rutas relativas dadas por el usuario en la línea de comando.

VonC
fuente
¡Muchas gracias! Noté que el seguimiento /.no es necesario, git creará los fragmentos de directorio sin él.
Bouke Versteegh
@BoukeVersteegh Interesante. He incluido tu comentario en la respuesta para mayor visibilidad.
VonC
Estoy en git versión 2.7.4 pero aún recibo este mensaje de error Relative path can only be used from the toplevel of the working tree. Estoy haciendogit submodule add ../../../functest
FlyingAura
@ user3426358 sí, eso es de esperar: la respuesta anterior es sobre la capacidad de agregar un submoduel git desde cualquier subcarpeta del repositorio principal, no solo desde su carpeta raíz. No se trata de hacer referencia al repositorio remoto de submódulo con una ruta relativa. Si lo hace, recibirá el mensaje de error que ve.
VonC
@ user3426358 Y, por cierto, ese mensaje de error (que ves: " Relative path can only be used from the toplevel of the working tree") no es el de la pregunta original (" You need to run this command from the toplevel of the working tree")
VonC
17

Tuve un problema similar, pero me pinté en una esquina con herramientas GUI.

Tenía un subproyecto con algunos archivos que hasta ahora había copiado en lugar de registrarme en su propio repositorio de git. Creé un repositorio en la subcarpeta, pude confirmar, enviar, etc. bien. Pero en el repositorio principal, la subcarpeta no se trataba como un submódulo, y el repositorio principal seguía rastreando sus archivos, lo cual no era bueno.

Para salir de este lío, tuve que decirle a Git que dejara de rastrear la subcarpeta (sin eliminar los archivos):

proj> git rm -r --cached ./ui/jslib

Luego tuve que decirle que había un submódulo allí (que no puede hacer si hay algo que actualmente está siendo rastreado por git):

proj> git submodule add ./ui/jslib

Actualizar

La forma ideal de manejar esto implica un par de pasos más. Idealmente, el repositorio existente se mueve a su propio directorio, libre de cualquier módulo git principal, se confirma y empuja, y luego se agrega como un submódulo como:

proj> git submodule add [email protected]:user/jslib.git ui/jslib

Eso clonará el repositorio de git como un submódulo, que implica los pasos de clonación estándar, pero también varios otros pasos de configuración más oscuros que git toma en su nombre para que ese submódulo funcione. La diferencia más importante es que coloca un archivo .git simple allí, en lugar de un directorio .git, que contiene una referencia de ruta a donde vive el directorio git real, generalmente en la raíz principal del proyecto .git / modules / jslib.

Si no haces las cosas de esta manera, funcionarán bien para ti, pero tan pronto como te comprometes y presionas al padre, y otro desarrollador va a tirar de ese padre, simplemente les harás la vida mucho más difícil. Será muy difícil para ellos replicar la estructura que tiene en su máquina siempre que tenga un directorio .git completo en una subcarpeta de un directorio que contenga su propio directorio .git.

Entonces, mover, empujar, git agregar submódulo, es la opción más limpia.

Chris Moschini
fuente
16

Para aquellos de ustedes que comparten mi extraño gusto por editar manualmente los archivos de configuración, agregar (o modificar) lo siguiente también sería el truco.

.git / config (configuración personal)

[submodule "cookbooks/apt"]
    url = https://github.com/opscode-cookbooks/apt

.gitmodules (configuración compartida comprometida)

[submodule "cookbooks/apt"]
    path = cookbooks/apt
    url = https://github.com/opscode-cookbooks/apt

Vea esto también: ¿ diferencia entre .gitmodules y especificación de submódulos en .git / config?

yoniLavi
fuente
2

guión bash de una línea para ayudar a facilitar la respuesta de Chris anterior, ya que también me había pintado en una esquina usando las actualizaciones de Vundle para mis guiones .vim. DESTes la ruta al directorio que contiene sus submódulos. Haz esto después de hacergit rm -r $DEST

DEST='path'; for file in `ls ${DEST}`; do git submodule add `grep url ${DEST}/${file}/.git/config|awk -F= '{print $2}'` ${DEST}/${file}; done

salud

Rick R
fuente