¿Qué hacer con la gran historia de svn al pasar a git?

23

Editar: a diferencia de algunas preguntas similares, como Mover un repositorio SVN de varios GB a Git o /programming/540535/managing-large-binary-files-with-git Mi escenario no involucra varios subproyectos que se puede convertir fácilmente en submuelles de git, ni en algunos archivos binarios muy grandes que sean adecuados para git-annex. Es un repositorio único donde los archivos binarios son el conjunto de pruebas que se acoplan estrechamente al código fuente principal de la misma revisión, al igual que si fueran activos de tiempo de compilación como gráficos.

Estoy investigando el cambio de un antiguo repositorio de código de tamaño medio / grande (50 usuarios, 60k revisiones, 80Gb de historial, 2Gb de copia de trabajo) de svn. A medida que el número de usuarios ha crecido, hay una gran rotación en el tronco, y las características a menudo se extienden en múltiples confirmaciones, lo que dificulta la revisión del código. Además, sin ramificación no hay forma de "bloquear" el código incorrecto, las revisiones solo se pueden hacer después de que se haya comprometido con el enlace troncal. Estoy investigando alternativas. Esperaba que pudiéramos pasar a git, pero tengo algunos problemas.

El problema con el repositorio actual en cuanto a git es el tamaño. Hay una gran cantidad de residuos viejos allí, y limpiarlos con una rama de filtro cuando se convierte en git puede reducir su tamaño en un orden de magnitud, alrededor de 5-10 GB. Esto todavía es demasiado grande. La razón principal del gran tamaño del repositorio es que hay muchos documentos binarios que son entradas para las pruebas. Estos archivos varían entre .5mb y 30mb, y hay cientos. También tienen bastantes cambios. He visto submódulos, git-annex, etc., pero tener las pruebas en un submódulo se siente mal, al igual que tener un anexo para muchos archivos para los que desea un historial completo.

Entonces, la naturaleza distribuida de git es realmente lo que me impide adoptarlo. Realmente no me importa la distribución, solo quiero la ramificación barata y las potentes funciones de fusión. Como supongo que el 99.9% de los usuarios de git lo hacen, utilizaremos un repositorio central bendecido y desnudo.

No estoy seguro de entender por qué cada usuario debe tener un historial local completo al usar git. Si el flujo de trabajo no está descentralizado, ¿qué están haciendo esos datos en los discos de los usuarios? Sé que en versiones recientes de git puedes usar un clon superficial con solo historial reciente. Mi pregunta es: ¿es viable hacer esto como el modo de operación estándar para todo un equipo? ¿Se puede configurar git para que sea siempre superficial para que pueda tener un historial completo solo centralmente, pero los usuarios por defecto solo tienen 1000 revoluciones de historial? La opción para eso, por supuesto, sería convertir 1000 revoluciones a git y mantener el repositorio svn para arqueología. En ese escenario, sin embargo, nos encontraríamos con el mismo problema nuevamente después de los próximos miles de revisiones a los documentos de prueba.

  • ¿Qué es un buen mejores prácticas para el uso de git con grandes repositorios que contienen muchos archivos binarios que no quieren que la historia de? La mayoría de las mejores prácticas y tutoriales parecen evitar este caso. Resuelven el problema de unos pocos binarios enormes, o proponen descartarlos por completo.
  • ¿Se puede usar la clonación superficial como un modo normal de operación o es un "hack"?
  • ¿Podrían usarse los submódulos para el código donde tiene una dependencia estrecha entre la revisión de la fuente principal y la revisión del submódulo (como en dependencias binarias en tiempo de compilación o un conjunto de pruebas unitarias)?
  • ¿Qué tan grande es "demasiado grande" para un repositorio git (local)? ¿Deberíamos evitar el cambio si podemos reducirlo a 4GB? 2GB?
Anders Forsgren
fuente
posible duplicado de mover un repositorio SVN de varios GB a Git
mosquito
Busqué mucha información sobre esto y no encontré nada que respondiera a mi pregunta. En la pregunta vinculada, los workaounrds (submódulos, anexo, etc.) funcionarían mucho mejor que en mi escenario.
Anders Forsgren
1
Git LFS
CodesInChaos
Perforce puede ser una mejor opción que git, ya que está diseñado para hacer frente a muchos archivos binarios grandes, por lo que muchos desarrolladores de juegos lo utilizan. Plasticscm también vale la pena mirar.
Ian
Solo un lado: evite los submódulos git si puede, ya que complican demasiado el sistema de compilación (que ya es complicado en su caso).
IgorGanapolsky

Respuestas:

10

Wow, esa es una pregunta larga (y un problema complejo). Intentaré intentarlo.

No estoy seguro de entender por qué cada usuario debe tener un historial local completo al usar git.

Esta es una decisión de diseño central con git. Por las razones exactas que necesitaría preguntarle al autor (Linus Torvalds), pero hasta donde yo sé, la razón principal es la velocidad: tener todo local (en un disco rápido o incluso en caché en RAM) hace que las operaciones en el historial sean mucho más rápidas evitando el acceso a la red.

La razón principal del gran tamaño del repositorio es que hay muchos documentos binarios que son entradas para las pruebas. Estos archivos varían entre .5mb y 30mb, y hay cientos. También tienen bastantes cambios.

Ese es el punto en el que pensaría primero. Tener tantos archivos binarios que cambian constantemente en el control de código fuente me parece problemático (incluso con SVN). ¿No puedes usar un enfoque diferente? Ideas:

  • A diferencia del código fuente, un archivo binario de 3 MB probablemente no esté escrito a mano. Si alguna herramienta / proceso lo genera, considere integrar eso en su compilación, en lugar de almacenar los datos.

  • Si eso no es práctico, los archivos binarios suelen estar mejor en un repositorio de artefactos (como Artifactory for Maven & co.). Quizás esa sea una opción para ti.

He mirado submódulos, git-annex, etc., pero tener las pruebas en un submódulo se siente mal, al igual que tener un anexo para muchos archivos para los que desea un historial completo.

En realidad, esto parece que git-annex encajaría perfectamente. git-annex básicamente le permite almacenar el contenido del archivo fuera de un repositorio de git (el repositorio contiene un marcador de posición). Puede almacenar el contenido del archivo de varias maneras (repositorio central de git, unidad compartida, almacenamiento en la nube ...), y puede controlar qué contenido desea tener localmente.

¿Quizás malinterpretaste cómo funciona git-annex? git-annex almacena el historial completo de todos los archivos que administra, solo le permite elegir qué contenido de archivo desea tener localmente.

Finalmente, sobre sus preguntas:

¿Cuál es una buena práctica recomendada para usar git con repositorios grandes que contienen muchos archivos binarios para los que quieres historial?

En mi experiencia, las opciones generalmente son:

  • evitar la necesidad de binarios en el repositorio (generarlos a pedido, almacenarlos en otro lugar)
  • use git-annex (o una solución similar, como Git LFS)
  • vive con un gran repositorio (no todas las operaciones de git se ven afectadas por archivos grandes, y si tienes una computadora y una unidad rápidas, puede ser bastante viable)

¿Se puede usar la clonación superficial como un modo normal de operación o es un "hack"?

Eso podría ser factible; Sin embargo, no creo que esto resuelva su problema:

  • perderías los beneficios de git que provienen de tener un historial completo, como la búsqueda rápida del historial
  • las fusiones pueden volverse difíciles, porque AKAIK debe tener al menos el historial de vuelta al punto de ramificación para fusionarse
  • los usuarios tendrían que volver a clonar periódicamente para mantener pequeño el tamaño de su clon
  • es solo una forma poco común de usar git, por lo que es probable que tengas problemas con muchas herramientas

¿Qué tan grande es "demasiado grande" para un repositorio git (local)? ¿Deberíamos evitar el cambio si podemos reducirlo a 4GB? 2GB?

Eso depende de la estructura del repositorio (pocos / muchos archivos, etc.), de lo que desea hacer, de qué tan robustas son sus computadoras y de su paciencia :-).

Para darle una idea rápida: en mi computadora portátil (nueva pero de baja especificación), la confirmación de un archivo de 500 MB demora entre 30 y 60 segundos. Solo el historial de la lista (git log, etc.) no se ve afectado por los archivos grandes; cosas como "git log -S", que debe escanear el contenido del archivo, son muy lentas; sin embargo, la velocidad está dominada principalmente por E / S, por lo que no es realmente culpa de git.

En un repositorio de 3 GB con un puñado de revisiones, "git log -S" tarda aproximadamente un minuto.

Entonces diría que un par de GB está bien, aunque no es ideal. Probablemente, más de 10-20 GB lo están impulsando, pero podría ser factible, tendría que probarlo.

sleske
fuente
Gracias por tu minuciosa respuesta. Ciertamente analizaré el uso del anexo para los documentos de prueba. La barra de "rendimiento razonable" probablemente esté "cerca de svn", es decir, si es significativamente más lenta para cualquier operación, entonces habría demasiada fricción para cambiar.
Anders Forsgren
Creo que Git LFS también se puede usar para el almacenamiento de archivos binarios grandes.
IgorGanapolsky
@IgorG .: Sí, Git LFS es una alternativa, hay otras. Gracias por señalarlo, edité mi publicación.
sleske
4

A medida que el número de usuarios ha crecido, hay una gran rotación en el tronco, y las características a menudo se extienden en múltiples confirmaciones, lo que dificulta la revisión del código. Además, sin ramificación no hay forma de "bloquear" el código incorrecto, las revisiones solo se pueden hacer después de que se haya comprometido con el enlace troncal

Pasar a git no resolverá estos problemas, son problemas en la forma en que usa la herramienta y si usa git de la misma manera, los problemas permanecerán.

Puede ramificarse en svn con la misma facilidad en git, y la fusión generalmente es igual de fácil y tiene las mismas dificultades. Git fue diseñado para trabajar con el código fuente del núcleo, por lo que hizo algunas suposiciones que pueden no aplicarse en todos los casos, como la suya con grandes binarios e historias masivas. La intención detrás de un DVCS es que cada usuario trabaje efectivamente solo y solo colabore después, es decir, que tengan su propio repositorio (una copia), trabajen como quieran y luego envíen los cambios a cualquier otra persona que lo desee. Un sistema federado utilizado en el desarrollo del kernel de Linux es perfecto para esto: empuja sus cambios al siguiente tipo de la cadena que lo fusiona con su base de código y luego lo empuja al siguiente tipo hasta que llegue a Linus que lo publica en el lanzamiento. La mayoría de los equipos usan git de manera similar, pero con solo un tipo de upstream que a menudo es un repositorio 'gold' del lado del servidor,

Así que primero buscaría cambiar su flujo de trabajo, solo migrar a git una vez que tenga una mejor manera de trabajar. Implemente la ramificación y la fusión en SVN, si no cambia el nombre de los archivos o directorios, la fusión va bastante bien.

gbjbaanb
fuente
44
"Puede ramificarse en svn con la misma facilidad en git, y la fusión es generalmente igual de fácil y tiene los mismos escollos", wow, esa es una afirmación realmente controvertida. En mi opinión, la fusión en git suele ser una brisa y, por lo general, en una pesadilla, incluso en las versiones posteriores a la introducción de un intento a medias de seguimiento de fusión (sí, trabajo con git, no solo en este repositorio). El flujo de trabajo que queremos tener es uno en el que realiza una rama de características, revisión de código / compilación de CI en esa rama. Simplemente no hay forma de hacerlo en SVN sin una frustración masiva.
Anders Forsgren
2
no, lo hacemos todo el tiempo aquí. Solo estoy revisando las 157 ramas en mi repositorio SVN para ver cuáles se pueden eliminar. Nos ramificamos, desarrollamos, revisamos y luego nos fusionamos casi a diario aquí, ocasionalmente nos metemos en problemas, pero eso siempre se soluciona sacando una nueva sucursal de la troncal y fusionando los cambios a esa (para que pueda fusionarse fácilmente a la troncal más adelante) . Sin embargo, eso solo se aplica realmente a las ramas antiguas. Si tienes una frustración masiva, no la entiendes lo suficientemente bien. Git también te dará frustraciones masivas.
gbjbaanb
2
Simplemente no lo experimento. Cuando trabajo con git (como dije que lo hago, pero en repositorios más pequeños) me resulta bastante fácil y natural hacer funciones de ramificación, rebase, aplastamiento y fusión. Los "conflictos de árbol después de renombrar", etc., se sienten mucho más raros, y el hecho de que pueda emular una historia lineal y simple (a través de rebase + squash, etc.) es muy importante. Entonces: en aras de mantener la pregunta sobre el tema (git con repositorios grandes): supongamos que svn no admite el flujo de trabajo que necesito, y git sí.
Anders Forsgren
1
En una compañía anterior usamos git, y conozco a alguien que solía perder su trabajo regularmente usándolo, ¡así que no es un sistema perfecto de ninguna manera! SVN tampoco lo es, pero SVN se adapta mucho mejor a sus circunstancias que git IMHO, y funciona. Sobre el tema, cómo hacer que git funcione como quieres ... Realmente no estoy seguro de que lo haga, lo siento.
gbjbaanb
77
@gbjbaanb si alguien está perdiendo su trabajo con Git, está haciendo algo terriblemente mal.
RubberDuck
2

Mire en la lista de correo de GCC. Migrando el CCG árbol fuente del compilador de de SVN a GIT se analiza en este momento (agosto y septiembre de 2015), mientras se mantiene la historia de GCC. Consulte, por ejemplo, el repositorio de la maquinaria de conversión y los criterios de aceptación para los hilos de correo de conversión git ; encontrará referencias a herramientas y procedimientos relacionados con la conversión (que no es tan sencillo como parece; la conversión de un historial de código tan grande necesita 36 horas y aproximadamente 64 Gbytes de RAM, IIRC)

Basile Starynkevitch
fuente
¿Quiso decir migrar de SVN a Git? Migrar de un sistema de control de versiones a un conjunto de compiladores parece un poco ... extraño. Además, esto se lee un poco más como un comentario que como una respuesta.
8bittree
Sí. Lo siento por el error tipográfico.
Basile Starynkevitch
Gracias. 36 horas suena como una brisa, la nuestra puede convertirse en un par de semanas ...
Anders Forsgren
2

Si la conversión de todo el repositorio SVN en Git da como resultado un gran repositorio que no es factible clonar, puede intentar usar SubGit para crear espejos Git más pequeños para ciertas partes de su repositorio Subversion.

Por ejemplo, puede importar y sincronizar algún subdirectorio de su repositorio SVN http://domain/repos/trunk/project/src:

subgit configure --layout auto --trunk trunk/project/src http://domain/repos project.git
edit project.git/subgit/config
edit project.git/subgit/authors.txt
subgit install project.git

Para más detalles sobre el uso de SubGit, consulte su documentación .

Tan pronto como tenga Git mirror de ese directorio, puede usar el repositorio Git para enviar nuevos cambios que se reflejen inmediatamente en el repositorio SVN. Dado que solo sincroniza cierta parte del repositorio SVN que reduce significativamente el tamaño del repositorio Git convertido y aún puede crear ramas, fusionarlas, emplear cualquier flujo de trabajo desde el lado de Git.

Alternativamente, puede importar todo el repositorio SVN pero excluir archivos grandes de la sincronización:

subgit configure --layout auto --trunk trunk http://domain/repos project.git
edit project.git/subgit/config
...
[svn]
    excludePath = *.bin
    excludePath = *.iso
...
edit project.git/subgit/authors.txt
subgit install project.git

El repositorio Git resultante debería tener un tamaño razonable y los desarrolladores aún pueden usar Git para enviar sus cambios al repositorio Subversion.

Tenga en cuenta que esta solución debería funcionar bien para usted si está listo para mantener el servidor Subversion en funcionamiento y usar Git junto con su repositorio SVN.

Descargo de responsabilidad: soy uno de los desarrolladores de SubGit; SubGit es un software comercial con varias opciones gratuitas disponibles.

vadishev
fuente
1

Me acercaré a su situación de la siguiente manera:

1) Inicialice un repositorio git en el mismo directorio que su repositorio SVN. Hacer git initygit remote add origin para comenzar ese repositorio de git. De esa manera, puede continuar comprometiéndose en SVN y git por separado sin tener que lidiar con una conversión completa de uno a otro hasta que esté listo.

2) Use activamente las herramientas bfg y filter-branch para intentar reducir su repositorio git, como se explica aquí: https://confluence.atlassian.com/bitbucket/reduce-repository-size-321848262.html

3) Use git-annex, o Git LFS, o simplemente un servidor de almacenamiento externo para sus binarios grandes (transporte de archivos usando scripts de shell en tiempo de compilación).

4) Una vez que se sienta cómodo con la estrategia de fusión / ramificación en su repositorio git, y se sienta cómodo con el tamaño de su repositorio git, podrá realizar una migración completa de su svn a git.

Espero que esto ayude.

IgorGanapolsky
fuente