2011-05-12 23 views
6

Estoy usando git diariamente por un tiempo, y esta vez me he encontrado con un problema que podría describir de esta manera.Repositorio git "Capas"

Tengo un repositorio que contiene toda la estructura del sitio web, y la raíz web está en la raíz del repositorio. Todo estaba bien hasta que fue repositorio de un solo sitio. Sin embargo, ese mismo repositorio ahora se usa para varios sitios, básicamente el mismo sitio, en diferentes idiomas, pequeños retoques de plantillas, diferentes gráficos, etc. Esos elementos tienen una versión natural.

Hay una rama principal, que contiene el código fuente original del sitio, y me gustaría tener el maestro (o alguna otra rama) para contener el código que es universal en todos los sitios, ya que eventualmente habrá cambios que son demasiado específicos del sitio para incluirlos en la parte universal del repositorio.

A continuación, hay una rama para cada sitio que utiliza este código fuente. Todas esas ramas (por ejemplo, site1, site2 y Sitio3) se crean a partir rama principal, y cada sitio clones rama correcta.

Bueno, me pareció una buena idea, hasta que comencé a hacer cambios en todas partes.

Si realicé un cambio en la rama site1, y necesitaba copiar ese cambio en la rama site2, seleccionaría la confirmación de una rama a otra. La fusión es imposible, ya que hay otros cambios en la rama de sitio1 que no pertenecen a la rama de sitio2. ¿Hay alguna otra solución más elegante para este tipo de situación, o es que la recolección de cerezas es exactamente para este propósito?

Ahora, el verdadero "problema" para mí es cuando cambio de maestro, y luego quiero copiar todos esos cambios en todas las ramas. Naturalmente, considerando el hecho de que todas las ramas son descendientes de master, y que I do desea esos cambios en todas las ramas del sitio *, cambio a cada rama y maestro de fusión.

Esto crea una historia bastante desagradable para todas las ramas. Cada ronda de fusiones complica gráfico considerablemente, lo que me lleva a dos conclusiones:

  1. esta forma de capas ramas pueden trabajar, siempre y cuando veo a mi paso y no hacer nada estúpido, y no tratando de conseguir cualquier sentido fuera del gráfico de historial de todas las ramas. O ..
  2. tiene que haber alguna forma mejor y más adecuada de hacerlo.

Para ilustrar mi "problema", daré una imagen del gráfico que obtuve después de crear esas ramas, agregando algunas confirmaciones específicas de la rama, escogiendo algunas de ellas, agregando y fusionando una confirmación del maestro a todas las ramas, comprometer o dos a ramas específicas, y luego una fusión maestra a todos.

sort of not-so-simple history graph

No sé, me gusta la simplicidad, y tal vez yo no estoy acostumbrado a ver y difíciles de seguir gráficos como éste (que sólo crecerán en complejidad con cada fusión siguientes, yo 'tengo miedo).

Supongo que podría hacer todo el camino, y tener un buen historial de historia, pero eso tampoco suena bien, ya que podría hacer varios commits seguidos, y luego olvidar elegir uno de ellos para todas las otras ramas ...

Entonces ... ¿Alguna idea, experiencia o sugerencia que no le importaría compartir?

ACTUALIZACIÓN: Elijo una solución que se describe en mi comentario sobre la respuesta aceptada. ¡Gracias a todos los que contribuyeron!

ACTUALIZACIÓN 2: A pesar de que no está fuertemente relacionada con esta cuestión, recently I stumbled upon this model of branching que parece ser adecuado para casi cualquier ciclo de desarrollo organizado, con GIT como DVCS subyacentes. Es una muy buena lectura. Recomendado.

+1

Menos tiempo para una respuesta, pero eche un vistazo a 'rebase'. – KingCrunch

+2

La fusión puede no ser tan mala como crees. Fundamentalmente, una fusión significa "incorporar todo desde otra rama a esta", lo que parece que es lo que quieres hacer. Puede usar 'git merge --log' para incluir una lista de los temas de la confirmación fusionada en su mensaje de confirmación de fusión, y luego use' git log --first-parent' (o 'gitk --first-parent' ') para ver su historial en las ramas del sitioX. – Cascabel

Respuesta

4

respuesta alternativo:

Se podía mover la abstracción del nivel de las sucursales a nivel de repositorio. Cree un repositorio principal con una rama principal. Clona este repositorio para cada sitio. Cuando se realizan cambios en la rama principal, extraiga estos cambios en cada repositorio del sitio. De esta forma solo necesitarás una rama principal por repositorio.


Respuesta original:

Cuando la rama principal se ha cambiado usted podría rebasar las otras ramas en la rama principal actualizada. Vamos a suponer que usted ha basado pl_site en algunos cometen el maestro y ese maestro ha cambiado:

o---o---o---o---o master 
     \ 
      o---o---o---o---o pl_site 

Después de haber porcentualizada pl_site, que se verá así:

o---o---o---o---o master 
        \ 
        o'---o'---o'---o'---o' pl_site 

Tenga en cuenta que los compromete en la versión porcentualizada de pl_site son nuevos. pl_site ahora contiene los cambios que se hicieron en el maestro.

Comandos:

$ git checkout pl_site 
$ git rebase master 
+0

Esto solo lo lleva tan lejos. Dentro de un año, esa rebase podría no funcionar, y podrías terminar destruyendo la historia para lograrlo. (Es decir, el primer commit de 'pl_site' beyond' master' no siempre se aplicará a cualquier versión futura de 'master'.) – Cascabel

+0

Eso no resuelve el problema real,' rebase' simplemente destruye el historial de commits se ve bonito. –

+0

@Dietrich: Es la historia, que se ve fea, por lo que toleras, se destruye o la mantienes fea (o encuentras una herramienta que simplemente la imprime bonita: D) – KingCrunch

1

que no tienen una buena respuesta para usted, porque su problema es complicado y ha complicado soluciones.

Opción 1: Refactor

Usted ha dicho que los diferentes sitios son "básicamente el mismo sitio". Así que muévalos a diferentes proyectos y mantenga el main_site en un proyecto en sí mismo. Los otros sitios incluirán main_site como subproyecto.

Por lo tanto, para el banner ...

en_site/ 
en_site/images/banner.jpg 
en_site/master/ 
en_site/master/images/banner.jpg 

Su código del sitio web, script de configuración, script de implementación, o lo que se asegurará de que se elija images/banner.jpg sobre master/images/banner.jpg. Tal vez cuando implemente el sitio master/images se copie primero y luego se copie el images, tal vez haga algo más sofisticado.

Esto podría ser mucho trabajo.Sin embargo, cuando nos fijamos en la historia, obtendrá algo como esto:

en_site: A -> B -> C -> D 
de_site: E -> F -> G -> H -> I 
main_site: J -> K -> L -> M -> N -> O 

Opción 2: Uso Darcs

En Darcs, puede mover los parches de rama en rama. Algunos VCS comerciales probablemente también puedan hacer esto. Por lo que sus ramas se vería así:

master: patch1 patch2 patch3 patch4 
en_site: patch1 patch2 patch3 patch4 en1 en2 en3 
de_site: patch1 patch2 patch3 patch4 de1 de2 de3 

Supongamos que desea parche puerto en2 al sitio alemán.

de_site: patch1 patch2 patch3 patch4 de1 de2 de3 en2 

Voila. Sin embargo, esto no es tan limpio como parece. Los aficionados de Darcs señalarán que este modelo de parche coincide con nuestro modelo conceptual de "mover un parche a otra rama", sin embargo, esto pasa por alto el hecho de que todavía tendrá que probar para asegurarse de que el parche en2 no lo rompe todo cuando lo pones en de_site.

Por ejemplo, ¿qué ocurre si en2 hace un cambio en la misma parte del código que de1? ¿Entonces que? Debe fusionarse manualmente, sin importar qué VCS esté usando. Para cada caso obvio como este, hay otro caso que el VCS no detectará y tendrá que verificarlo usted mismo.

Mi experiencia

Cuando empecé a usar git, parecía que era git merge magia. Sin embargo, ninguna cantidad de trucos de VCS ocultará el hecho de que su sitio tiene interdependencias muy complicadas. Puede refactorizar su sitio para eliminar las interdependencias, o esperar que su historial de VCS no se vuelva tan complicado que ya no pueda entenderlo.

La compensación entre nuevas sucursales, nuevos proyectos y la refactoración de las cosas en las bibliotecas es una transacción delicada. Mantener una gran colección de parches es mucho más trabajo que mantener una gran colección de proyectos que usan una biblioteca común, la cantidad de trabajo (grande) necesaria para refactorizar puede pagar rápidamente. O puede que no.

+0

Estoy en la encrucijada con respecto a exactamente lo que describió ... Así que o bien voy a refactorizar e implementar esos detalles específicos por sitio de alguna manera sensata para que puedan se anulan mutuamente, o voy a elegir una solución basada en VCS que no sea tan simple pero que se pueda mantener, mientras mantengo el código intacto. Gracias por las ideas –