Solución simple: eliminar la rama 'trabajo' después de fusionar
Respuesta corta: puede usar git como desee (consulte a continuación un flujo de trabajo simple), incluida la fusión. Solo asegúrese de seguir cada ' trabajo de fusión git ' con ' git branch -d work ' para eliminar la rama de trabajo temporal.
Explicación de fondo:
El problema de combinación / dcommit es que siempre que 'git svn dcommit' una rama, el historial de fusión de esa rama se 'aplana': git se olvida de todas las operaciones de fusión que entraron en esta rama: solo se preserva el contenido del archivo, pero se pierde el hecho de que este contenido (parcialmente) proviene de otra rama específica. Ver: ¿Por qué git svn dcommit pierde el historial de confirmaciones de fusión para sucursales locales?
(Nota: no hay mucho que git-svn pueda hacer al respecto: svn simplemente no comprende las combinaciones de git mucho más potentes. Por lo tanto, dentro del repositorio de svn, esta información de combinación no se puede representar de ninguna manera).
Pero este es todo el problema. Si elimina la rama 'trabajo' después de que se haya fusionado con la 'rama maestra', entonces su repositorio git está 100% limpio y se ve exactamente como su repositorio svn.
Mi flujo de trabajo:
Por supuesto, primero cloné el repositorio svn remoto en un repositorio git local (esto puede llevar algo de tiempo):
$> git svn clone <svn-repository-url> <local-directory>
Todo el trabajo se realiza dentro del "directorio local". Cada vez que necesito obtener actualizaciones del servidor (como 'svn update'), hago:
$> git checkout master
$> git svn rebase
Hago todo mi trabajo de desarrollo en una rama separada 'trabajo' que se crea así:
$> git checkout -b work
Por supuesto, puede crear tantas ramas para su trabajo como desee y fusionarlas y volver a crearlas como desee (simplemente elimínelas cuando haya terminado con ellas, como se explica a continuación). En mi trabajo normal, me comprometo con mucha frecuencia:
$> git commit -am '-- finished a little piece of work'
El siguiente paso (git rebase -i) es opcional --- es solo limpiar el historial antes de archivarlo en svn: una vez que alcancé una piedra estable que quiero compartir con los demás, reescribo el historial de este 'trabajo' bifurca y limpia los mensajes de confirmación (otros desarrolladores no necesitan ver todos los pequeños pasos y errores que cometí en el camino, solo el resultado). Para esto, lo hago
$> git log
y copie el hash sha-1 del último commit que esté activo en el repositorio svn (como lo indica un git-svn-id). Entonces llamo
$> git rebase -i 74e4068360e34b2ccf0c5869703af458cde0cdcb
Solo pegue sha-1 hash de nuestro último svn commit en lugar del mío. Es posible que desee leer la documentación con 'git help rebase' para obtener detalles. En resumen: este comando primero abre un editor que presenta sus confirmaciones ---- solo cambie 'elegir' a 'aplastar' para todas las confirmaciones que desea eliminar con las confirmaciones anteriores. Por supuesto, la primera línea debe permanecer como una "elección". De esta manera, puede condensar sus muchos pequeños compromisos en una o más unidades significativas. Guarde y salga del editor. Obtendrá otro editor que le pedirá que reescriba los mensajes de registro de confirmación.
En resumen: después de terminar el 'pirateo de códigos', masajeo mi rama 'trabajo' hasta que se vea cómo quiero presentarlo a los otros programadores (o cómo quiero ver el trabajo dentro de unas semanas cuando navego por el historial) .
Para enviar los cambios al repositorio svn, hago:
$> git checkout master
$> git svn rebase
Ahora estamos de vuelta en la antigua rama 'maestra' actualizada con todos los cambios que ocurrieron mientras tanto en el repositorio svn (sus nuevos cambios están ocultos en la rama 'trabajo').
Si hay cambios que pueden chocar con sus nuevos cambios de 'trabajo', debe resolverlos localmente antes de que pueda impulsar su nuevo trabajo (vea los detalles más abajo). Entonces, podemos empujar nuestros cambios a svn:
$> git checkout master
$> git merge work # (1) merge your 'work' into 'master'
$> git branch -d work # (2) remove the work branch immediately after merging
$> git svn dcommit # (3) push your changes to the svn repository
Nota 1: El comando 'git branch -d work' es bastante seguro: solo le permite eliminar ramas que ya no necesita (porque ya están fusionadas en su rama actual). Si ejecuta este comando por error antes de fusionar su trabajo con la rama 'maestra', recibirá un mensaje de error.
Nota 2: asegúrese de eliminar su rama con 'git branch -d work' entre la fusión y dcommit: si intenta eliminar la rama después de dcommit, recibirá un mensaje de error: cuando hace 'git svn dcommit', git olvida que su sucursal se ha fusionado con 'maestro'. Debe eliminarlo con 'git branch -D work' que no realiza la verificación de seguridad.
Ahora, inmediatamente creo una nueva rama 'de trabajo' para evitar piratear accidentalmente la rama 'maestra':
$> git checkout -b work
$> git branch # show my branches:
master
* work
Integrando su 'trabajo' con cambios en svn:
Esto es lo que hago cuando 'git svn rebase' revela que otros cambiaron el repositorio de svn mientras estaba trabajando en mi rama 'trabajo':
$> git checkout master
$> git svn rebase # 'svn pull' changes
$> git checkout work # go to my work
$> git checkout -b integration # make a copy of the branch
$> git merge master # integrate my changes with theirs
$> ... check/fix/debug ...
$> ... rewrite history with rebase -i if needed
$> git checkout master # try again to push my changes
$> git svn rebase # hopefully no further changes to merge
$> git merge integration # (1) merge your work with theirs
$> git branch -d work # (2) remove branches that are merged
$> git branch -d integration # (2) remove branches that are merged
$> git svn dcommit # (3) push your changes to the svn repository
Existen soluciones más potentes:
el flujo de trabajo presentado es simplista: utiliza los poderes de git solo dentro de cada ronda de 'actualizar / piratear / dcommitir', pero deja el historial del proyecto a largo plazo tan lineal como el repositorio svn. Esto está bien si solo desea comenzar a usar git merges en pequeños primeros pasos en un proyecto svn heredado.
Cuando se familiarice con git merging, siéntase libre de explorar otros flujos de trabajo: si sabe lo que está haciendo, puede mezclar git merges con svn merges (¿ Usando git-svn (o similar) solo para ayudar con svn merge? )