2011-01-15 9 views
8

Estoy tratando de mantener una copia vacía de un repositorio de Git y tener algunos problemas para mantener las ramas de seguimiento remoto actualizadas. Creo las ramas de seguimiento remoto de esta manera:¿Cómo obtengo una rama de seguimiento remoto para estar al día con el origen remoto en un repositorio de Git desnudo?

git branch -t 0.1 origin/0.1 

Esto parece hacer lo que tengo que hacer en ese momento. Sin embargo, si realizo cambios en origin y luego llevo con el repositorio desnudo, las cosas comienzan a desmoronarse. Mi flujo de trabajo es el siguiente:

git fetch origin 

Parece que todas las confirmaciones vienen en ese punto, pero no se actualiza mi copia local de 0,1. Puedo ver que los cambios han sido introducidos en el repositorio haciendo lo siguiente:

git diff 0.1 refs/remotes/origin/0.1 

¿Qué tengo que hacer para conseguir mi sucursal de seguimiento actualizado con las actualizaciones del mando a distancia? Siento que me falta un paso o una bandera en algún lado.

Actualizado: Aclaración adicional

Normalmente uno empujar en un repositorio desnudo, en lugar de ejecutar git fetch desde el interior de la misma. Si puede hacer eso, la vida será mucho más fácil.

Aquí hay un poco de aclaración sobre el flujo de trabajo.

El repositorio de git público del proyecto está alojado en GitHub. Estoy administrando el proyecto (wiki, issues, forums) usando Redmine. Redmine requiere un repositorio local para operar. Cuando GitHub recibe cambios, hace ping a Redmine. Redmine luego intenta obtener cambios de su origen (GitHub).

Esto funciona muy bien si solo estoy trabajando con el maestro, pero no funcionaba con mis ramas de seguimiento. Los cambios se estaban importando pero no se estaban enumerando en la sucursal del navegador de repositorios de Redmine porque las sucursales locales no se estaban actualizando.

Estoy seguro de que podría haberlo solucionado de otra manera, pero encontrar una solución (genérica) para poner en marcha las ramas de seguimiento definitivamente fue mi preferencia ya que la mayoría de los complementos relacionados con git para Redmine suponen cosas como "git fetch" origen "es todo lo que se necesita hacer.

Ver respuesta aceptada para la solución completa. La solución --mirror parece ser exactamente lo que se necesita en este caso.

Respuesta

17

Normalmente, uno accederá a un repositorio vacío, en lugar de ejecutar git fetch desde allí. Si puede hacer eso, la vida será mucho más fácil.

Si tiene para obtener en lugar de presionar y solo desea crear un reflejo de origen en su repositorio simple, podría evitar tener ramas de seguimiento remoto por completo. Si está comenzando este mirror desde cero, Charles Bailey señala que git hará toda esta configuración por usted si inicialmente clona el repositorio con git clone --mirror.

De lo contrario, se puede obtener un efecto similar con:

git fetch origin +refs/heads/*:refs/heads/* 

El + significa que esto va a sobrescribir el estado de sus ramas locales con los del mando a distancia. Sin el +, se rechazarán las actualizaciones que no sean fusiones de avance rápido. Sin embargo, si esto es solo un espejo, eso no debería importar. (Se puede configurar que se trata de la acción predeterminada en git fetch origin estableciendo la variable de configuración remote.origin.fetch a +refs/heads/*:refs/heads/*. Si se quiere duplicar las etiquetas y ramas de seguimiento remoto de origen, así, se puede usar +refs/*:refs/* en su lugar.)

Sin embargo, si, como originalmente lo solicitó, desea mantener sucursales de rastreo remoto y combinarlas selectivamente en sucursales locales, puede seguir los siguientes pasos, pero no necesariamente las recomiendo a menos que sea la única persona que use este repositorio simple. (Nota: originalmente aquí sugerí usar "git symbolic-ref HEAD refs/heads/whatever" para cambiar la rama y "git reset --soft" para cambiar la referencia de la rama - sin embargo, Charles Bailey señaló en los comentarios que uno puede utilice "git update-ref refs/heads/whatever refs/remotes/origin/whatever", que no requiere uno para cambiar de rama primero.)

En primer lugar, es posible que desee comprobar que la actualización de la rama tendría ha sido una fusión rápida, y después de eso actualizar la rama. Tenga en cuenta que aquí hay una condición de carrera, por lo que le digo que solo debe hacer esto si es la única persona que usa su repositorio local: el cheque sería inútil si alguien más se mueve en la rama entre esos pasos.

  1. Se puede comprobar que una combinación equivalente sería un avance rápido (es decir, que la historia de origin/master incluye master) mediante la comparación con git merge-base master origin/mastergit show-ref master - deben ser la misma. O puede utilizar la secuencia de comandos is-ancestor en this question, lo que hace esos comandos con algunas comprobaciones adicionales.)
  2. Por último, usted puede actualizar su rama actual (master en este caso) para que apunte a origin/master con git update-ref refs/heads/master refs/remotes/origin/master

Sin embargo , como dije al principio, supongo que la verdadera solución que desea es o bien:

  • Empujar en su repositorio desnudo o en lugar
  • Reflejando la Reposi desnuda remoto tory exactamente, como he descrito anteriormente

Espero que sea de alguna utilidad.

+1

'git merge' siempre requiere un árbol de trabajo, en su lugar debe usar' git update-ref' en un repositorio simple.Creo que tienes razón en que un espejo parece una mejor solución. Puede valer la pena agregar un no sobre 'git clone --mirror'. –

+0

@Charles Bailey: la razón por la que pensé que podría ser un error es que en el origen de builtin-merge.c hay un comentario que comienza "En este punto, necesitamos una combinación real ..." después del punto donde un rápido hacia adelante se habría hecho - No creo que el índice o el árbol de trabajo se necesite hasta ese momento. Eliminaré esa observación, de todos modos. –

+0

Puedes preguntar en la lista de correo de git, pero no estoy seguro de que se considere un error. Creo que, en general, es más consistente tener una distinción clara entre los comandos que no requieren un árbol de trabajo y los que sí lo hacen. Tener un comando que _might_ necesita un árbol de trabajo es una interfaz más compleja que podría causar algunos malentendidos. –

1

Cuando fetch, los cambios remotos actualizan su propia referencia local para el control remoto, origin/0.1 (esto nunca causa ningún conflicto, ya que origin/0.1 nunca aloja ningún cambio local). Para importar esos cambios, puede git reset refs/remotes/origin/0.1 desde 0.1, lo que hará que la rama HEAD (0.1) apunte a la misma confirmación que la rama remota.

Tenga en cuenta que al hacerlo perderá cualquier cambio a 0.1 que no provenga del control remoto.

+1

Si entiendo correctamente la pregunta, eso no funcionará, ya que la pregunta se refiere a un repositorio vacío y 'git merge' y' git pull' requieren un árbol de trabajo. –

+0

¡Oh, tienes razón! Modifiqué mi respuesta en consecuencia. – huitseeker

Cuestiones relacionadas