¿Cómo trabajo con un repositorio git dentro de otro repositorio?

283

Tengo un repositorio de medios Git donde guardo todos mis archivos y scripts maestros de JavaScript y CSS que usaré en varios proyectos.

Si creo un nuevo proyecto que está en su propio repositorio de Git, ¿cómo utilizo los archivos JavaScript de mi repositorio de medios en mi nuevo proyecto de manera tal que no tenga que actualizar ambas copias del script cuando realice cambios? ?

Brent O'Connor
fuente
Consulte la respuesta del subárbol a continuación de @ ruslan-kabalin. Nota: los ganchos de precompromiso (o sobrecompromiso ) son una forma de lidiar con la objeción planteada por Robert Dundon
Erizo

Respuestas:

347

La clave son los submódulos git .

Comience a leer el capítulo Submódulos del Libro de la comunidad de Git o del Manual del usuario

Digamos que tiene el repositorio PROJECT1, PROJECT2 y MEDIA ...

cd /path/to/PROJECT1
git submodule add ssh://path.to.repo/MEDIA
git commit -m "Added Media submodule"

Repita en el otro repositorio ...

Ahora, lo bueno es que cada vez que confirmes cambios en MEDIA, puedes hacer esto:

cd /path/to/PROJECT2/MEDIA
git pull
cd ..
git add MEDIA
git commit -m "Upgraded media to version XYZ"

Esto acaba de registrar el hecho de que el submódulo MEDIA WITHIN PROJECT2 está ahora en la versión XYZ.

Le da el 100% de control sobre qué versión de MEDIA usa cada proyecto. Los submódulos git son geniales, pero necesitas experimentar y aprender sobre ellos.

Con un gran poder viene la gran oportunidad de ser mordido en la grupa.

gahooa
fuente
Este flujo de trabajo me recuerda el uso de un módulo NPM privado stackoverflow.com/questions/7575627/…
cyrf
Si prefiere que la versión predeterminada sea la última, puede agregar un script para propagar el compromiso MEDIA a todos los proyectos dependientes.
jiggunjer
3
¿Cómo se integra esto con github?
theonlygusti
26

Considere usar subárbol en lugar de submódulos, hará que la vida de los usuarios de repositorios sea mucho más fácil. Puede encontrar una guía más detallada en el libro Pro Git .

Ruslan Kabalin
fuente
66
Aquí hay otro artículo informativo sobre subtree vs. submodule: blogs.atlassian.com/2013/05/…
Benny Neugebauer
3
Según ese artículo, uno de los inconvenientes es:> La responsabilidad de no mezclar código super y subproyecto en commits recae en usted. Nadie tuvo tiempo para eso (IMO)
Robert Dundon
20

Si entiendo bien tu problema, quieres lo siguiente:

  1. Tenga sus archivos multimedia almacenados en un único repositorio git, que es utilizado por muchos proyectos
  2. Si modifica un archivo multimedia en cualquiera de los proyectos en su máquina local, debería aparecer inmediatamente en cualquier otro proyecto (por lo que no desea comprometerse + empujar + jalar todo el tiempo)

Desafortunadamente, no hay una solución definitiva para lo que desea, pero hay algunas cosas con las que puede facilitarle la vida.

Primero debe decidir una cosa importante: ¿desea almacenar para cada versión en el repositorio de su proyecto una referencia a la versión de los archivos multimedia? Entonces, por ejemplo, si tiene un proyecto llamado example.com, ¿necesita saber qué style.css usó hace 2 semanas, o el último es siempre (o mayormente) el mejor?

Si no necesita saber eso, la solución es fácil:

  1. crear un repositorio para los archivos multimedia y uno para cada proyecto
  2. cree un enlace simbólico en sus proyectos que apunte al repositorio de medios clonado localmente. Puede crear un enlace simbólico relativo (por ejemplo, ../media) y asumir que todos verificarán el proyecto para que el directorio de medios esté en el mismo lugar, o escribir el nombre del enlace simbólico en .gitignore, y todos podrán decidir donde él / ella pone los archivos multimedia.

Sin embargo, en la mayoría de los casos, desea conocer esta información de versiones. En este caso tienes dos opciones:

  1. Almacene cada proyecto en un gran repositorio. La ventaja de esta solución es que solo tendrá 1 copia del repositorio de medios. La gran desventaja es que es mucho más difícil cambiar entre versiones de proyecto (si realiza el pago a una versión diferente, siempre modificará TODOS los proyectos)

  2. Use submódulos (como se explica en la respuesta 1). De esta manera, almacenará los archivos de medios en un repositorio, y los proyectos contendrán solo una referencia a una versión específica de repositorio de medios. Pero de esta manera normalmente tendrá muchas copias locales del repositorio de medios, y no puede modificar fácilmente un archivo de medios en todos los proyectos.

Si yo fuera usted, probablemente elegiría la primera o tercera solución (enlaces simbólicos o submódulos). Si elige usar submódulos, aún puede hacer muchas cosas para facilitarle la vida:

  1. Antes de comprometerse, puede cambiar el nombre del directorio de submódulos y poner un enlace simbólico a un directorio de medios común. Cuando esté listo para confirmar, puede eliminar el enlace simbólico y eliminar el submódulo de nuevo, y luego confirmar.

  2. Puede agregar una de sus copias del repositorio de medios como un repositorio remoto a todos sus proyectos.

Puede agregar directorios locales como remotos de esta manera:

cd /my/project2/media
git remote add project1 /my/project1/media

Si modifica un archivo en / my / project1 / media, puede confirmarlo y extraerlo de / my / project2 / media sin enviarlo a un servidor remoto:

cd /my/project1/media
git commit -a -m "message"
cd /my/project2/media
git pull project1 master

Puede eliminar estas confirmaciones más tarde (con git reset) porque no las ha compartido con otros usuarios.

Gyim
fuente
1
para proyectos relacionados con la web en los que trabaja desde la wwwcarpeta de Apache , debe colocar un .htaccessarchivo en la raíz de la wwwcarpeta o de su proyecto, Options +FollowSymLinksdentro o mejor aún <IfModule mod_rewrite.c>{new line}Options +FollowSymLinks{new line}RewriteEngine on{new line}</IfModule> (reemplazar {new line}con una nueva línea real ')
3

Tuve problemas con los subárboles y submódulos que sugieren las otras respuestas ... principalmente porque estoy usando SourceTree y parece bastante defectuoso.

En cambio, terminé usando SymLinks y eso parece funcionar bien, así que lo estoy publicando aquí como una posible alternativa.

Aquí hay una guía completa: http://www.howtogeek.com/howto/16226/complete-guide-to-symbolic-links-symlinks-on-windows-or-linux/

Pero básicamente solo necesita vincular las dos rutas en un símbolo del sistema elevado. Asegúrese de usar el prefijo de enlace duro / J. Algo en este sentido: mklink / JC: \ projects \ MainProject \ plugins C: \ projects \ SomePlugin

También puede usar rutas de carpetas relativas y ponerlas en un bate para que cada persona las ejecute cuando comprueben su proyecto por primera vez.

Ejemplo: mklink / J. \ Assets \ TaqtileTools .. \ TaqtileHoloTools

Una vez que se ha vinculado la carpeta, es posible que deba ignorar la carpeta dentro de su repositorio principal que hace referencia a ella. De lo contrario, eres bueno para ir.

Tenga en cuenta que he eliminado mi respuesta duplicada de otra publicación ya que esa publicación se marcó como una pregunta duplicada para esta.

ickydime
fuente