git-svn: ¿cuál es el equivalente a `svn switch --relocate`?

88

Un repositorio svn que estoy duplicando a través de git-svn ha cambiado de URL.

En vainilla svn simplemente harías svn switch --relocate old_url_base new_url_base.

¿Cómo puedo hacer esto usando git-svn?

El simple cambio de la url svn en el archivo de configuración falla.

kch
fuente
Debería intentar y posiblemente aceptar esta respuesta: stackoverflow.com/a/4061493/1221661
Fritz
Respuesta más actualizada: stackoverflow.com/a/40523789/537554 . Misma pregunta, pero formulada desde la perspectiva de un usuario de Git.
ryenus

Respuestas:

61

Esto maneja mi situación bastante bien:

https://git.wiki.kernel.org/index.php/GitSvnSwitch

Cloné usando el file://protocolo y quería cambiar al http://protocolo.

Es tentador editar la urlconfiguración en la [svn-remote "svn"]sección de .git/config, pero por sí solo no funciona. En general, debe seguir el siguiente procedimiento:

  1. Cambie la urlconfiguración de svn-remote al nuevo nombre.
  2. Corre git svn fetch. ¡Esto necesita obtener al menos una nueva revisión de svn!
  3. Cambie la urlconfiguración de svn-remote a la URL original.
  4. Ejecutar git svn rebase -lpara hacer un rebase local (con los cambios que se produjeron con la última operación de recuperación).
  5. Cambie la urlconfiguración de svn-remote de nuevo a la nueva URL.
  6. Ahora, git svn rebasedebería funcionar de nuevo.

Las almas aventureras pueden querer intentarlo --rewrite-root.

kch
fuente
2
para ser justos, esto realmente me falló y terminé volviendo a clonar el repositorio. Es difícil conseguir que git lo maneje cuando se cambia el nombre del directorio svn.
Gregg Lind
Preferiría aceptar un artículo más detallado, pero es justo que lo acepte hasta que aparezca una nueva respuesta.
kch
2
Aquí hay otra descripción de este procedimiento: theadmin.org/articles/git-svn-switch-to-a-different-a-svn-url
n8gray
el enlace proporcionado en la respuesta aceptada está desactualizado y el nuevo a partir de ahora es: git.wiki.kernel.org/articles/g/i/t/GitSvnSwitch_8828.html Seguí el "Caso general" y fue simple y realmente funcionó bien.
TcMaster
2
@TcMaster: funcionó para mí también ... pero es por eso que las respuestas no deben contener solo enlaces, se vuelven obsoletos y se vuelven inútiles ... Voy a agregar una respuesta wiki de la comunidad.
UncleZeiv
37

Puede ver si lo siguiente funciona bien:

  1. Si svn-remote.svn.rewriteRootno existe en el archivo de configuración ( .git/config):

    git config svn-remote.svn.rewriteRoot <currentRepositoryURL>
    
  2. Si svn-remote.svn.rewriteUUIDno existe en el archivo de configuración:

    git config svn-remote.svn.rewriteUUID <currentRepositoryUUID>
    

    El currentRepositoryUUIDse puede obtener de .git/svn/.metadata.

  3. git config svn-remote.svn.url <newRepositoryURL>

H Krishnan
fuente
Fantástico, gracias, esto funcionó muy bien para mí (clonado a través de file://, cambiar a svn+ssh); solo notando que: este procedimiento no necesita "buscar al menos una nueva revisión de svn"; también ./.git/svn/.metadataafter first svn rebasecontiene el <newRepository>as reposRoot, pero esto no es suficiente para eliminar las rewrite*claves de .git/config; por lo tanto, esas claves deben guardarse permanentemente allí, según tengo entendido.
sdaau
1
A mí también me funcionó, como un encanto. El OP debería probar este y obtenerlo como la respuesta correcta.
Rafareino
Perfecto. Tenía un gran proyecto con miles de confirmaciones en el historial, por lo que un nuevo clon habría destruido el historial (o tardaría mucho en finalizar la compra). Estoy usando svn+ssh://y nuestro servidor svn acaba de cambiar el dominio de .sea .compara desinfectar nuestro nombre interno.
UlfR
Funcionó como un regalo para mí. Tenía un repositorio de 2 años con miles de confirmaciones, el repositorio se movió a un nuevo host, por lo que esto evitó un (temido) clon completo de svn.
David Victor
21

Desafortunadamente, la mayoría de los enlaces en estas respuestas no funcionan, así que duplicaré un poco de información de la wiki de git para referencia futura.

Esta solución funcionó para mí:

  • Edite la svn-remote url(o la fetchruta) .git/configpara que apunte al nuevo dominio / url / ruta

  • Ejecuta git git svn fetch. ¡Esto necesita obtener al menos una nueva revisión de svn!

  • Si lo intenta git svn rebaseahora, recibirá un mensaje de error como este:

    Unable to determine upstream SVN information from working tree history
    

    Creo que esto se debe a que git svnestá confundido por el hecho de que su última confirmación antes de la recuperación tendrá un git-svn-idapunte a la ruta anterior, que no coincide con la que se encuentra en .git/config.

  • Como solución alternativa, cambie svn-remote url(o fetchruta) de nuevo al dominio / URL / ruta original

  • Ahora ejecute de git svn rebase -lnuevo para hacer una rebase local con los cambios que se produjeron con la última operación de recuperación. En esta ocasión se va a trabajar, al parecer porque git svnno será confundido por el hecho de que el git-svn-idde la nueva cabeza no coincide con la encontrada en .git/config.

  • Finalmente, cambie svn-remote url(o fetchruta) de nuevo al nuevo dominio / url / ruta

  • ¡En este punto git svn rebasedebería funcionar de nuevo!

La información original se encontró aquí .

TíoZeiv
fuente
3

Git svn se basa en gran medida en la URL de svn. Cada confirmación que se importa desde svn tiene una git-svn-idque incluye la URL de svn.

Una estrategia de reubicaciones válida es llamar git-svn cloneal nuevo repositorio y fusionar los cambios en ese nuevo cierre. Para obtener un procedimiento más detallado, consulte este artículo:

http://www.sanityinc.com/articles/relocating-git-svn-repositories

Adam Alexander
fuente
2

git filter-branch

Este script , tomado de una entrada de blog , me ha funcionado. Proporcione la URL de repositorio nueva y antigua como parámetro, al igual que para svn switch --relocate.

La secuencia de comandos llama git filter-branchpara reemplazar las URL de Subversion en los git-svn-idmensajes de confirmación, actualizaciones .git/configy también actualiza los git-svnmetadatos al recrearlos usando git svn rebase. Si bien git svn clonepodría ser la solución más sólida, el filter-branchenfoque funciona mucho más rápido para grandes repositorios (horas frente a días).

#!/bin/sh

# Must be called with two command-line args.
# Example: git-svn-relocate.sh http://old.server https://new.server
if [ $# -ne 2 ]
then
  echo "Please invoke this script with two command-line arguments (old and new SVN URLs)."
  exit $E_NO_ARGS
fi

# Prepare URLs for regex search and replace.
oldUrl=`echo $1 | awk '{gsub("[\\\.]", "\\\\\\\&");print}'`
newUrl=`echo $2 | awk '{gsub("[\\\&]", "\\\\\\\&");print}'`

filter="sed \"s|^git-svn-id: $oldUrl|git-svn-id: $newUrl|g\""
git filter-branch --msg-filter "$filter" -- --all

sed -i.backup -e "s|$oldUrl|$newUrl|g" .git/config

rm -rf .git/svn
git svn rebase
krlmlr
fuente
1

git_fast_filter

Aún más rápido que git-filter-branch(es decir, minutos en lugar de horas), pero similar en espíritu, es usar git_fast_filter. Sin embargo, esto requiere un poco más de codificación y no existe una solución ordenada y lista para usar. En contraste con git-filter-branch, esto creará una nueva cesión temporal de un viejo uno. Se supone que masterapunta al último compromiso SVN.

  1. Clonar git_fast_filterdel repositorio de Gitorious.
  2. Cree un script de Python en el mismo directorio donde lo clonó git_fast_filterbasado en este Gist , configure el bit ejecutable usando chmod +x. Adapte las rutas de repositorio nuevas y antiguas. (El contenido del script también se pega a continuación).
  3. Inicialice un nuevo repositorio de destino usando git init, cambie el directorio de trabajo a este nuevo repositorio.
  4. Ejecute la siguiente tubería:

    (cd path/to/old/repo && git-fast-export --branches --tags --progress=100) | \
        path/to/git_fast_filter/commit_filter.py | git-fast-import
    
  5. Copie .git/config, y quizás otros archivos relevantes .git/infodesde el antiguo repositorio al nuevo repositorio.

  6. Quitar .git/svn.
  7. Tenga en git-svncuenta la nueva asignación de números de revisión

    1. Ejecutar git branch refs/remotes/git-svn master

      • Sus controles remotos git-svn pueden llamarse de manera diferente a refs/remotes/git-svn, consultar .git/config, svn-remotesecciones
    2. Ejecutar git svn info. Si este comando se congela, algo anda mal. Debería reconstruir la asignación del número de revisión.

    3. Retire la rama falsa refs/remotes/git-svn, será recreada porgit-svn

  8. Sincronice llamando git svn rebase.

A continuación se muestra el contenido de commit_filter.py, reemplace los valores de IN_REPOy OUT_REPOsegún corresponda:

#!/usr/bin/python

from git_fast_filter import Commit, FastExportFilter
import re
import sys

IN_REPO = "https://svn.code.sf.net/p/matsim/code"
OUT_REPO = "https://svn.code.sf.net/p/matsim/source"

IN_REPO_RE = re.compile("^git-svn-id: %s" % re.escape(IN_REPO), re.M)
OUT_REPO_RE = "git-svn-id: %s" % OUT_REPO

def my_commit_callback(commit):
  commit.message = IN_REPO_RE.sub(OUT_REPO_RE, commit.message)
  sys.stderr.write(".")

filter = FastExportFilter(commit_callback = my_commit_callback)
filter.run()
krlmlr
fuente
0

La git svn rebase -lsolución anterior no funcionó para mí. Decidí hacerlo de una manera diferente:

  1. Clone el antiguo repositorio SVN en git repo oldy el nuevo SVN en git reponew
  2. Buscar oldennew
    • cd new
    • git fetch ../old
    • git tag old FETCH_HEAD
  3. Rebase newencima de old(debería tener éxito porque los árboles en la raíz newy la punta de oldson idénticos)
    • git checkout master(Se asume que la masterrama apunta a la cabeza SVN. Este será el caso con un clon limpio; de lo contrario, haga dcommit antes de comenzar).
    • git rebase --root --onto old
  4. Reconstruir los metadatos de git-svn newpara dar cuenta de la rebase
    • git update-ref --no-deref refs/remotes/git-svn master(ajuste la referencia remota dependiendo de cómo clonó, por ejemplo, podría ser refs/remotes/svn/trunk)
    • rm -r .git/svn
    • git svn info
Ben Challenor
fuente
1. ¿Empieza con un nuevo clon de la nueva ubicación a la nueva? Si es así, ¿por qué no ha terminado en ese momento? 2. Si cambia la base de lo nuevo a lo antiguo, ¿todas las confirmaciones anteriores mencionan la URL anterior en su entrada de registro de confirmación svn-id? 3. ¿Existe alguna documentación que se guarde para eliminar .git / svn? (3b: ¿qué comando está reconstruyendo los metadatos de git-svn, información de git svn?)
Micha Wiedenmann
0

Basándome en algunas de las otras respuestas a esta pregunta, se me ocurrió un script Ruby que maneja la reubicación de git-svn. Puede encontrarlo en https://gist.github.com/henderea/6e779b66be3580c9a584 .

Maneja la reubicación sin verificar otra copia, e incluso maneja el caso donde hay cambios no empujados en una o más ramas (ya que eso rompe la lógica regular). Utiliza cosas de la respuesta de git filter-branch (para la lógica principal) y la respuesta sobre copiar ramas de una instancia del repositorio a otra (para copiar ramas con cambios no empujados).

He estado usando esto para reubicar un montón de repositorios git-svn que tengo para trabajar, y esta versión del script (he pasado por innumerables iteraciones) parece funcionar para mí. No es muy rápido, pero parece manejar todos los casos que he encontrado y resulta en un repositorio completamente reubicado.

El script le da la opción de crear una copia del repositorio antes de realizar cualquier cambio, por lo que puede usar esta opción para crear una copia de seguridad. Es necesario crear una copia si tiene cambios no enviados en alguna rama.

El script no utiliza gemas u otras bibliotecas que no se incluyan en la instalación normal de MRI Ruby. Utiliza las bibliotecas readline y fileutils incluidas en MRI.

Con suerte, mi guión le resultará útil a otra persona. No dude en realizar cambios en el guión.

NOTA: Solo he probado este script con git 2.3.0 / 2.3.1 y Ruby 2.2.0 en OS X 10.10 Yosemite (ya que ese es el entorno que uso), pero espero que funcione también en otros entornos. Sin embargo, no hay garantías sobre Windows.

Eric Henderson
fuente