2010-09-08 10 views
26

Tenemos una configuración de dos niveles.¿Mantiene automáticamente un repositorio secundario en sincronización con un repositorio primario?

Tenemos un repositorio principal (llamado 'primario' a continuación).

Y un depósito secundario (denominado 'secundario' más adelante) que se ha creado de esta manera:

$ git clone --bare --shared $REPO_A/primary secondary.git 

Las personas que trabajan en el repositorio de Secundaria Ver las ramas que se originan del repositorio principal como de sólo lectura, pero basan su propia ramas de estas ramas.

Queremos sincronizar el repositorio secundario con el repositorio principal una vez al día.

I.e. queremos que las confirmaciones y las nuevas ramas que se enviaron a la primaria se vuelvan visibles para las personas que trabajan en el repositorio secundario (la próxima vez que hagan una extracción).

No queremos que esto sea simétrico, es decir, la actividad contra el repositorio secundario no será visible para aquellos que trabajan desde el repositorio principal.

Idealmente me gustaría ejecutar un trabajo cron que se ejecute en la máquina con el repositorio secundario desnudo que de alguna manera obtiene datos nuevos del primario y los incluye automáticamente en el secundario.

Esperaba que pudiera haber una manera simple de hacer esto (y espero que alguien aquí me diga que sí).

Si tuviera que escribir un script para hacerlo, lo haría:

  • crear un clon fresca de la secundaria.

    $ git clone $REPO_B/secondary 
    $ cd secondary 
    
  • Obtén todas las sucursales.

    $ git branch -r | sed 's?.*origin/??' 
    
  • Obtener todas las ramas en el repositorio primario.

    $ git ls-remote --heads $REPO_A/primary | sed 's?.*refs/heads/??' 
    
  • Para cada rama primaria para los que no tiene ya una rama secundaria correspondiente:

    $ git fetch $REPO_A/primary $BRANCHNAME:$BRANCHNAME 
    $ git push origin $BRANCHNAME:refs/heads/$BRANCHNAME 
    
  • Para cada rama primaria para la que ya tengo una rama secundaria correspondiente:

    $ git checkout -b $BRANCHNAME --track origin/$BRANCHNAME 
    $ git pull $REPO_A/primary $BRANCHNAME 
    $ git push 
    

Como soy nuevo en git no me sorprendería si no he podido o considerar ciertos problemas fundamentales?

Y como he dicho, espero que haya una forma más sencilla de hacerlo, es decir, alguien dice "oh, no hagas todo eso, solo hazlo ...".

Respuesta

25

Oh, no hacer todo lo que, simplemente:

git --bare fetch 

;)

(ver este old thread for instance)
Si ha agregado el relevant remote origins a tu repositorio desnudo, se puede recuperar a su vez, cada uno de esos orígenes.

+4

Esto parece lo que quiero. Gracias por los enlaces - de estos llegué a: ' $ cd secondary.git ; git --bare fetch origin '+ refs/heads/*: refs/heads/*' ' Como un hacker veterano de UNIX, siempre me gusta realmente entender en qué estoy. Sin embargo, la mayoría de la documentación de Git parece ser realmente se presentan simples casos de Alice y Bob, y cualquier cosa más compleja es el estilo del libro de cocina. ¿Puede recomendar un buen libro en profundidad o documentación web para Git? –

+4

@George: sí: http://www.newartisans.com/2008/04/ git-from-th e-bottom-up.html, aunque http://stackoverflow.com/questions/315911/git-for-beginners-the-definitive-practical-guide ofrece muchos otros enlaces interesantes. http://tom.preston-werner.com/2009/05/19/the-git-parable.html también es bueno. – VonC

+0

También tenga en cuenta que esas especificaciones de referencia están en su configuración de git, por lo que con 'fetch = + refs/*: refs/*', solo tiene que escribir 'git fetch' – Dustin

10

Puede hacer un git clone --bare --mirror y hacer un git fetch periódicamente para que esto suceda.

Lo hago realtimish usando una herramienta llamada gitmirror que escribí en el nodo.js que ejecuto en una máquina en casa para recibir webhooks de github, así como ganchos ad-hoc para sincronizar las confirmaciones.

Para un ejemplo que no es github, tengo un repositorio que se utiliza para una copia de seguridad de couchdb que tiene un compromiso de una vez por hora. El trabajo de cron básicamente se reduce a esto:

# do some backup stuff 
git commit -qam "Backup `date`" >> dump.log 2>&1 

A partir de ahí, tengo un post-commit hook (.git/hooks/post-commit) que tiene este aspecto:

#!/bin/sh 
curl -sS http://my.home.machine/gitmirror/bak/repo-name.git 

Usted puede lograr lo mismo empujando desde el lado receptor Esto tiene la ventaja de disparar y olvidar la carga útil en el caso normal.

+0

Editar: Se agregó '--bare' a la línea de clonación ya que VonC me lo recordó. Por lo general, lo hago y me doy cuenta de que no hice '--bare' y luego lo convertí manualmente o lo hice de nuevo. – Dustin

+0

Interesantes opciones de copia de seguridad (y una respuesta más detallada que la mía). +1 – VonC

+1

La sugerencia de VonC parece hacer lo que quiero. Sin embargo, me siento mal, ya que realmente no le he dado una oportunidad a Dustin sobre la base de que no puedo encontrar nada que explique la opción --mirror de manera significativa. P. ej. La página man de git-clone no dice más que "Configurar un espejo del repositorio remoto. Esto implica --bare". ¿Pero qué significa esto ciclo de vida sabio, etc.? ¿Cómo se clona un repositorio con --mirror diferente de uno que no es? Sorprendentemente, Google-ing no me iluminó :( –

Cuestiones relacionadas