svn - migrar - subgit
Empujando un repositorio Git existente a SVN (16)
¿Qué sucede si no desea comprometer todos los compromisos que realice en Git, en el repositorio SVN? ¿Qué pasa si solo desea enviar de forma selectiva los compromisos por la tubería? Bueno, tengo una mejor solución.
Guardo un repositorio local de Git donde todo lo que hago es buscar y fusionar desde SVN. De esa manera, puedo asegurarme de incluir todos los mismos cambios que SVN, pero mantengo mi historial de confirmación completamente separado de SVN.
Luego guardo una copia de trabajo local de SVN separada que está en una carpeta separada. Ese es el que hago para volver a SVN, y simplemente uso la utilidad de línea de comandos SVN para eso.
Cuando estoy listo para comprometer el estado de mi repositorio Git local a SVN, simplemente copio todo el lío de archivos en la copia de trabajo local de SVN y los confirmo desde allí utilizando SVN en lugar de Git.
De esta manera, nunca tendré que volver a basar, porque la reorganización es como la limpieza.
He estado haciendo todo mi trabajo en Git y empujando a GitHub. Estoy muy contento con el software y el sitio, y no deseo cambiar mis prácticas de trabajo en este momento.
Mi asesor de doctorado está pidiendo a todos los estudiantes que mantengan su trabajo en un repositorio SVN que se encuentra en la universidad. He encontrado toneladas de documentación y tutoriales a punto de desplegar un repositorio SVN existente en Git, pero nada acerca de empujar un repositorio Git a un repositorio SVN nuevo. Supongo que debe haber alguna forma de hacer esto con una combinación de git-svn y una nueva rama y rebasado y todos esos términos maravillosos, pero soy un novato de Git y no me siento seguro con ninguno de ellos.
Luego, solo quiero ejecutar un par de comandos para enviar confirmaciones a ese repositorio SVN cuando lo elija. Deseo seguir usando Git y simplemente hacer que el repositorio SVN refleje lo que hay en Git.
Seré la única persona comprometida con SVN, si esto marca alguna diferencia.
Así es como lo hicimos funcionar:
Clona tu repositorio Git en algún lugar de tu máquina.
Abra .git / config y agregue lo siguiente (desde Mantener un espejo SVN de solo lectura de un repositorio Git ):
[svn-remote "svn"]
url = https://your.svn.repo
fetch = :refs/remotes/git-svn
Ahora, desde una ventana de consola, escriba estos:
git svn fetch svn
git checkout -b svn git-svn
git merge master
Ahora, si se rompe aquí por cualquier razón, escriba estas tres líneas:
git checkout --theirs .
git add .
git commit -m "some message"
Y finalmente, puedes comprometerte a SVN:
git svn dcommit
Nota: siempre desecho esa carpeta después.
Cree un nuevo directorio en el repositorio de Subversion para su proyecto.
# svn mkdir --parents svn://ip/path/project/trunk
Cambie a su proyecto administrado por Git e inicialice git-svn.
# git svn init svn://ip/path/project -s
# git svn fetch
Esto creará una única confirmación porque el directorio de su proyecto SVN todavía está vacío. Ahora vuelva a escribir todo en ese commit, git svn dcommit
y debería estar listo. Sin embargo, seriamente arruinará tus fechas de compromiso.
En mi caso, tuve que iniciar un proyecto limpio desde SVN
$ Project> git svn init protocol://path/to/repo -s
$ Project> git svn fetch
agrega todas tus fuentes de proyectos ...
$ Project> git add .
$ Project> git commit -m "Importing project sources"
$ Project> git svn dcommit
Hace poco tuve que migrar varios repositorios Git a SVN, y después de probar todas las soluciones que pude encontrar, lo que finalmente me funcionó fue Mercurial (sí, utilizando un tercer VCS). Usando esta guía , se me ocurrió el siguiente proceso (en Linux, pero la idea básica también debería funcionar en Windows).
Los paquetes necesarios:
$ sudo apt-get install git subversion mercurial python-subversion
Mercurial debe configurarse agregando lo siguiente a
~/.hgrc
:[extensions] hgext.convert=
Cree algunos directorios de trabajo temporales (tuve varios repositorios para migrar, así que creé directorios para las versiones SVN y Git, para mantenerlos separados):
$ mkdir svn $ mkdir git
Hacer un repositorio SVN local vacío:
$ svnadmin create svn/project
Clona el repositorio de Git existente:
$ git clone server/path/project.git git/project
Que Mercurial haga lo suyo.
$ hg convert --dest-type svn git/project svn/project
Ahora el repositorio SVN debe contener el historial de confirmación completo, pero no con las marcas de tiempo originales. Si esto no es un problema, omita la siguiente parte del paso 11.
Con un poco de trabajo, la fecha y la hora de cada compromiso se pueden cambiar . Como mis repositorios son bastante pequeños, me fue posible hacerlo manualmente. Primero, cree un gancho de
pre-revprop-change
en el repositorio de SVN con el siguiente contenido, para permitir la modificación de la propiedad necesaria:#!/bin/bash exit 0;
Este script tiene que ser ejecutable:
$ chmod +x svn/project/hooks/pre-revprop-change
Mercurial creó una copia de trabajo del repositorio SVN, denominada project -wc, así que cámbielo y edite los tiempos de confirmación:
$ cd project-wc $ svn propedit svn:date --revprop -r 1
Ingrese la fecha y hora correctas (¡preste atención a las zonas horarias!) Y guarde. Debería recibir un mensaje que dice "Establecer un nuevo valor para la propiedad svn: fecha en la revisión 1".
Ahora enjuague y repita para cualquier otra revisión.Opcionalmente, compruebe el historial de confirmaciones para asegurarse de que todo se vea bien:
$ svn log -r 1:HEAD
Luego vuelve a subir un nivel:
$ cd ..
Volcar el repositorio:
$ svnadmin dump svn/project > project.dump
Y carga el volcado en tu servidor de Subversion. ¡Hecho!
Este proceso probablemente también funcionaría directamente entre repositorios remotos, pero me resultó más fácil trabajar con los locales. Arreglar los tiempos de compromiso fue mucho trabajo, pero en general el proceso fue mucho más sencillo que cualquier otro método que encontré.
Me gustaría compartir una gran herramienta que se utiliza en la comunidad de WordPress llamada Scatter
Git complementos de WordPress y un poco de dispersión de la cordura
Esto permite a los usuarios poder enviar su repositorio Git a wordpress.org SVN automáticamente. En teoría, este código se puede aplicar a cualquier repositorio SVN.
Necesitaba enviar mi repositorio Git existente a un repositorio SVN vacío.
Así es como logré hacer esto:
$ git checkout master
$ git branch svn
$ git svn init -s --prefix=svn/ --username <user> https://path.to.repo.com/svn/project/
$ git checkout svn
$ git svn fetch
$ git reset --hard remotes/svn/trunk
$ git merge master
$ git svn dcommit
Funcionó sin problemas. Espero que esto ayude a alguien.
Como tuve que autorizarme con un nombre de usuario diferente al repositorio de SVN (mi origin
usa autenticación de clave pública / privada), tuve que usar la propiedad --username
.
Necesitaba esto también, y con la ayuda de la respuesta de Bombe + algunos jugueteando, lo conseguí funcionando. Aquí está la receta:
Importar Git -> Subversion
1. cd /path/to/git/localrepo
2. svn mkdir --parents protocol:///path/to/repo/PROJECT/trunk -m "Importing git repo"
3. git svn init protocol:///path/to/repo/PROJECT -s
4. git svn fetch
5. git rebase origin/trunk
5.1. git status
5.2. git add (conflicted-files)
5.3. git rebase --continue
5.4. (repeat 5.1.)
6. git svn dcommit
Después del # 3 obtendrás un mensaje críptico como este:
Usando un nivel más alto de URL:
protocol:///path/to/repo/PROJECT => protocol:///path/to/repo
Solo ignora eso.
Cuando ejecuta el número 5, puede obtener conflictos. Resuélvalos agregando archivos con el estado "no fusionado" y reanudando el rebase. Eventualmente, habrás terminado; luego sincronice nuevamente con el repositorio SVN, usando dcommit
. Eso es todo.
Manteniendo los repositorios sincronizados
Ahora puedes sincronizar desde SVN a Git, usando los siguientes comandos:
git svn fetch
git rebase trunk
Y para sincronizar desde Git a SVN, usa:
git svn dcommit
Nota final
Es posible que desee probar esto en una copia local, antes de aplicar a un repositorio en vivo. Puedes hacer una copia de tu repositorio Git a un lugar temporal; simplemente use cp -r
, ya que todos los datos están en el propio repositorio. A continuación, puede configurar un repositorio de pruebas basado en archivos, utilizando:
svnadmin create /home/name/tmp/test-repo
Y verifica una copia de trabajo usando:
svn co file:///home/name/tmp/test-repo svn-working-copy
Eso te permitirá jugar con las cosas antes de hacer cambios duraderos.
Anexo: Si te equivocas git svn init
Si ejecutó accidentalmente git svn init
con la URL incorrecta y no era lo suficientemente inteligente como para realizar una copia de seguridad de su trabajo (no pregunte ...), no puede volver a ejecutar el mismo comando. Sin embargo, puede deshacer los cambios emitiendo:
rm -rf .git/svn
edit .git/config
Y elimine la sección [svn-remote "svn"]
.
A continuación, puede ejecutar git svn init
nuevo.
Otra secuencia más que funcionó (con algunos comentarios en cada paso):
Instalar
git-svn
ysubversion
toolkits:sudo apt-get install git-svn subversion
Cambiar dentro del
PROJECT_FOLDER
cd PROJECT_FOLDER
Cree la ruta del proyecto en el servidor de Subversion (desafortunadamente, el complemento
git-svn
actual tiene un defecto en comparación con TortoiseSVN). No puede almacenar el código fuente directamente en elPROJECT_FOLDER
. En su lugar, de forma predeterminada, cargará todo el código enPROJECT_FOLDER/trunk
.svn mkdir --parents protocol: /// path / to / repo / PROJECT_FOLDER / trunk -m "creando un marcador de posición de git repo"
Este es el lugar donde el trunk
al final del camino es obligatorio
Inicialice el contexto del complemento
git-svn
dentro de la carpeta.git
git svn init -s protocol:///path/to/repo/PROJECT_FOLDER
Este es el lugar donde el
trunk
al final del camino no es necesario.Obtener una información vacía del repositorio de
Subversion
git svn fetch
Este paso ayuda a sincronizar el servidor Subversion con el complemento
git-svn
. Este es el momento en que el complementogit-svn
estableceremotes/origin
ruta deremotes/origin
y lo asocia con la subcarpetatrunk
en el lado del servidor.Los antiguos cambios de Git se hicieron antes de que el complemento
git-svn
se involucrara en el proceso (este paso es opcional )git rebase origin/trunk
Agregar archivos nuevos / modificados para confirmar (este paso es regular para las actividades de Git y es opcional )
git add .
Confirme los archivos recién agregados en el repositorio Git local (este paso es opcional y solo es aplicable si se ha usado el paso 7):
git commit -m "Importing Git repository"
Presionando todo el historial de cambios del proyecto en el servidor de Subversion:
git svn dcommit
Puedes hacer un nuevo repositorio SVN. Exporte su proyecto de Git (enviando archivos .git). Agréguelo al repositorio de SVN (inicialice el repositorio con lo que tenía hasta ahora en Git). Luego use las instrucciones para importar repositorios SVN en un proyecto Git nuevo.
Pero esto perderá tu anterior historial de Git.
Si desea seguir trabajando con Git como su repositorio principal y solo necesita "exportar" las revisiones a SVN de vez en cuando, puede usar Tailor para mantener el repositorio de SVN sincronizado. Puede copiar revisiones entre diferentes sistemas de control de origen y actualizaría el SVN con los cambios que realice en Git.
No he intentado una conversión de Git a SVN, pero para un ejemplo de SVN -> SVN vea esta respuesta .
Si no tiene que usar ningún SVN específico y está usando GitHub, puede usar su conector SVN.
Más información está aquí: Colaborando en GitHub con Subversion
Solo quiero compartir algo de mi experiencia con la respuesta aceptada. Hice todos los pasos y todo estaba bien antes de ejecutar el último paso:
git svn dcommit
$ git svn dcommit
Uso del valor no inicializado $ u en la sustitución (s ///) en la línea /usr/lib/perl5/vendor_perl/5.22/Git/SVN.pm.
Uso del valor no inicializado $ u en concatenación (.) O cadena en /usr/lib/perl5/vendor_perl/5.22/Git/SVN.pm línea 101. refs / remotes / origin / HEAD: '' https://192.168.2.101/svn/PROJECT_NAME ''no se encuentra en'' ''
Encontré el hilo https://github.com/nirvdrum/svn2git/issues/50 y finalmente la solución que apliqué en el siguiente archivo en la línea 101 /usr/lib/perl5/vendor_perl/5.22/Git/SVN.pm
Reemplacé
$u =~ s!^/Q$url/E(/|$)!! or die
con
if (!$u) {
$u = $pathname;
}
else {
$u =~ s!^/Q$url/E(/|$)!! or die
"$refname: ''$url'' not found in ''$u''/n";
}
Esto solucionó mi problema.
Usar git rebase
directamente perderá el primer commit. Git lo trata de manera diferente y no puede cambiarlo.
Existe un procedimiento que conservará el historial completo: http://kerneltrap.org/mailarchive/git/2008/10/26/3815034
Transcribiré la solución aquí, pero los créditos son para Björn.
Inicializar git-svn:
git svn init -s --prefix=svn/ https://svn/svn/SANDBOX/warren/test2
El prefijo le proporciona las ramas de seguimiento remoto como "svn / trunk", lo cual es bueno porque no obtiene nombres ambiguos si llama a su sucursal local solo "trunk". Y -s
es un acceso directo para el diseño estándar de troncales / etiquetas / ramas.
Busca las cosas iniciales de SVN:
git svn fetch
Ahora busque el hash de su confirmación de raíz (debería mostrar una confirmación única):
git rev-list --parents master | grep ''^./{40/}$''
A continuación, obtener el hash del commit de tronco vacío:
git rev-parse svn/trunk
Crea el injerto:
echo <root-commit-hash> <svn-trunk-commit-hash> >> .git/info/grafts
Ahora, "gitk" debería mostrar svn/trunk
como la primera confirmación en la que se basa su rama maestra.
Hacer el injerto permanente:
git filter-branch -- ^svn/trunk --all
Suelta el injerto:
rm .git/info/grafts
gitk aún debería mostrar svn/trunk
en la ascendencia del maestro.
Linealiza tu historia sobre el tronco:
git svn rebase
Y ahora "git svn dcommit -n" debería decirle que se comprometerá con el tronco.
git svn dcommit
Git -> SVN con historial completo de confirmaciones
Tuve un proyecto Git y tuve que moverlo a SVN. Así lo hice, manteniendo todo el historial de cometidos. Lo único que se pierde es el tiempo de confirmación original, ya que libSVN establecerá la hora local cuando hagamos git svn dcommit
.
Cómo:
Tener un repositorio SVN donde queremos importar nuestras cosas y clonarlas con git-svn:
git svn clone https://path.to/svn/repository repo.git-svn`
Ve allí:
cd repo.git-svn
Agregue el control remoto del repositorio Git (en este ejemplo estoy usando C: /Projects/repo.git ). Quieres presionar a SVN y darle el nombre old-git:
git remote add old-git file:///C/Projects/repo.git/
Obtenga la información de la rama maestra del repositorio de git antiguo al repositorio actual:
git fetch old-git master
Verifique la rama maestra del control remoto old-git en una nueva rama llamada old en el repositorio actual:
git checkout -b old old-git/master`
Rebase para poner el HEAD encima de old-git / master. Esto mantendrá todos tus compromisos. Básicamente, lo que esto hace es tomar todo tu trabajo realizado en Git y ponerlo encima del trabajo al que estás accediendo desde SVN.
git rebase master
Ahora vuelve a tu rama maestra:
git checkout master
Y puedes ver que tienes un historial de compromiso limpio. Esto es lo que quieres empujar a SVN.
Empuje su trabajo a SVN:
git svn dcommit
Eso es todo. Está muy limpio, sin piratería, y todo funciona perfectamente fuera de la caja. Disfrutar.