2010-05-14 20 views
28

Estoy usando git-svn para trabajar con un repositorio SVN. Mis copias de trabajo se han creado usando git svn clone -s http://foo.bar/myproject para que mi copia de trabajo siga el esquema de directorio predeterminado para SVN (troncales, etiquetas, ramas).git-svn: reset tracking para el maestro

Recientemente he estado trabajando en una sucursal que se creó utilizando git-svn branch myremotebranch y se retiró utilizando git checkout --track -b mybranch myremotebranch. Necesitaba trabajar desde múltiples ubicaciones, por lo que desde la rama I git-svn dcommit -ed archivos al repositorio SVN con bastante regularidad.

Después de terminar mis cambios, volví a cambiar al maestro y ejecuté una combinación, comprometí la fusión e intenté realizar la fusión exitosa con el enlace troncal remoto.

Parece como si después de la fusión del seguimiento remoto para el maestro ha cambiado a la rama que estaba trabajando:

# git checkout master 
# git merge mybranch 
... (successful) 
# git add . 
# git commit -m '...' 
# git svn dcommit 
Committing to http://foo.bar/myproject/branches/myremotebranch ... 
# 

¿Hay alguna manera de actualizar el maestro de manera que está siguiendo remotes/trunk como antes de la fusión?

Estoy usando git 1.7.0.5, si eso sirve de algo.

Sería útil si también pudiera explicar por qué esto sucedió, por lo que puedo evitar que el problema vuelva a suceder. ¡Gracias!

Editar:

Aquí está mi actual .git/config:

[core] 
    repositoryformatversion = 0 
    filemode = true 
    bare = false 
    logallrefupdates = true 
    autocrlf = false 
[svn-remote "svn"] 
    url = http://foo.bar/myproject 
    fetch = trunk:refs/remotes/trunk 
    branches = branches/*:refs/remotes/* 
    tags = tags/*:refs/remotes/tags/* 
[branch "mybranch"] 
    remote = . 
    merge = refs/remotes/myremotebranch 

por lo que parece que el tronco está apuntando al lugar correcto. Sin embargo, cambiar a la rama y luego regresar al maestro no ayuda; git svn dcommit en el maestro todavía intenta presionar a myremotebranch.

Respuesta

22

Cuando no hay cambios en el enlace troncal, git realiza una fusión de avance rápido y simplemente establece la rama "principal" local en la confirmación en su bifurcación. Git-svn no sabe cómo realizar fusiones de avance rápido al tronco, de hecho cree que "maestro" ahora apunta a la rama svn.

Para solucionar esto, use git merge --no-ff al fusionar. Esto forzará a git a crear un commit de fusión, que luego se puede enviar a svn.

+1

buen punto en el '--no-ff'. +1 – VonC

+0

Para aclarar, si entiendo, git usa la confirmación de que el puntero "maestro" está activado para decidir a qué rama de SVN comprometerse. Es por eso que el paso de compromiso de SVN falla, ya que después de completar la fusión, y 'mybranch' y 'master' están en la misma confirmación. Ese compromiso se creó originalmente a partir de la rama SVN 'myremotebranch'. – cmcginty

+2

No creo que la creación de un nuevo compromiso de fusión ayude a aclarar las cosas, ya que la información de fusión se perderá cuando se propague al repositorio svn de todos modos. –

5

Si no ha realizado ninguna confirmación en el maestro, es decir, el git merge mybranch fue un avance rápido: master HEAD simplemente cambie al mybranch HEAD.

Eso podría explicar por qué el git svn dcommit llevó sus cambios al SVN mybranch.
Sería:

  • primera actualización de la rama SVN correspondiente a la última Git mybranch aún no comete dcommitted,
  • registro de la fusión de tronco lateral SVN
  • y entonces se rebase principal en el Lado Git (nada que hacer, ya está allí).

No creo principal no ha cambiado su referencia, pero si usted tiene una duda (y su directorio de trabajo es limpio), usted podría (si maestro está desprotegido actualmente):

git reset --hard remotes/trunk 
+0

Parece como restablecer, cambiar algo en el maestro, 'dcommit'ing, luego volver a fusionar para que haya un conflicto, solucionar ese conflicto, luego' dcommit'ing corrige el problema. Aunque no es agradable. –

+0

@digitala: ¿quieres decir que el reinicio solo no es suficiente? El primer compromiso después del reinicio no ocurre en el tronco SVN? – VonC

4

En general, no debe usar git merge con git svn, porque svn, incluso con branches, no admite el tipo de seguimiento de fusión que hace git. Cuando necesita fusionar una sucursal, he tenido el mayor éxito (al menos con svn recientes) haciendo un proceso simple check/merge svn y luego usando git svn rebase para actualizar mis repositorios git-svn. Esto preserva los metadatos nativos de rastreo de fusión de svn, que (AFAIK) git-svn es completamente ignorante.

No estoy totalmente seguro de en qué estado se encuentra su repositorio svn - Verificaría para asegurarse de que el compromiso de combinación hiciera lo que usted quería en el enlace. Incluso si lo hiciera, apuesto a que si miras los contenidos de los archivos refs/heads/master y refs/remotes/trunk en tu repositorio, verás que son diferentes en este momento. Si ese es el caso, yo (sin cambios locales presentes) hago un git-svn fetch seguido de un git branch -f master remotes/trunk; git reset --hard master para resincronizar la rama git con la rama de seguimiento git-svn. Si tiene cambios locales, deberá confirmar y hacer algo como git rebase master^4 --onto remotes/trunk, donde 4 es la cantidad de confirmaciones que debe conservar. Alternativamente, si no están comprometidos, alístelos primero con git stash.

De lo contrario, siempre puede obtener todo en svn y simplemente limpiar el repositorio y obtener un nuevo pago.

+0

Estoy de acuerdo con ese análisis. +1 – VonC

0

he tenido el mismo problema, y ​​se fusionó mandos a distancia/tronco de nuevo en maestro después de lo cual señaló Información Git SVN nuevo en el tronco

No he tenido el tiempo para Actuall dcommit ya que estaba dejando el proyecto y mi git-svn repo murió con mi trabajo. Probé el dcommit --dry-run y dijo que volvería al trunk.

reproduzco la configuración y prueba cuando llegue el momento

aplausos

12

Si git svn rebase después de cambiar de nuevo a dominar y utilizar --squash puede evitar esto.

# git checkout master 
# git svn rebase //(<--the missing step) 
# git merge --squash mybranch // (<-- doesn't commit, more like an svn merge would do) 
... (successful) 
# git add . 
# git commit -m '...' 
# git svn dcommit 
Committing to http://foo.bar/myproject/trunk... 
# 

Para resolver el estado actual (es decir, su principal está apuntando a una rama SVN)

Puede 'switch' a otra rama, eliminar maestro, 'interruptor' volver a ella y luego fusionar de nuevo:

# git checkout mybranch 
# git branch -D master 
# git checkout -b master trunk 
... continue with merge... 
# git merge --squash mybranch 

... ahora tiene MyBranch fusionaron en maestro y listo para commitdcommit y luego a trunk

+1

Muchas gracias por esta explicación, incluido el bit 'para resolver el estado actual'. Estaba en el mismo aprieto, y esto funcionó muy bien para resolverlo. – sockmonk

+2

No creo que 'git checkout -b master trunk' sea correcto. Debería ser 'git checkout -b master remotes/git-svn' – janos

+0

Eso sería cierto si quisiera trabajar en (es decir, fusionar) una rama SVN llamada" git-svn ", pero si está intentando fusionarse con el tronco y su SVN repro es "estándar" (ej. tiene/branches/tags/trunk en el mismo directorio) luego 'git checkout -b master trunk' es definitivamente correcto – dyodji

3

Hemos utilizado con éxito git merge --squash en git-svn feature branch development. El problema con git-svn es que, mientras que el clon git-svn local puede almacenar la información de fusión, una vez que se compromete con el repositorio svn, se pierde.

Así que para otros usuarios (git-) svn las confusiones de fusión se ven como compromisos simples. La calabaza es buena para lo mismo que git merge --no-ff (por ejemplo, producir una combinación de compromiso en el maestro), pero también incluye una lista de las confirmaciones reales realizadas en la rama que se fusiona, que de otro modo se perderían al realizar la transacción.