¿Cómo le digo a git-svn sobre una rama remota creada después de obtener el repositorio?

193

Estoy usando git-svnpara trabajar en contra del repositorio central de Subversion de mi compañía. Recientemente hemos creado una nueva rama de características en el repositorio central.

¿Cómo le digo a Git al respecto? Cuando corro git branch -rsolo puedo ver las ramas que existieron cuando corrí fetchcontra el repositorio de Subversion para inicializar mi repositorio de Git.

Hank Gay
fuente
Las respuestas desde aquí: stackoverflow.com/questions/13376917/… también pueden ser útiles.
Tomasz Gandor

Respuestas:

294

Puede agregar manualmente la rama remota,

git config --add svn-remote.newbranch.url https://svn/path_to_newbranch/
git config --add svn-remote.newbranch.fetch :refs/remotes/newbranch
git svn fetch newbranch [-r<rev>]
git checkout -b local-newbranch -t newbranch
git svn rebase newbranch
vjangus
fuente
3
simplemente agregando este enlace a los documentos como referencia kernel.org/pub/software/scm/git/docs/git-svn.html
slf
1
Desde .git / config es bastante fácil entender cómo se pueden configurar ramas remotas desde repositorios únicos / múltiples.
Mikael Lepistö
66
Si pudiera votar esto ocho veces, lo haría. Finalmente, una forma de agregar una rama svn que se agrega en una ubicación no estándar.
Tim Keating
77
Me sale fatal: Cannot setup tracking information; starting point 'newbranch' is not a branch.en el paso de pago git.
phpguru
17
@phpguru Intente eliminar el indicador de opción -t para que se convierta en 'git checkout -b local-newbranch newbranch', no olvide incluir el prefijo del control remoto a newbranch (ej. origen / newbranch).
mj1531
96

Si desea rastrear TODAS las ramas remotas de svn, entonces la solución es tan simple como:

git svn fetch

Esto buscará TODAS las ramas remotas que aún no se han obtenido.

Consejo adicional: si primero desprotegió el tronco y luego desea rastrear TODAS las ramas, edite .git/configpara que se vea así y vuelva a ejecutar git svn fetch:

[svn-remote "svn"]
        url = https://svn/path_to_repo_root/
        fetch = path_to_trunk:refs/remotes/git-svn
        branches = path_to_branches/*:refs/remotes/*

Los puntos clave urldeben apuntar a la raíz del repositorio, y las rutas definidas en fetchy branchesdeben ser relativas a url.

Si desea buscar solo ramas específicas en lugar de TODAS, hay un buen ejemplo en git svn --help:

[svn-remote "huge-project"]
        url = http://server.org/svn
        fetch = trunk/src:refs/remotes/trunk
        branches = branches/{red,green}/src:refs/remotes/branches/*
        tags = tags/{1.0,2.0}/src:refs/remotes/tags/*

Con versiones anteriores de git-svn, una vez que especificó ramas como esta, es posible que no pueda obtener nuevas ramas git svn fetch. Una solución es agregar más fetchlíneas, como esta:

[svn-remote "huge-project"]
        url = http://server.org/svn
        fetch = trunk/src:refs/remotes/trunk
        fetch = branches/blue:refs/remotes/branches/blue
        fetch = branches/yellow:refs/remotes/branches/yellow
        branches = branches/{red,green}/src:refs/remotes/branches/*

Otra solución alternativa de @AndyEstes: edite .git/svn/.metadatay cambie el valor de branches-maxRevo tags-maxReva una revisión antes de crear cualquier rama o etiqueta recién especificada. Una vez que haya hecho esto, ejecute git svn fetchpara rastrear la nueva rama remota svn.

janos
fuente
1
Si ya ha obtenido la revisión a la que realizó la ramificación svn antes de establecer esa configuración, es posible que desee hacer git svn reset.
kcm1700 18/0713
3
¡La edición .git/svn/.metadatafue muy útil! Estaba agregando ramas adicionales en mi .git/config, que git svn fetchno se repusieron, porque el número de revisión de metadatos estaba "demasiado lejos". En un caso, solo se obtuvo el último commit de una rama. Tengo manualmente deshacerse de la rama defectuosa (renombrado .git/svn/refs/remotes/svn/qa/XYZa .git/svn/refs/remotes/svn/qa/XYZ~, dejó caer su existencia en .git/packed-refs, etc) ... recogido un número de revisión "antes" de los metadatos ... RAN git svn fetchpara finalmente obtener un historial completo w / correcta gráfica, conectada.
starlocke
8
¡ESTO DEBE SER LA RESPUESTA ACEPTADA! @janos, ¡me acabas de salvar horas de dolor de cabeza! Si alguna vez vienes a la India, ¡te llevaré a tomar una cerveza!
Roopesh Shenoy
1
O: git svn fetch --all.
kenorb
1
Esta respuesta es sorprendente, porque responde a 7 preguntas para las que no pude encontrar respuestas, y lo hace sin escribir una narrativa de 6 páginas.
Droj
53

Parece que solo necesitaba hacerlo git svn fetch; De alguna manera, me había convencido de que obtendría todo el repositorio en lugar de solo los cambios.

Hank Gay
fuente
77
@mitjak ¿Por qué no es la respuesta correcta, si es la solución? No entiendo la sutileza de la respuesta.
rholmes
'una solución' tal vez no 'la solución'
slf
1
@rholmes: estoy bastante seguro de que mitjak significa que esa es la solución a su problema, pero no la respuesta a la pregunta que hizo. (Porque hiciste la pregunta equivocada; malinterpretaste el problema en ese momento.)
Mike Nelson
Esto funciona cuando la rama existía en el momento en que clonaste el repositorio svn en git. No funcionará si se creó una rama en el repositorio svn después.
Petr Gladkikh
3
Funciona bien cuando la rama se creó después del clon, lo hago todo el tiempo.
Tim Gautier
15

Tal vez lo arruiné de alguna manera, pero seguí las instrucciones en la respuesta de vjangus y casi funcionó. El único problema era que newbranch no parecía estar ramificado del tronco. En gitk, era una especie de "flotación" por sí solo; no tenía antepasado común con el tronco.

La solución a esto fue:

  1. Encuentre el SHA1 de la última confirmación que ocurrió en el tronco antes de que se creara la rama.
  2. Encuentre el SHA1 de la primera confirmación en la nueva rama (el mensaje probablemente sea "Nueva rama creada, copiada de troncal @ 12345" o algo así)
  3. git diff-tree <sha1 from step 1> <sha1 from step 2>- No debe haber salida. Si hay salida, es posible que haya seleccionado las confirmaciones incorrectas.
  4. git checkout local-newbranchentonces git rebase <sha1 from step 1>. Esto se basará local-newbranchen el nuevo árbol pero remotes/newbranchaún se desconectará.
  5. Vaya al archivo .git/refs/remotes/newbranchy edítelo para que contenga el SHA1 completo de la nueva confirmación (en el rebase newbranch) que corresponde a la confirmación anterior a la que apunta actualmente. (O tal vez usar git-update-ref refs/remotes/newbranch <new-SHA>. Gracias inger.)
  6. La próxima vez que git svn dcommita newbranch, usted obtendrá un montón de mensajes acerca de que la actualización de algunos de registro. Esto es normal, creo.

Recomiendo mantenerse gitk --allabierto todo el tiempo y actualizarlo a menudo para realizar un seguimiento de lo que está haciendo. Todavía soy algo nuevo en git y git svn, así que sugiera mejoras a este método.

MatrixFrog
fuente
2
Gracias, esto suena útil. Aproximadamente 5. probablemente 'git-update-ref refs / remotes / newbranch <new-SHA>' es la opción más segura.
Inger
Solo intenté con vjangus de nuevo y funcionó perfectamente. Voy a dejar esto aquí de todos modos, ya que podría ser valiosa para alguien ...
MatrixFrog
1
La solución vjangus siempre crea la nueva rama desconectada del tronco. Supongo que esto se debe a la forma en que SVN no tiene idea de cómo se copia el contenido real.
bogdan.mustiata
Mi experiencia con un gran repositorio git-svn es que las ramas svn siempre se crean en git separado del tronco. Debería haber alguna forma de conectarlos, pero no me he tomado el tiempo para resolverlo. AFAIK, no puede volver a crear la rama git que está conectada a la rama svn, porque eso estropeará la lógica dcommit. Acabamos de aprender a vivir con eso.
Spencer
7

Una simplificación de la respuesta de vjangus:

Si está utilizando el diseño estándar en SVN y ha hecho el inicio svn habitual, git-svn hará las cosas de configuración por usted. Sólo:

  1. Encuentra la revisión de copia de sucursal en SVN
  2. Obtenga esa revisión con git-svn
  3. Crear una nueva sucursal local de seguimiento remoto

Un ejemplo. SVN url es svn+ssh://[email protected]/repo. SVN sucursal que estoy buscando es newbranch. La rama local de git (seguimiento remoto newbranch) será git-newbranch.

Paso 1: busque la revisión de copia de sucursal

    # svn log --stop-on-copy svn + ssh: //[email protected]/repo/branches/newbranch | cola -4
    r7802 | alguien | 2014-03-21 18:54:58 +0000 (viernes, 21 de marzo de 2014) | 1 linea

    ramificando HEAD a newbranch
    -------------------------------------------------- ----------------------

Entonces el punto de ramificación en SVN es la revisión 7802.

Paso 2: recuperar la revisión

    # git svn fetch -r 7802
    Posible punto de ramificación encontrado: svn + ssh: //[email protected]/repo/trunk => svn + ssh: //[email protected]/repo/branches/newbranch, 7801
    Rama principal encontrada: (referencias / controles remotos / troncal) 8dcf3c5793ff1a8a79dc94d268c91c2bf388894a
    Siguiente padre con do_switch
    Padres seguidos exitosamente
    r7802 = 9bbd4194041675ca5c9c6f3917e05ca5654a8a1e (refs / remotes / newbranch)

git-svn hizo todo el trabajo y ahora sabe sobre el control remoto:

    # git show-ref | grep newbranch
    2df23af4733f36f5ad3c14cc1fa582ceeb3edb5c refs / remotes / newbranch

Paso 3: cree su nueva sucursal local siguiendo la remota:

    # git checkout -b git-newbranch -t newbranch
    Extraer archivos: 100% (413/413), hecho.
    Branch git-newbranch configurado para rastrear refs locales remotos / remotos / newbranch.
    Cambió a una nueva rama 'git-newbranch'
Gil Hamilton
fuente
¡Seguir esto finalmente me permitió entender ( show-refes invaluable)! Para cualquier persona atascada con referencias remotas erróneamente a las ramas, puede eliminarlas (tuve que hacerlo git branch -d newbranchy luego forzar la eliminación del directorio de referencia .git/svn/refs/remotes/newbranch) y luego comenzar de nuevo en el paso 2 (arriba).
tutuDajuju
5

No he encontrado ninguna documentación sobre esta característica, pero parece que la configuración de git svn admite múltiples entradas de búsqueda. De esta manera, también puede agregar ramas por separado sin necesidad de agregar otra entrada de repositorio svn remota a su configuración ni usar comodines para obtener todas las ramas de cierto directorio.

Suponga que su árbol SVN es realmente desagradable con muchas ramas sin ninguna lógica de cómo están ubicadas, por ejemplo, tener ramas y subdirectorios que contienen más ramas.

es decir

trunk
branches
  -> branch1
  -> sub-dir1
    -> branch2
    -> branch3
  -> sub-dir2
    -> branch4
    -> sub-dir3
      -> branchX 
<... hundreds more ...>

y solo desea elegir a mano algunas de las ramas que se incluirán en su repositorio git.

Primero puede iniciar su repositorio con solo troncal sin ninguna rama adicional:

git svn clone -r 10000:HEAD https://svn.com/MyRepo myrepo --prefix=svn/ --trunk=trunk 

Después de eso, debería ver la siguiente configuración:

localhost: elhigu$ git config --get-regexp "svn-remote."
svn-remote.svn.url https://svn.com/MyRepo
svn-remote.svn.fetch trunk:refs/remotes/svn/trunk

cuando quiera obtener una nueva sucursal de MyRepo, simplemente puede agregar nuevas entradas de recuperación a la configuración:

git config --add svn-remote.svn.fetch branches/sub-dir2/branch4:refs/remotes/svn/branches/sub-dir2/branch4

O puede editar la misma configuración en .git / config

Para buscar las nuevas ramas después de agregarlas a la configuración, simplemente ejecute:

git svn fetch -r 10000:HEAD

[Editar] A veces parece necesario ejecutar fetch con --todos los parámetros para recuperar ramas recién agregadas:

git svn fetch --all -r 10000:HEAD
Mikael Lepistö
fuente
4

En lugar de lidiar con las peculiaridades de git-svn, puede probar SubGit .

Uno tiene que instalar SubGit en el repositorio de Subversion. Después de eso, se puede usar el flujo de trabajo estándar de git en lugar de usar comandos especiales de git-svn:

  1. Empujando nuevos commits:

    git-svn:

    $ git commit
    $ git svn rebase
    $ git svn dcommit
    

    SubGit:

    $ git commit
    $ git push
    
  2. Obteniendo cambios entrantes

    git-svn:

    $ git svn rebase
    

    SubGit:

    $ git pull [--rebase]
    
  3. Crear una nueva sucursal:

    git-svn:

    $ git svn branch foo
    $ git checkout -b foo -t remotes/foo
    $ git commit
    $ git svn dcommit
    

    SubGit:

    $ git checkout -b foo
    $ git commit
    $ git push
    

Consulte la documentación de SubGit para más detalles.

vadishev
fuente
1
SubGit tiene la desventaja de que crea dos repositorios: uno svn y un repositorio git "sombra". Esto podría ser un problema para grandes repositorios SVN ...
Udo
@Udo si el repositorio SVN tiene algunos proyectos, uno puede especificar solo uno de ellos y sincronizarlo con el repositorio Git. En este caso, no es necesario convertir todo el repositorio de Subversion en Git. Pero si uno tiene un gran proyecto SVN en este repositorio, puede convertir no todo el historial de este repositorio sino el historial a partir de una revisión mínima. Esto permite disminuir el tamaño del repositorio Git traducido.
vadishev
1
@Udo: cualquier empresa que no esté dispuesta a comprar un disco duro en su servidor de repositorio tiene sus prioridades en mal estado. Pero la mayoría de los lugares con grandes repositorios toman sus repositorios bastante en serio, y los requisitos de espacio en disco para los repositorios generalmente no son un problema importante, incluso para empresas con décadas de historia y decenas de millones de líneas de código y cientos de miles de revisiones. Es la forma más concreta de la compañía de sus principales activos intelectuales, y el espacio en disco es bastante económico. Puede provocar la necesidad de actualizar un controlador RAID, pero aun así, la ganancia en productividad ...
Bob Kerns
@Bob Kerns: el punto es que SVN y Git "en cuanto al tamaño" no son compatibles. No es una cuestión de almacenamiento en disco más o menos. Pero puede trabajar con un gran repositorio SVN porque generalmente necesita retirar solo unos pocos archivos / proyectos. Pero no puedes clonar un gran repositorio de Git, al menos no se burla ;-) Por "enorme" me refiero a varios conciertos.
Udo
2

Para agregar a la respuesta de vjangus, que me ayudó, también me pareció útil agregar el uso de injertos git para atar las ramas al tronco en el punto apropiado, permitiendo que git vea el historial y realice fusiones correctamente.

Esto es simplemente un caso de agregar una línea a .git/info/graftslos hashes:

<initial branch commit> <parent commit in trunk>

p.ej.

378b0ae0902f5c2d2ba230c429a47698810532e5 6c7144991381ce347d4e563e9912465700be0638

Crédito a http://evan-tech.livejournal.com/255341.html

(Agregaría esto como un comentario, pero no tengo suficiente reputación).

Haddon CD.
fuente
0

Si no realiza un pago con un diseño válido, no podrá pagar una sucursal remota.

Esto es lo que hago:

git svn init -s <svn path with no trunk> local_repo
cd local_repo
git svn fetch 
## wait

Después de eso, puede cambiar a una rama remota:

git checkout --track -b branch_name branch_name

Luego, se lo cambiará automáticamente a su sucursal.

MikeHoss
fuente