2010-07-29 4 views
11

Estoy trabajando en un repositorio Git que se ha extraído de un repositorio SVN usando git svn. Hace muchas lunas, el repositorio SVN se creó a partir de un tarball fuente del proyecto original (upstream). El proyecto original tenía una estructura de archivos como la siguiente:¿Cómo puedo modificar la ruta del archivo en un conjunto de parches de Git?

/ 
    COPYING 
    README 
    src/ 
     ...many source files... 

Sin embargo, cuando se creó el repositorio SVN, los archivos README, etc., fueron despojados a cabo, y la aplicación se creó con src/ como la raíz, por lo el repositorio ahora se ve así:

/ 
    ...many source files 

Recientemente convertí este repositorio SVN en un repositorio Git. El proyecto original también está en un repositorio de Git, y me gustaría comenzar a rastrear los cambios preliminares para poder ver fácilmente qué cambios personalizados se han realizado (y enviar revisiones al proyecto original, si corresponde). Encontré la confirmación en el repositorio ascendente del que se creó nuestro repositorio SVN, así que ahora me gustaría aplicar nuestros cambios a esa confirmación (en una sucursal). Puedo crear fácilmente un conjunto de parches usando git format-patch y aplicarlos al repositorio reescrito clonado ... excepto que las estructuras de archivos son diferentes, por lo que los parches ya no apuntan a los archivos correctos. ¿Hay alguna manera de aplicar los parches desde git format-patch al directorio src/ en el repositorio clonado? (Tenga en cuenta que los parches de Git también tienen la información necesaria, como el nombre del autor original, el correo electrónico y la fecha, que también me gustaría aplicar y no tener que hacer a mano, por ejemplo, al meterme con GIT_AUTHOR_EMAIL, etc.)

+2

Pregunta similar: http://stackoverflow.com/questions/931882/how-to-apply-a-git-patch-from-one-repository-to-another – koppor

Respuesta

5

Me parece que usted debe poder usar git filter-branch para cambiar las rutas en el repositorio de SVN clonado previamente. Luego, después de que se hayan actualizado todas las rutas de archivos, ahora puede usar git format-patch para crear parches que aplicarán al repositorio recien clonado desde la parte superior.

Probar:

git filter-branch --tree-filter 'mkdir src; git ls-tree --name-only $GIT_COMMIT | xargs -I files mv files src'

+0

Casi funciona, pero los archivos en 'src/'están organizados en subdirectorios; esta solución los mueve todos directamente bajo' src/'. ¿Hay alguna manera de mover todo el árbol subdirectorio? – mipadi

+0

@mipadi: lo tienes claro. Mi error por no * probar * lo que escribo: O. Corregí ese error en mi respuesta. Gracias por señalar el problema :) –

+0

No hay problema - tu respuesta original funciona bien si 'src /' no contiene ningún subdirectorio (y olvidé mencionar eso en mi pregunta). – mipadi

2

Tuve que hacer algo muy similar una vez, no era bonita, pero era manejable. Lo que terminé haciendo fue:

git format-patch <commitish> --stdout > patches-for-upstream.mbox 
$EDITOR patches-for-upstream.mbox 

dentro del editor, miré a la que los bits eran comunes y necesitaba cambiar para hacer "git am" hacer lo que quería. Que resultaron ser tres líneas, por archivo cometido en cada confirmación:

  • la línea que comienza con diff --git a/path/to/file b/path/to/file
  • la línea que comienza con --- a/path/to/file
  • la línea que comienza con +++ b/path/to/file

Lo que el El editor debe hacer en este punto es pasar por este tipo de líneas y realizar los cambios que usted sabe que son necesarios para que todos los parches se apliquen al otro repositorio de Git.

Lo hice en Vim, usando tres macro de escritura rápida, YMMV.Algo a lo largo de las líneas de:

  • pase a la siguiente línea que comienza con diff --git a/
  • ir hacia adelante a la barra después del cambio a
  • el camino a medida que lo necesita ser
  • ir hacia adelante a la barra después de la b/ (avanzar al siguiente espacio desde el archivo a, entonces /)
  • cambio de la trayectoria de la misma manera como nex
  • t línea (el ---)
  • avanzar a a/
  • cambio de la trayectoria
  • siguiente línea (la +++)
  • Avanzar hacia b/
  • cambio de la trayectoria

Repita hasta que el archivo hecho En Vim, era cuestión de obtenerlo en macro una vez (qq<long string of commands>q), probarlo una vez (@q) y luego hacerlo para todo el archivo ([email protected]).

Guarde el archivo, entre en el otro repositorio Git e intente git am.

3

Recientemente tuve un problema similar. Mi solución fue crear un nuevo repositorio de destino con un subdirectorio src, a continuación, he creado un conjunto de parches en el repositorio de código fuente:

/data/source-repository$ git format-patch -k --root 

entonces esos parches se aplicaron al directorio src en el repositorio de destino:

/data/target-repository$ git am -k --committer-date-is-author-date --directory src ../source-repository/*.patch 

Todos los parches del depósito de origen finalizaban en src en el repositorio de destino, es decir, todas las rutas se ajustaban en consecuencia.

A partir de ahí, podría volver a crear parches e importarlos en el depósito de aguas arriba dentro de una sucursal.

+1

Esto combinado con 'git filter-branch --subdirectory-filter ' me permitió mover mis commits a un directorio diferente por completo. –

Cuestiones relacionadas