2012-07-02 19 views
5

Tengo dos repositorios:Combinar dos repositorios (proyecto original y cambiada proyecto sin historia)

  • Gephi (gran proyecto de código abierto) alojado en GitHub
  • Proyecto de mi empresa basada en Gephi

Hace 7 meses, cuando nuestro proyecto comenzó, alguien tomó una instantánea del proyecto gephi en github y la guardó en la empresa svn => cambiar la pérdida de la historia

ahora decidí mover nuestro proyecto al repositorio Git y fusionar los cambios con el proyecto original

he repositorio ahora git emigrado de SVN con git-svn

mis archivos no tiene historial de cambios más allá del momento en que nuestro proyecto se inició

¿Puedo asignar el estado inicial de nuestro repositorio al estado del repositorio original? En otras palabras, me gustaría comenzar a aplicar nuestros cambios al repositorio original de una revisión específica.

Actualización:

Hoy me encontré con otro obstáculo. Esquema primera:

enter image description here

  • rama roja es el proyecto original

  • <alpha1> y <alpha2> son confirmaciones de plugins para el proyecto principal (no relacionada con el Código comprometido en <E' E'' E'''>)

  • en <E'> <E''> <E'''> se agregó el código del repositorio principal del proyecto (rojo) <E> (en cada confirmación c ca un tercio del proyecto de <E>)

He rebuscado repositorios rojas y azules en una sola. En el segundo esquema tengo el estado deseado. ¿Es posible hacer esto? (Por ejemplo, hacer de <E' E'' E''> sólo una confirmación (<E'>) y luego marca que cometió como un combinado de las ramas <ABCD> y <alpha1 alpha2>)

Gracias Julien por su respuesta. Parece muy útil.

Respuesta

5

Descargo de responsabilidad: He probado esto, y parece que funciona como se esperaba (asumiendo que te entendí correctamente, por supuesto). Sin embargo, todavía hay muchas cosas que pueden salir mal. Absolutamente solo pruebe esto en una copia de trabajo separada del repositorio de su proyecto, y asegúrese de examinar todo antes de empujarlo a cualquier lugar. Mantenga copias de seguridad completas del directorio del estado antes de hacerlo.

Así que supongo que tiene dos repositorios independientes.El proyecto original (Gephi):

A---B---C---D---E 
       ^HEAD of Gephi 

Y su proyecto, cuya primera revisión se ve idéntica a la última revisión del proyecto original:

E'---V---W---Y---...---Z 
        ^HEAD of your project 

(posiblemente con algunas ramas, pero que en realidad no importa . aquí)

lo que le gustaría tener (si he entendido correctamente) es:

A---B---C---D---E---V---W---Y---...---Z 

Puede intentar lo siguiente. Una vez más, ¡haz esto por tu cuenta, separa el árbol de trabajo, y asegúrate de que todo esté en orden antes de enviar esto a cualquier repositorio central!

Mientras que en el directorio de su propio árbol de trabajo, ir a buscar las cabezas y los objetos del original repositorio Gephi:

git fetch /path/to/original/gephi 

Si no ha clonado el repositorio Gephi, que también podría especificar el github URL en lugar de una ruta del sistema de archivos local.

Esto dará lugar a la siguiente situación en su árbol de trabajo actual:

A---B---C---D---E 
       ^FETCH_HEAD 

E'---V---W---Y---...---Z 
        ^HEAD 

no hemos cambiado mucho. Actualmente, las dos cabezas coexisten pacíficamente y de forma completamente independiente entre sí, pero ahora tiene acceso a los objetos de ambos repositorios y puede intentar combinarlos.

Ahora queremos descartar E'(debe ser idéntica a E), y en lugar de hacer E el padre de su proyecto de primera cometer, que es V. Para ello, puede utilizar git filter-branch:

git filter-branch -f --parent-filter 'test $GIT_COMMIT = <V> && echo "-p <E>" || cat' 

Reemplace <V> y <E> por los valores hash de confirmación de V y E, respectivamente. Para encontrarlos, puede hacer git log para examinar las confirmaciones de su proyecto y, dado que las hemos obtenido, git log FETCH_HEAD para examinar las confirmaciones de Gephi.

Esto conectará efectivamente V directamente a E.

Esto debería funcionar incluso si resulta que la cabeza (es decir, el último commit) del repositorio original, Gephi no es lo que usted, basado en su proyecto, significado que ha habido nuevos compromisos en Gephi que no has tenido (¿todavía?) atendidos. Solo asegúrese de volver a sustituir <E> con el hash de la confirmación en la que ha basado sus cambios, y no con el encabezado.

Por el contrario, asegúrese de sustituir <V> con el hash del primer cambio que hizo. Tal vez su repositorio no contenga una E 'idéntica a E, pero la primera confirmación ya contiene cambios hacia la original. Entonces este primer hash commit será tu <V>, en lugar del que está después.

Para resumir los dos últimos párrafos: el comando anterior también debería funcionar si su situación se parece, por ejemplo, esto:

A---B---C---D---E---F---G---H---I 
       ^   ^FETCH_HEAD 
       point where your project branched off 

V---W---Y---...---Z 
^    ^HEAD 
first change based on E 

Sólo asegúrese de usar el hash que tienen sentido en este contexto se comprometen.

+0

Acabo de probar esto, y parece funcionar (así que actualicé mi advertencia en la parte superior). Todavía te aconsejo absolutamente que pruebes esto en un árbol de trabajo desechable y que hagas copias de seguridad completas. ¡Es fácil obtener la declaración 'filter-branch' incorrecta, o mezclar los hashes! –

+0

Si el proyecto local tiene varias ramas, o si hay fusiones en el historial, 'git rebase' no es la herramienta correcta porque linealizará el historial. Use 'filter-branch' en su lugar. –

+0

Gracias. Eso era lo que tenía originalmente, pero pensé que rebase tenía la sintaxis más fácil. Revertí mis cambios y ahora solo menciona filter-branch nuevamente. –

1

Suena como es posible que desee investigar grafts (o posiblemente replacements) - estos métodos difieren de filter-branch y rebase en que añaden los meta-datos para cambiar el estado de visibilidad del repositorio, en lugar de volver a escribir la historia a efecto en realidad el cambio. Esto es útil cuando hay personas que usan las ramas existentes, ya que evita cambiar el historial debajo de ellas.

En su caso, querría agregar un injerto para E', dando E como padre adicional.

+0

Recomiendo 'git replace' sobre injertos: los reemplazos son referencias, por lo que se pueden sincronizar entre repositorios (con un refspec apropiado). –

+0

Sí, eso es cierto en muchos casos. Sin embargo, la descripción del problema parece que el repositorio de git acaba de comenzar ("ahora decidí mover nuestro proyecto [...]/tengo ahora el repositorio de git"), y con un nuevo repositorio, prefiero las reescrituras reales en lugar de metadatos adicionales eso se demoraría hasta el final de los tiempos. –

Cuestiones relacionadas