with tortoise together branches and git git-svn

tortoise - Git-svn fusiona dos ramas SVN



svn and git together (2)

Examinando un poco más en el asunto, descubrí que git admite la configuración de la propiedad svn:mergeinfo en la rama SVN cuando dcommit ''ing:

git svn dcommit --mergeinfo "/branches/somebranch:1-3"

¡NÓTESE BIEN! svn:mergeinfo se sobrescribe con lo que se indica en la línea de comandos, así que tenga cuidado de enumerar las combinaciones anteriores también .

Mientras que la versión más reciente de git agregó el parámetro de configuración para establecer automáticamente esta propiedad:

config key: svn.pushmergeinfo

Tuve algunos problemas con el mergeinfo automático, por una razón u otra, GIT lo calculó mal y no pude hacerlo funcionar.

SOLUCIÓN: git-merge-svn

Para automatizar el proceso, escribí un script de shell git-merge-svn que se puede usar para fusionar dos ramas SVN con el conjunto svn:mergeinfo correcto en el dcommit.

El script maneja ambas situaciones:

  • la rama no está fusionada en git - hará git merge antemano
  • las ramas ya se han fusionado en git (pero no en SVN); se desplazarán hasta el antepasado anterior para las revisiones de confirmación combinadas.

Con este script, pude producir estas combinaciones únicamente en el lado de git y retener la información de combinación para que el gráfico GIT muestre el registro muy bien:

Ejemplo de uso:

  1. Hacer algunas confirmaciones en devel6
  2. dcommit devel6 to SVN ( necesario para obtener los números de revisión de SVN para los confirmaciones)
  3. echa un vistazo a testtunk6 - sí, sé que hice un error tipográfico en el nombre ;-)
  4. git merge-svn devel6

Las últimas salidas de commant:

% git merge-svn devel6 About to do an SVN merge: devel6 -> testtunk6 * NEW MERGE COMMIT |/ | * devel6 [7b71187] (r102) * | testtunk6 [0682a45] (r101) /| * [273d6d6] (r100) STEP 1: GIT merge Executing: git merge devel6 Continue? (y/n) [n]: y Merge made by the ''recursive'' strategy. testfile | 1 + 1 file changed, 1 insertion(+) STEP 2: SVN dcommit executing: git svn dcommit --mergeinfo /idp/branches/devel:9-32,35-41 /idp/branches/devel6:89 /idp/branches/devel6:94 /idp/branches/devel6:93 /idp/branches/devel6:96 /idp/branches/devel6:97 /idp/branches/devel6:99 /idp/branches/devel6:100 /idp/branches/devel6:102 Continue? (y/n) [n]: y Committing to https://my.svn.host/svn/auth/idp/branches/testtunk6 ... M testfile Committed r103 M testfile Found merge parent (svn:mergeinfo prop): 7b71187fc371d3f86658c5850009e63be88157ac r103 = 87759323cbadd38bac78087d57b6870a926287e7 (refs/remotes/svn/testtunk6) No changes between 3fb2168cfbbe605fbd810d76513443203a85a549 and refs/remotes/svn/testtunk6 Resetting to the latest refs/remotes/svn/testtunk6

He leído numerosas preguntas de SO y blogs en git-svn y fusionándolos. Algunos de ellos (en particular, la página de manual de git-svn ) advierten contra el uso de la combinación en cualquier lugar cerca de la rama de la que planeo dcommit .

Otros, como esta respuesta SO , afirman que la fusión está bien siempre y cuando use las ramas de características dcommitting antes de dcommitting .

Tengo una configuración con dos ramas SVN (y git) de larga duración:

  • trunk (git-svn: svn/trunk , git: master ) - la rama estable
  • sucursales / devel (git-svn: svn/devel , git: devel ) - la rama principal de desarrollo desde la cual desentrañé las ramas de características (y puedo vivir con rebasarlas de nuevo en devel en lugar de fusionarlas).

En la imagen de arriba, (1) muestra el historial pasado de SVN, donde las branches/devel se han fusionado en un trunk .

(2) muestra que he dcommitted éxito mi desarrollo actual nuevamente a SVN.

La pregunta: ¿puedo usar git-svn para combinar dos ramas SVN de modo que la historia muestre el punto de fusión (como puede hacer SVN)? En otras palabras: ¿qué sucede si dcommit que dcommit del master como se muestra en (3) ?

¿Esto arruinará mi historial de SVN (o git)? ¿O esto simplemente olvidará que devel se fusionó con el master ?

EDITAR: Si git simplemente olvida que el devel se fusionó con el master , ¿hay una diferencia entre dcommiting desde el punto (3) y aplicar todas las confirmaciones como un solo parche ?


Git y Svn tienen diferentes estructuras de datos para mantener un historial.

Svn utiliza un árbol simple. Es decir, cada confirmación tiene solo un padre, pero una confirmación podría tener varios hijos (ramas). Por lo tanto, Svn no es compatible con las fusiones. Lo que ellos llaman "fusionar" es en realidad un conjunto de cambios, la analogía más cercana en git es la rebase o tal vez cherry-pick . Desde la versión 1.5, Svn admite una propiedad de metainfo svn:mergeinfo que ayuda a rastrear lo que se "fusionó", sin embargo, parece ser una solución alternativa que explica por qué las sucursales en Svn son tan difíciles de usar. El punto de fusión es una confirmación que aplasta todos los conjuntos de cambios combinados y la resolución de conflictos en un conjunto de cambios, probablemente anotado con la propiedad svn:mergeinfo .

Git utiliza un gráfico acíclico dirigido, que es una forma muy natural de describir la fusión y ramificación de la historia. Un punto de fusión es solo otro compromiso con dos (o más) padres. Por lo tanto, su (3) en la imagen es una confirmación de fusión. Por lo tanto, toda la historia parece natural, tiene todas las confirmaciones accesibles en un gráfico de historia desde el punto actual.

El puente Git-Svn intenta hacer lo mejor para manejar el inconveniente del diseño de Svn, antes de hacer dcommit , generalmente rebasa todos los compromisos combinados en la parte superior de la rama actual de Svn. Hace unos 2 años, git-svn no pudo suministrar svn:mergeinfo , por lo que lo que está pidiendo es imposible. Por otra parte, cuando está dcommit , git crea un "doble" commit "difícilmente" vinculado a un svn commit, por lo que vuelve a escribir el commit original.