¿Cómo se organizan varios repositorios de git, para que todos estén respaldados juntos?

98

Con SVN, tenía un único repositorio grande que guardaba en un servidor y revisaba algunas máquinas. Este era un sistema de respaldo bastante bueno y me permitió trabajar fácilmente en cualquiera de las máquinas. Podría verificar un proyecto específico, comprometerme y actualizar el proyecto 'maestro', o podría verificar todo.

Ahora, tengo un montón de repositorios de git, para varios proyectos, varios de los cuales están en github. También tengo el repositorio SVN que mencioné, importado a través del comando git-svn.

Básicamente, me gusta tener todo mi código (no solo proyectos, sino fragmentos y scripts aleatorios, algunas cosas como mi CV, artículos que he escrito, sitios web que he creado, etc.) en un gran repositorio que puedo clonar fácilmente en un control remoto. máquinas o tarjetas de memoria / discos duros como copia de seguridad.

El problema es que, dado que es un repositorio privado, y git no permite la verificación de una carpeta específica (que podría enviar a github como un proyecto separado, pero que los cambios aparezcan tanto en el repositorio principal como en el secundario repos)

Yo podría utilizar el sistema git submódulo, pero no actuar como quiero demasiado (submódulos son punteros a otros repositorios, y realmente no contienen el código real, por lo que es inútil para la copia de seguridad)

Actualmente tengo una carpeta de git-repos (por ejemplo, ~ / code_projects / proj1 / .git / ~ / code_projects / proj2 / .git /), y después de hacer cambios en proj1 lo hago git push github, luego copio los archivos en ~ / Documente / código / python / proyectos / proj1 / y haga una única confirmación (en lugar de las numerosas en los repositorios individuales). Entonces hazlo git push backupdrive1, git push mymemorysticketc.

Entonces, la pregunta: ¿Cómo funcionan su código personal y sus proyectos con repositorios de git y cómo mantenerlos sincronizados y respaldados?

dbr
fuente

Respuestas:

74

Recomiendo encarecidamente no poner datos no relacionados en un repositorio de Git determinado. La sobrecarga de crear nuevos repositorios es bastante baja, y esa es una característica que hace posible mantener diferentes linajes completamente separados.

Luchar contra esa idea significa terminar con una historia innecesariamente enredada, lo que hace que la administración sea más difícil y, lo que es más importante, las herramientas de "arqueología" menos útiles debido a la dilución resultante. Además, como mencionaste, Git asume que la "unidad de clonación" es el repositorio, y prácticamente tiene que hacerlo debido a su naturaleza distribuida.

Una solución es mantener cada proyecto / paquete / etc. como su propio repositorio desnudo (es decir, sin árbol de trabajo) bajo una jerarquía bendita, como:

/repos/a.git
/repos/b.git
/repos/c.git

Una vez que se han establecido algunas convenciones, resulta trivial aplicar operaciones administrativas (copia de seguridad, empaquetado, publicación web) a la jerarquía completa, que cumple una función no del todo diferente a los repositorios SVN "monolíticos". Trabajar con estos repositorios también se vuelve algo similar a los flujos de trabajo SVN, con la adición de que uno puede usar confirmaciones y ramas locales:

svn checkout   --> git clone
svn update     --> git pull
svn commit     --> git push

Puede tener múltiples controles remotos en cada clon de trabajo, para facilitar la sincronización entre las múltiples partes:

$ cd ~/dev
$ git clone /repos/foo.git       # or the one from github, ...
$ cd foo
$ git remote add github ...
$ git remote add memorystick ...

Luego puede buscar / extraer de cada una de las "fuentes", trabajar y confirmar localmente, y luego presionar ("respaldo") a cada uno de estos controles remotos cuando esté listo con algo como (observe cómo eso empuja las mismas confirmaciones e historial a cada uno de los mandos a distancia!):

$ for remote in origin github memorystick; do git push $remote; done

La forma más fácil de convertir un repositorio de trabajo existente ~/dev/foo en un repositorio tan simple es probablemente:

$ cd ~/dev
$ git clone --bare foo /repos/foo.git
$ mv foo foo.old
$ git clone /repos/foo.git

que es mayormente equivalente a un - svn importpero no descarta la historia "local" existente.

Nota: los submódulos son un mecanismo para incluir linajes relacionados compartidos , por lo que de hecho no los consideraría una herramienta adecuada para el problema que está tratando de resolver.

Damien Diederen
fuente
18
El hecho de que sigo terminando con muchos repositorios separados y escribiendo scripts simples para ayudar a administrarlos me hace sentir que falta algo en git. Simplemente no puedo decidir exactamente qué es o qué hacer al respecto.
DonGar
Bueno, ¿también gestiona muchos proyectos separados? Una relación uno a uno entre proyectos y repositorios se siente razonable en un mundo distribuido, pero aún así organizaría los repositorios desnudos en un árbol de directorio común para facilitar la copia de seguridad y la administración. (En otras palabras, Git / Hg / Bzr te obliga a separar la administración de las tareas del proyecto, mientras que la mayoría de los flujos de trabajo de SVN combinan las dos; ahora es común ver a las personas delegar la parte administrativa en GitHub u otros proveedores similares)
Damien Diederen
2
esta idea solo tiene sentido si aloja sus propios proyectos y / o todos son de código abierto. De lo contrario, necesitaría en github, necesitaría proyectos privados ilimitados que podrían ser costosos
dkinzer
2
En lugar de "para github memorystick de origen remoto; git push $ remote; hecho", también se puede configurar un control remoto especial para empujar con un solo comando a muchos controles remotos: stackoverflow.com/questions/36862/… . (Podría ser más conveniente en algunos casos.)
imz - Ivan Zakharyaschev
2
Creo que lo que falta es una forma en que git puede mantener sus objetos separados por subárbol para que un único "repositorio" pueda estar compuesto de unidades separadas sincronizadas aunque separables (descargadas individualmente sin el resto) de tal manera que las personas puedan trabajar en subconjuntos sin conocer el resto.
peterk
28

Quiero agregar a la respuesta de Damien donde recomienda:

$ for remote in origin github memorystick; do git push $remote; done

Puede configurar un control remoto especial para presionar a todos los controles remotos reales individuales con 1 comando; Lo encontré en http://marc.info/?l=git&m=116231242118202&w=2 :

Entonces, para "git push" (donde tiene sentido empujar las mismas ramas varias veces), puedes hacer lo que yo hago:

  • .git / config contiene:

    [remote "all"]
    url = master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6
    url = login.osdl.org:linux-2.6.git
    
  • y ahora git push all masterempujará la rama "maestra" a ambos
    repositorios remotos.

También puedes ahorrarte escribir las URL dos veces usando la construcción:

[url "<actual url base>"]
    insteadOf = <other url base>
imz - Ivan Zakharyaschev
fuente
3

También tengo curiosidad por las formas sugeridas de manejar esto y describiré la configuración actual que uso (con SVN). Básicamente, he creado un repositorio que contiene una jerarquía de mini-sistema de archivos que incluye sus propios directorios bin y lib. Hay un script en la raíz de este árbol que configurará su entorno para agregar estos directorios bin, lib, etc ... a las variables de entorno adecuadas. Entonces, el directorio raíz esencialmente se ve así:

./bin/            # prepended to $PATH
./lib/            # prepended to $LD_LIBRARY_PATH
./lib/python/     # prepended to $PYTHONPATH
./setup_env.bash  # sets up the environment

Ahora, dentro de / bin y / lib están los múltiples proyectos y sus bibliotecas correspondientes. Sé que este no es un proyecto estándar, pero es muy fácil para alguien más en mi grupo verificar el repositorio, ejecutar el script 'setup_env.bash' y tener las versiones más actualizadas de todos los proyectos localmente en su revisa. No tienen que preocuparse por instalar / actualizar / usr / bin o / usr / lib y hace que sea sencillo tener múltiples pagos y un entorno muy localizado por pago. Alguien también puede simplemente administrar todo el repositorio y no preocuparse por desinstalar ningún programa.

Esto nos está funcionando bien y no estoy seguro de si lo cambiaremos. El problema con esto es que hay muchos proyectos en este gran repositorio. ¿Existe una forma estándar de git / Hg / bzr de crear un entorno como este y dividir los proyectos en sus propios repositorios?

Danny G
fuente
3

, Todavía no he intentado anidar repositorios de git porque no me he encontrado con una situación en la que sea necesario. Como he leído en el canal #git, git parece confundirse al anidar los repositorios, es decir, estás intentando git-init dentro de un repositorio de git. La única forma de administrar una estructura git anidada es usar git-submoduleo Androidrepo utilidad .

En cuanto a la responsabilidad de la copia de seguridad que estás describiendo, digo que la delegues ... Para mí, normalmente coloco el repositorio de "origen" para cada proyecto en una unidad de red en el trabajo que los técnicos de TI respaldan periódicamente mediante su estrategia de copia de seguridad de elección. Es simple y no tengo que preocuparme por eso. ;)

Spoike
fuente
2

¿Qué hay de usar mr para administrar sus múltiples repositorios Git a la vez?

El comando mr (1) puede verificar, actualizar o realizar otras acciones en un conjunto de repositorios como si fueran un repositorio combinado. Es compatible con cualquier combinación de repositorios subversion, git, cvs, mercurial, bzr, darcs, cvs, vcsh, fossil y veracity, y se puede agregar fácilmente soporte para otros sistemas de control de revisiones. [...]

Es extremadamente configurable a través de un simple script de shell. Algunos ejemplos de cosas que puede hacer incluyen:

[...]

  • Al actualizar un repositorio de git, extraiga de dos fuentes ascendentes diferentes y combine las dos.
  • Ejecute varias actualizaciones del repositorio en paralelo, acelerando enormemente el proceso de actualización.
  • Recuerde las acciones que fallaron debido a que una computadora portátil está fuera de línea, para que se puedan volver a intentar cuando vuelva a estar en línea.
imz - Ivan Zakharyaschev
fuente
1

Existe otro método para tener repositorios git anidados, pero no resuelve el problema que busca. Aún así, para otros que buscan la solución yo estaba:

En el repositorio de git de nivel superior, simplemente oculte la carpeta en .gitignore que contiene el repositorio de git anidado. Esto hace que sea fácil tener dos repositorios git separados (¡pero anidados!).

arxpoetica
fuente