svn - migrar - subgit
Usando git-svn(o similar)*solo*para ayudar con una combinaciĆ³n de svn? (3)
Acabo de resolver esto yo mismo. Un método más simple es pasar git merge
la opción --squash
, que realizará la fusión sin registrar un commit de fusión, manteniendo el historial lineal para no confundir git-svn.
Mi fusión también era muy grande, y tuve que configurar git config diff.renamelimit 0
para que git encontrara correctamente todos los cambios de nombre.
Algunas fusiones de subversión complejas están surgiendo en mi proyecto: grandes ramas que han estado separadas durante mucho tiempo. Svn da demasiados conflictos, y algunos de ellos parecen espurios.
Dado que git
es elogiado por una experiencia de combinación superiour, ¿sería bueno usar git-svn
solo para el beneficio de hacer que la fusión sea más manejable?
¿Puede recomendar otras alternativas (por ejemplo, svk
, hgsvn
) para disminuir el dolor de fusión?
Algunos conflictos son fáciles de resolver (por ejemplo, importaciones de Java, espacios en blanco), así que también me pregunto si hay alguna solución automatizada para ellos.
Un cambio completo a DVCS podría suceder en el futuro (a algunos nos encantaría), pero no ahora. (ACTUALIZACIÓN: esto ya no es cierto, el equipo cambió recientemente y está contento con él).
Gracias por adelantado.
PD: hay publicaciones que parecen estar relacionadas (por ejemplo, git-svn fusionar 2 ramas de svn ) pero no responden completamente a esta pregunta.
Actualización: vea mi respuesta -novice- después de bajar (y subir :) en este camino.
Estoy tratando de responder mi pregunta: el uso de git para las fusiones de svn parece prometedor.
Actualización: no es solo prometedor, es un gran éxito. En resumen, Linus tenía razón .
Acaba de completar una gran fusión de 2 ramas svn que han estado separadas durante 1,5 años; Se cambiaron 3k archivos, obtuve toneladas de conflictos en svn (~ 800 creo).
Encontré git & git-svn un salvavidas:
- resolución automática de conflictos: para empezar, dio muchos menos archivos en conflicto (~ la mitad, creo)
- rendimiento increíble
- excelente modelo de repo / bifurcación , flujos de trabajo flexibles: experimentación fácil con varios enfoques, como la fusión pedazo por pedazo (en el tiempo), siempre haciendo verificaciones de cordura (compilación, etc.); cada vez que se produce un problema: retrocede. Siempre puedes dar un paso atrás cuando sea necesario.
- usabilidad, excelentes herramientas:
-
git-log
(y las opciones subyacentes degit-rev-parse
), nada puede ser más poderoso que esto. También es útil:-p
te da diffs de una vez; en svn obtienes un log, luego encuentras el diff para esa "revisión-1: revisión", o usas UI torpes. Encontrar cuando se agregó / eliminó una cadena en el repositorio, buscar múltiples ramas simultáneamente -
gitk
: muy útil para visualizar historiales de sucursales, combinado con una gran capacidad de búsqueda. No he visto nada como esto en otras herramientas, especialmente no tan rápido como este. No importa, está en Tk, es simplemente genial -
git gui
: funciona bien, incluso si no es el más sexy, una gran ayuda para que el novato descubra cosas -
blame
: un milagro Sí, detecta de dónde viene el segmento original (copiar y pegar, etc.) -
mergetool
: experiencia mucho más placentera que iniciar la gransvn merge
que luego se detiene cada vez (es decir, cada 5 minutos) se ejecuta en un conflicto, presiona ''(p) ostpone'', que luego busca manualmente los archivos en conflicto. Prefiero un sabor de este integrado engit gui
(necesitaba un pequeño parche para eso). Se encontró que la integración de herramientas de diferencias externas es mejor configurable que ensvn
. - controladores de combinación conectables y control de granulación de ellos
-
rebase
permite filtrar las partes más desordenadas del historial de svn
-
- distribución: no es necesario ir a la oficina cuando se trabaja en esto, puede pausar y avanzar paso a paso en tren / avión, etc.
- un disco USB con Unison hizo que la sincronización <-> fuera un pedazo de pastel
- esto no hubiera sido posible sin la loca compresión de git (proyecto de 5 años con 26k commits, toneladas de ramas y archivos binarios, check de trunk svn: 1.9Gb => todos estos en el repositorio completo de git: 1.4Gb!)
Por lo tanto, esto realmente puede hacer la diferencia de una pesadilla a la alegría, especialmente si disfrutas aprendiendo (lo que requiere un poco de esfuerzo en este caso, supongo que aprender una moto después de una bicicleta).
Aunque no puedo obligar a todos en la empresa a cambiar de inmediato, realmente no tenía intención de hacerlo. Nuevamente, git-svn
nos salva con el enfoque de "sumergir el dedo del pie primero". Pero al ver las reacciones de los colegas, el cambio podría suceder mucho antes de que nadie lo espere :)
Yo diría que, incluso si nos olvidamos de las fusiones y confirmaciones, estas cosas ya son geniales como una interfaz de solo lectura para consultas, visualización, copias de seguridad, etc.
Advertencia:
"No confirme que Git merge se compromete con el repositorio de Subversion. Subversion no maneja las fusiones de la misma manera que Git, y esto causará problemas. Esto significa que debe mantener su historial de desarrollo de Git lineal (es decir, sin fusionarse desde otras ramas, simplemente rebase) ". (último párrafo de http://learn.github.com/p/git-svn.html )
Otra excelente fuente es el libro de Pro Git , la sección "Cambio de ramas activas" básicamente dice que la fusión funciona, pero dcommit
solo almacenará el contenido de la combinación, pero la historia se verá comprometida (lo que rompe las fusiones posteriores), por lo que debería soltar la rama de trabajo después de la fusión. De todos modos, tiene sentido después de todo, y en la práctica es fácil evitar las trampas aquí ... en svn, encontré que la gente no suele volver a fusionarse de todos modos, así que esto podría verse como un paso atrás si vienes del mundo git en el primer lugar.
De todos modos, el compromiso solo funcionó para mí. Lo hice en mi propia rama de trabajo de svn que guardaba solo para esto, así que evité cualquier conflicto extra esa vez. Sin embargo, decidí hacer la fusión final de esta rama de trabajo al tronco svn en svn (después de sincronizar todo en git); --ignore-ancestry
dio los mejores resultados allí.
Actualización: como descubrí más tarde, los últimos pasos anteriores (rama svn extra y fusión-ignorar-ascendencia) se evitan fácilmente manteniendo la rama de la que se trata lineal. Como Gabe dice a continuación, merge --squash
solo crea una simple y estúpida confirmación de svn. Justo cuando estaba listo con enormes fusiones en mi sucursal local (lo que podría tomar días / semanas), ahora simplemente:
git checkout -b dcommit_helper_for_svnbranch svnbranch
git merge --squash huge_merge_work_with_messy_nonlinear_history
git commit ''nice merge summary'' # single parent, straight from the fresh svnbranch
git dcommit
Sé que el seguimiento de fusión no funcionará bien desde el lado svn, hasta que cambiemos completamente. No puedo esperar por eso.
ACTUALIZACIÓN : @Kevin solicitó más detalles sobre todo el proceso de fusión de las ramas svn. Hay muchos artículos, publicaciones por ahí, pero como novato encontré algo confuso / engañoso / desactualizado. De todos modos, la forma en que hazlo en estos días (por supuesto, atorado con git-svn después de esa fusión, al igual que algunos colegas recién infectados) ...
git svn clone -s http://svn/path/to/just-above-trunk # the slowest part, but needed only once ever..you can every single branch from the svn repo since revision #1. 2)
git svn fetch # later, anytime: keep it up to date, talking to svn server to grab new revisions. Again: all branches - and yet it''s usually a faster for me than a simple ''svn up'' on the trunk:)
# Take a look, sniff around - some optional but handy commands:
git gui & # I usually keep this running, press F5 to refresh
gitk --all # graph showing all branches
gitk my-svn-target-branch svn-branch-to-merge # look at only the branches in question
git checkout -b my-merge-fun my-svn-target-branch # this creates a local branch based on the svn one and switches to it..before you notice :)
# Some handy config, giving more context for conflicts
git config merge.conflictstyle diff3
# The actual merge..
git merge svn-branch-to-merge # the normal case, with managable amount of conflicts
# For the monster merge, this was actually a loop for me: due to the sheer size, I split up the 2 year period into reasonable chunks, eg. ~1 months, tagged those versions ma1..ma25 and mb1..mb25 on each branch using gitk, and then repeated these for all of them
git merge ma1 # through ma25
git merge mb1 # through mb25
# When running into conflicts, just resolve them.. low tech way: keep the wanted parts, then "git add file" but you can
git mergetool # loops through each conflicted file, open your GUI mergetool of choice..when successful, add the file automatically.
git mergetool my-interesting-path # limit scope to that path
En realidad, preferí usar la integración integrada de mergetool de ''git gui'' (haga clic derecho en el archivo en conflicto). Sin embargo, eso es un poco limitado, así que mira mi pequeño parche arriba, que te permite agregar un guión de shell donde puedes invocar las herramientas de mezcla que prefieras (probé una variedad de ellas a veces en paralelo ya que causaban una cantidad sorprendente de pena ... pero normalmente Estoy atrapado con kdiff3 ..
Cuando un paso de fusión funciona bien (sin conflicto), una confirmación de fusión se realiza automáticamente; de lo contrario, resuelves conflictos entonces
git commit # am usually doing this in the git gui as well.. again, lightning fast.
La última fase. Tenga en cuenta que hasta ahora solo teníamos confirmaciones locales, sin hablar con el servidor svn todavía. A menos que hayas usado --squares u otros trucos, ahora terminas con un gráfico donde tu commit de fusión tiene 2 padres: las sugerencias de tus ramas svn-mirror. Ahora este es el resultado habitual: svn solo puede tomar la historia lineal ... por lo que ''git-svn'' lo simplifica simplemente descartando el segundo padre (svn-branch-to-merge en el caso anterior) ... por lo que el seguimiento de fusión real es ido en el lado svn ... pero de lo contrario está bien en este caso.
Si desea una forma más segura / limpia, aquí es donde entra mi fragmento anterior: simplemente realice la fusión final con --squash. Adaptado el anterior a este flujo:
git checkout -b dcommit_helper_for_svnbranch my-svn-target-branch # another local workbranch.. basically needed as svn branches (as any other remote branch) are read-only
git merge --squash my-merge-fun
git commit ''nice merge summary'' # single parent, straight from the fresh svn branch
git dcommit # this will result in a ''svn commit'' on the my-svn-target-branch
Uy, esto se está haciendo demasiado largo, deteniéndose antes de que sea demasiado tarde ... Buena suerte.
Hay nuevas herramientas disponibles que solucionan muchos problemas de git-svn y ofrecen una experiencia mucho mejor para usar Subversion y Git.
Entre otras cosas, estas herramientas solucionan algunos problemas de ramificación y fusión. Aquí hay una descripción general:
git-svn
De la documentación:
CAVEATS
...
No se recomienda ejecutar git merge o git pull en una sucursal de la que planea comprometerse. Subversion no representa fusiones de ninguna manera razonable o útil; para que los usuarios que usan Subversion no puedan ver las fusiones que hayas realizado. Además, si se fusiona o tira de una rama git que es un espejo de una rama SVN, dcommit puede comprometerse con la rama incorrecta.
Hay principalmente tres razones para no comprometer la fusión de fusión:
git-svn no envía automáticamente la propiedad svn: mergeinfo para las ramas fusionadas. Como resultado, Subversion no puede rastrear esas fusiones realizadas por git. Esto incluye fusiones normales de Git y selecciones de cereza.
como git-svn no convierte svn: ignore, svn: eol-style y otras propiedades de SVN automáticamente, la fusión de commit no tiene los metadatos correspondientes en Git. Como resultado, dcommit no envía estas propiedades al repositorio SVN, por lo que se pierden.
dCommit siempre envía cambios a la rama a la que hace referencia un primer padre de una confirmación de fusión. Algunas veces los cambios aparecen donde el usuario no los espera.
SubGit es un espejo bidireccional del lado del servidor Git-SVN.
Si uno tiene acceso local al repositorio de Subversion, uno puede instalar SubGit en él:
$ subgit configure $SVN_REPOS # Adjust $SVN_REPOS/conf/subgit.conf to specify your branches and tags # Adjust $SVN_REPOS/conf/authors.txt to specify git & svn authors mapping $ subgit install $SVN_REPOS ... $ INSTALLATION SUCCESSFUL
En este momento, SubGit convierte el repositorio de Subversion en Git (también funciona en direcciones opuestas) e instala los enlaces SVN y Git. Como resultado, los repositorios de Subversion y Git están sincronizados: cada confirmación y envío inicia ganchos que convierten las modificaciones entrantes de inmediato.
SubGit convierte svn: ignora las propiedades en archivos .gitignore, svn: eol-style y svn: propiedades de tipo mime en .gitattributes, por lo que las asignaciones de fusión en Git conservan estos metadatos.
Cuando uno presiona merge commit, SubGit convierte todos los commits nuevos en revisiones de Subversion. Hace honor a la propiedad svn: mergeinfo, por lo que la operación de fusión es seguida correctamente por SVN.
Incluso si el usuario empuja un historial de Git muy complejo, SubGit convierte todas las confirmaciones manteniendo válidos los datos de seguimiento de fusión. Una vez empujamos toda la historia del repositorio git.git de una vez y se convirtió correctamente en SVN.
SubGit es un producto comercial. Es gratis para proyectos de código abierto y académicos y también para proyectos con hasta 10 committers.
Para obtener más información, consulte la documentación de SubGit y la página de comparación de git-svn .
SmartGit es una alternativa del lado del cliente para git-svn.
SmartGit también es compatible con las conversiones de propiedades svn: ignorar, svn: eol-style y svn: mime-type. Y también establece la propiedad svn: mergeinfo para las asignaciones de fusión. Incluso actualiza los datos de seguimiento de fusión necesarios para las confirmaciones de recolección selectiva.
SmartGit es un cliente comercial de Git y Mercurial. Es gratis para uso no comercial.
Descripción completa: soy uno de los desarrolladores de SubGit.