2009-01-19 24 views
9

Aquí está mi problema:svn import retroactiva en git

  1. que utiliza Subversion desde hace algún tiempo, hasta que me pasa a Git. Un poco más de tiempo transcurrido.
  2. No hubo importación del historial de Subversion a Git. Era una comprobación estricta, eliminación de los directorios .svn, luego git init. No es un movimiento inteligente.
  3. Ahora, miles de commit de git más tarde, encuentro una copia de seguridad del repositorio de Subversion realizada en el momento en que se produjo la primera confirmación de git. Aha!

Me gustaría revertir el git repo al día 0, importar correctamente el svn repo, luego volver a aplicar todos los cambios de git, corrigiendo así lo que no se hizo la primera vez.

¿Alguien ha intentado esto? ¿Cómo voy a hacer esto? Suena como la madre de todas las rebases.

Respuesta

14

Suena como un trabajo para injertos git. La documentación para esto es un poco esquemática, pero básicamente lo que quiere hacer es esto:

  1. Obtenga una copia de git-svn del svn en su repositorio. La forma más fácil de hacer esto es git svn clon in, luego busque el clon svn en su repositorio existente
  2. Averigüe qué compromiso base debe seguir la confirmación svn. Entonces probablemente tengas una raíz de git en algún lado ("Última versión de SVN") que debería seguir a la última versión de SVN. Este es el encabezado del clon git-svn que acaba de obtener
  3. Crea un archivo .git/info/injertos y coloca los dos sha en una sola línea. El primero es el primer commit de git, luego un espacio, luego el último commit de svn. Esto le dice a git que el commit git no es parentless, pero de hecho tiene el último commit svn como parent.
  4. Ahora puede verificar con gitk/gitx/lo que sea que estén conectados los dos repositorios
  5. Para que el cambio sea permanente, ejecute git filter-branch. Probablemente quieras leer su página de manual primero.

También puede hacer el paso 3 para todas sus sucursales, por supuesto. El problema con el enfoque de jpalecek es que la rebase aplanará su historial, por lo que si tuviera alguna fusión, la rebase los perderá. El enfoque de rama de filtro mantiene su historial intacto.

+1

Esto es exactamente lo que hice para memcached: http://groups.google.com/group/memcached/browse_thread/thread/a7b153bc087244b1/4023dbe7168ea5fa – Dustin

+0

Bonito escrito, Pieter. Has hecho git injertos simples. +1 – Paul

+0

Gracias Pieter, +1 de mí. El mismo proceso con un par de imágenes también se puede encontrar en http://blog.experimentalworks.net/2009/07/git-voodoo/ –

1

Nunca he intentado lo que quiere, pero estoy haciendo algo similar con CVS.

Básicamente, me gustaría sugerir:

  1. Crear un nuevo repositorio git con la historia desde SVN
  2. En este nuevo repositorio, git fetch todo, desde el repositorio git (no habrá comete en común)
  3. Entonces, git branch remote/branch branch-last y git rebase --onto svn-last remote/branch-first branch-last, donde remote/branch-first es la primera cometió de su repositorio git importados, etc.

Si tienes más sucursales, las cosas son más complicadas. Creo que repetir el paso 3 podría servir, pero será mejor que te pruebes. Si tiene fusiones en su historial de git, puede necesitar git rebase -i -p .... Recuerde, la ventaja de git es que básicamente no puede arruinar nada (especialmente si está trabajando en un repositorio separado).