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:
- Hacer algunas confirmaciones en devel6
-
dcommit
devel6 to SVN ( necesario para obtener los números de revisión de SVN para los confirmaciones) - echa un vistazo a testtunk6 - sí, sé que hice un error tipográfico en el nombre ;-)
-
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 endevel
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.