2010-05-31 10 views
26

Algunas subversiones complejas de subversión 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.Usando git-svn (o similar) * solo * para ayudar con una combinación de svn?


Dado que git es alabado por una experiencia de fusión superiour, habría de ser bueno para su uso git-svn sólo para el beneficio de hacer la combinación más manejable?


Me puede recomendar otras alternativas (por ejemplo. svk, hgsvn) para disminuir el dolor de combinació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 puede 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 de antemano.

PD: hay publicaciones que parecen estar relacionadas (por ejemplo, git-svn merge 2 svn branches) pero no responden completamente esta pregunta.

Actualización: ver mi -nodo- respuesta después de bajar (y subir :) esta carretera.

+0

¿Por qué no * solo * usando git-svn para todo? –

+0

@ Vi.esto suena como una pregunta separada de alto nivel, puede agregarla como tal: -/La mía era, aproximadamente: "¿presentarías git-svn en un equipo basado en SVN, solo para ayudar con un gran fusión? " – inger

+1

Después de * solo * fusionarse, pueden pensar en comenzar * solo * usándolo ... –

Respuesta

33

Intentando responder a 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 was right.

Acabo 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).

me encontré con git & git-svn un protector de la vida:

  • resolución automática de conflictos: para empezar, le dio una gran cantidad de archivos de menos conflictivos (~ medio creo)
  • rendimiento increíble
  • excelente repo/branching model, flujos de trabajo flexibles: experimentación fácil con diversos enfoques, como la fusión de fragmentos por uno (en tiempo), siempre haciendo comprobaciones de cordura (compilación, etc.); cada vez que se produce un problema: retrocede. Siempre puedes dar un paso atrás cuando sea necesario.
  • facilidad de uso, gran utillaje:
    • git-log (y las opciones subyacentes git-rev-parse), nada puede ser más poderoso que esto. También es útil: -p le ofrece diffs de una sola vez; en svn obtienes un log, luego encuentras el diff para esa "revisión-1: revisión", o usas UI torpes. Buscar 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 excelentes capacidades de búsqueda. No he visto nada como esto en otras herramientas, especialmente no tan rápido como este.No importa que se encuentra en Tk, es simplemente brillante
    • git gui: funciona bien incluso si no la más sexy - gran ayuda para los novatos para descubrir cosas
    • blame: un milagro. Sí, detecta que el segmento original proviene de (copia & pasta, etc)
    • mergetool: mucha experiencia más agradable que dando inicio a la gran svn merge que luego se detiene cada vez que (. Es decir, cada 5 minutos) que se ejecuta en un conflicto, pulse ' (p) ostpone ', que busca manualmente los archivos en conflicto más adelante. Prefirió un sabor de esto integrado en git gui (se necesitaba tiny patch para eso). Se encontraron herramientas integradas de diferenciación externas mejor configurables que en svn.
    • enchufable se fusionan los conductores y control de grano fino de ellos
    • rebase permitido para filtrar las partes más sucios de la historia SVN
  • distribución: no hay necesidad de ir a la oficina cuando se trabaja en esto, podría hacer una pausa & progreso paso a paso en el tren/avión, etc ..
    • una unidad USB con Unison realizado la sincronización de trabajo < -> casa un pedazo de la torta
    • esto no haría h ave sido posible sin compresión loca del GIT (antiguo proyecto de 5 años con las confirmaciones, 26k toneladas de ramas y archivos binarios, el tronco svn checkout: 1.9GB => todos ellos en el repositorio git completa: 1,4 GB)

Por lo tanto, esto realmente puede marcar la diferencia de una pesadilla a la alegría, especialmente si le gusta aprender (lo que requiere un poco de esfuerzo en este caso, supongo que aprender una motocicleta después de una bicicleta).

Aunque no puedo obligar a todos en la empresa a cambiar de inmediato, realmente no tenía la intención de hacerlo. Una vez más, nos salva por git-svn 'mojar el dedo del pie ante todo' .. Pero al ver las reacciones de sus colegas el interruptor podría ocurrir mucho antes de que nadie espera :)

Me decir- incluso si nos olvidamos de fusiones & confirmaciones, estas cosas ya es grande como una interfaz de sólo lectura para las consultas, visualización, copias de seguridad, etc ..

Advertencia:

"no dcommit fusión Git se compromete a el repositorio Subversion Subversion no maneja. se fusiona de la misma manera que como Git, y esto causará problemas. Esto significa que debe mantener su Git desarrollo lineal de la historia (es decir, sin la fusión de otras ramas, simplemente cambio de base)." (último párrafo del http://learn.github.com/p/git-svn.html)

Otra excelente fuente es la sección Pro Git book ' Cambiar las ramas activas básicamente dice que la fusión funciona, pero dcommit solo almacenará el contenido de la fusión, pero el historial se verá comprometido (lo que rompe las fusiones posteriores), por lo que debe soltar la rama de trabajo después de la fusión. sentido después de todo, y en la práctica es fácil evitar las trampas aquí ..en svn, encontré que las personas generalmente no vuelven a fusionarse de todas formas, por lo que esto solo podría ser visto como un paso atrás si vienes del mundo de git en 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 me enteré más tarde, los últimos pasos anteriores (rama svn adicional y fusión - ignorar ancestros) se evitan fácilmente manteniendo la rama de la que se trata lineal. Como dice Gabe a continuación, merge --squash solo crea una simple y estúpida confirmación de svn. Sólo cuando esté listo con gran fusión (s) en la rama de mi local (que podría tomar días/semana), yo ahora sólo:

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 la fusión no será un gran trabajo desde el lado del SVN hasta que cambiemos completamente No puedo esperar por eso.


ACTUALIZACIÓN: @ Kevin pidió algunos detalles más en todo el proceso de fusión de las ramas SVN .. Hay un montón de artículos, mensajes por ahí, pero como novato he encontrado algunas de las confuso/engañosa de entrada/salida de fecha .. de todos modos, la forma en que lo hago en estos días (por supuesto, pegado con git-svn después de ese asunto de combinación; al igual que algunos colegas recién infectadas) ..

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 

realidad preferido para usar Git' Integración integrada de mergetool de 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 atascado con kdiff3 ..

Cuando un paso de mezcla va bien (sin conflicto), una combinación de confirmación se realiza automáticamente, de lo contrario, a resolver conflictos a continuación

git commit # am usually doing this in the git gui as well.. again, lightning fast. 

la última fase .. Tenga en cuenta que hasta el momento solo teníamos confirmaciones locales, sin hablar con el servidor svn. A menos que hayas utilizado --squares u otros trucos, ahora terminas con un gráfico en el que tu commit de fusión tiene 2 padres: las sugerencias de tu sv n-espejo ramas. 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 quiere una forma más segura/limpia, aquí es donde entra mi fragmento anterior: simplemente haga 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 

Vaya, esto se está poniendo demasiado tiempo, parando antes demasiado tarde .. Buena suerte.

+2

+1 para su revisión completa y auto-respuesta –

+0

gracias. Espero que ayude a otros también. – inger

+0

Hola Inger, ¡genial que pudieras hacer que esto funcione! Soy un git novato y estoy evaluando git precisamente para este caso de uso: fusionar dos ramas que tienen muchos archivos y muchos conflictos de SVN falsos. ¿Puedes armar una breve lista de códigos sobre cómo configurar tu repositorio y realizar el trabajo? P.ej. git svn clone myrep; git checkout -b branchA; git checkout -b branchB; git merge branchA branchB; git commit, git svn dcommit, etc.? Quiero asegurarme de que entiendo completamente tu enfoque antes de comenzarlo porque git svn clone toma días :-(Gracias de antemano –

3

Acabo de resolver esto yo mismo. A simpler method es pasar git merge la opción --squash, que realizará la fusión sin registrar una fusión de compromiso, manteniendo el historial lineal para no confundir git-svn.

Mi fusión también fue muy grande, y tuve que configurar git config diff.renamelimit 0 para que git encontrara correctamente todos los cambios de nombre.

+1

Saludos por eso. Sí, he estado usando --squash merge a veces también. También es útil cuando quieres un único compromiso combinado en lugar de muchos pequeños (como alternativa a 'rebase -i'). – inger

+0

La opción de fusión '--no-ff' parece haber sido hecha para esto:' git merge --no-ff mybranch' –

3

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 bifurcación y fusión. He aquí un resumen:

  1. git-svn

    De la documentación:

    SALVEDADES

    ...

    Correr git merge o git pull no se recomienda en una rama 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.

    Existen principalmente tres razones para no dcommit fusión se compromete:

    • git-svn no envía automáticamente SVN: mergeinfo de 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 bifurcación 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.

  2. SubGit

    SubGit es un bi-direccional espejo del lado del servidor Git-SVN.

    Si uno tiene acceso local a depósito de la subversión, se 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 depósito de la subversión en Git (funciona en la dirección opuesta también) y ensambla las SVN y Git manos. 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 tipo mime para .gitattributes, por lo que las asignaciones de fusión en Git conservan estos metadatos.

    Cuando se 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 el historial de Git muy complejo, SubGit convierte todas las confirmaciones manteniendo los datos de seguimiento de fusión válidos. Una vez empujamos toda la historia de git.repositorio git a la 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 SubGit documentation y página de comparación.

  3. SmartGit

    SmartGit es una alternativa del lado del cliente para git-svn.

    SmartGit también admite svn: ignorar, svn: eol-style y svn: tipo de mime conversión de propiedades. 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.

+0

Gracias, escuché sobre SubGit antes. Parece un enfoque poderoso, sin embargo, parece más dirigido a una conversión completa. La pregunta anterior era más un experimento de inmersión, haciendo una única combinación de svn sin acceso al servidor y sin que nadie en la empresa lo notara ... De todos modos, mientras tanto logré que el equipo se volviera completo, y algunas otras personas también, y los chicos de TI están planeando una migración completa para la cual el modo dual podría ser útil. Entonces, gracias por la sugerencia. ¿Qué es mergeinfo confiable con todas las versiones de Svn? – inger

+0

Ahora estamos trabajando en SubGit 2.0 que admite sincronización bidireccional de repositorios Git y SVN ubicados en diferentes hosts. Básicamente, uno puede crear el repositorio Git en cualquier lugar, especificar el URL del repositorio SVN y habilitar la sincronización SubGit para estos repositorios. La sobrecarga es un poco más de retraso en el lado de Git sin demora alguna en el lado SVN. – vadishev

+0

En cuanto a svn: mergeinfo, SVN admite esta propiedad desde la versión 1.5, es decir, hace más de 4 años. Antes de eso, SVN no rastreaba el historial de fusión en absoluto. Para SVN 1.8, planean introducir una función de fusión "simétrica" ​​que debería mejorar el seguimiento de fusión. Con suerte, eso pone a SVN a la par con Git/Hg/etc en este sentido. – vadishev

Cuestiones relacionadas