Ver índice de contenidos del libro

8.1. Git y Subversion

Hasta hace poco tiempo, la mayoría de los proyectos en desarrollo de código abierto y un gran número de proyectos corporativos usaban Subversion para manejar su código fuente. Además de que era el VCS más popular, ha existido desde hace casi una década. También es muy similar en muchos aspectos a CVS, que antes fue el sistema de control de fuentes más utilizado.

Una de las grandes características de Git es el puente bidireccional llamado git svn. Esta herramienta permite el uso de Git como un cliente válido para un servidor Subversion, así que puedes utilizar todas las características locales de Git y luego hacer un "push" al servidor de Subversion como si estuvieras usando Subversion localmente. Esto significa que puedes hacer "branching" y "merging" localmente, usar el área de "staging", usar "rebasing" y "cherry-picking", y todo esto, mientras tus colaboradores continuan trabajando a la antigua usanza. Es una buena forma de migrar a Git dentro de un ambiente corporativo y ayudar a tus buenos desarrolladores a hacerse más eficientes mientras tu haces presión para que puedan cambiar la infraestructura y así soportar Git completamente. El puente de Subversion es la puerta de enlace hacia el mundo de DVCS.

8.1.1. git svn

El comando básico de Git para todas las operaciones relacionadas con Subversion es git svn. Escribe ese comando como prefijo de todas las demás operaciones. En realidad son pocos comandos, así que vamos a aprender los más comunes mientras presentamos varios flujos de trabajo sencillos.

Resulta importante destacar que cuando utilizas git svn, estás interactuando con Subversion, que es un sistema mucho menos sofisticado que Git. Aunque puedes hacer fácilmente ramas y fusiones en local, es mejor que el historial de tu código sea lo más lineal posible reorganizando (rebase) tu código y evitando interactuar simultáneamente con un repositorio git remoto.

No reescribas la historia de tu proyecto y trates de enviar (push) los cambios. Tampoco envíes (push) cambios a un repositorio Git para colaborar a la vez con otros programadores que utilicen Git. Subversion solo puede manejar un historial de código lineal y es fácil estropearlo. Si trabajas en equipo y algunos utilizan Subversion y otros Git, asegúrate de que todos utilizan el servidor SVN para colaborar; esto hará que tu trabajo sea mucho más sencillo.

8.1.2. Preparación

Para probar el comando git svn, necesitas un repositorio SVN típico para el que tengas acceso de escritura. Si quieres seguir los mismos ejemplos de este libro, haz una copia de mi repositorio test-svn. Para que sea más sencillo, puedes emplear una herramienta llamada svnsync que incluyen las versiones más recientes de Subversion — se incluye al menos desde la versión 1.4. Para estas pruebas, he creado un repositorio Subversion en el sitio Google Code y que es una copia parcial del proyecto protobuf, que a su vez es una herramienta que codifica información para transmitirla a través de redes de comunicaciones.

En primer lugar, crea un nuevo repositorio Subversion local:

$ mkdir /tmp/test-svn
$ svnadmin create /tmp/test-svn

Después, permite que todos los usuarios puedan cambiar revprops. Lo más fácil es que crees un archivo llamado revprop-change que siempre devuelva 0:

$ cat /tmp/test-svn/hooks/pre-revprop-change 
#!/bin/sh
exit 0;
$ chmod +x /tmp/test-svn/hooks/pre-revprop-change

Ahora ya puedes sincronizar este proyecto en tu máquina local ejecutando el comando svnsync init e indicando los dos repositorios (a dónde y desde dónde):

$ svnsync init file:///tmp/test-svn http://progit-example.googlecode.com/svn/ 

El comando anterior prepara las propiedades necesarias para la sincronización. Después, clona el código ejecutando el siguiente comando:

$ svnsync sync file:///tmp/test-svn
Committed revision 1.
Copied properties for revision 1.
Committed revision 2.
Copied properties for revision 2.
Committed revision 3.
...

Completar esta operación cuesta solo unos minutos, pero si tratas de copiar el repositorio original a otro repositorio remoto en vez de a uno local, el proceso entero puede llevar casi una hora, aunque hay menos de 100 commits. Subversion clona una revisión cada vez y después envía los cambios a otro repositorio — es tan ineficiente que resulta ridículo, pero es la única forma sencilla de hacerlo.

8.1.3. Comenzando

Ahora que ya tienes un repositorio Subversion con permiso de escritura, puedes seguir el flujo de trabajo habitual. Comienza ejecutando el comando git svn clone, que importa un repositorio Subversion completo en un repositorio Git local. Recuerda que si estás importando desde un repositorio Subversion alojado remotamente, debes reemplaazar file:///tmp/test-svn por la URL de ese repositorio remoto:

$ git svn clone file:///tmp/test-svn -T trunk -b branches -t tags
Initialized empty Git repository in /Users/schacon/projects/testsvnsync/svn/.git/
r1 = b4e387bc68740b5af56c2a5faf4003ae42bd135c (trunk)
      A    m4/acx_pthread.m4
      A    m4/stl_hash.m4
...
r75 = d1957f3b307922124eec6314e15bcda59e3d9610 (trunk)
Found possible branch point: file:///tmp/test-svn/trunk => \
    file:///tmp/test-svn /branches/my-calc-branch, 75
Found branch parent: (my-calc-branch) d1957f3b307922124eec6314e15bcda59e3d9610
Following parent with do_switch
Successfully followed parent
r76 = 8624824ecc0badd73f40ea2f01fce51894189b01 (my-calc-branch)
Checked out HEAD:
 file:///tmp/test-svn/branches/my-calc-branch r76

Lo anterior es equivalente a ejecutar el comando git svn init seguido de git svn fetch sobre la URL indicada. Este proceso puede tardar un tiempo. Como el proyecto de prueba solo tiene 75 commits y el código entero no es muy grande, solo tarda unos minutos. No obstante, Git tiene que descargar (checkout) cada versión una por una y confirmarlas (commit) individualmente. Si el proyecto tiene cientos o miles de confirmaciones (commits) este proceso puede tardar desde horas hasta días enteros.

Las opciones -T trunk -b branches -t tags indican a Git que este repositorio Subversion sigue las convenciones comunes para las ramas y las etiquetas. Si utilizas nombres diferentes para el trunk, las ramas (branches) o las etiquetas (tags), indícalo con estas opciones. Como es tan común usar las convenciones anteriores, exsite un atajo llamado -s que indica que el repositorio sigue la convención estándar. Así que el siguiente comando es equivalente al anterior:

$ git svn clone file:///tmp/test-svn -s

Después de ejecutar el comando anterior, ya deberías tener un repositorio Git válido con todas las ramas y etiquetas importadas:

$ git branch -a
* master
  my-calc-branch
  tags/2.0.2
  tags/release-2.0.1
  tags/release-2.0.2
  tags/release-2.0.2rc1
  trunk

Fíjate como esta herramienta prefija las referencias externas de forma diferente. Cuando clonas un repositorio Git normal, todas las ramas remotas están disponibles localmente con el nombre origin/[nombre-rama] y prefijadas con el nombre de la referencia remota. No obstante, el comando git svn supone que no vas a utilizar varias referencias remotas y por eso no prefija nada al nombre de las ramas. Si utilizas el comando de bajo nivel show-ref, puedes ver el nombre completo de todas las referencias:

$ git show-ref
1cbd4904d9982f386d87f88fce1c24ad7c0f0471 refs/heads/master
aee1ecc26318164f355a883f5d99cff0c852d3c4 refs/remotes/my-calc-branch
03d09b0e2aad427e34a6d50ff147128e76c0e0f5 refs/remotes/tags/2.0.2
50d02cc0adc9da4319eeba0900430ba219b9c376 refs/remotes/tags/release-2.0.1
4caaa711a50c77879a91b8b90380060f672745cb refs/remotes/tags/release-2.0.2
1c4cb508144c513ff1214c3488abe66dcb92916f refs/remotes/tags/release-2.0.2rc1
1cbd4904d9982f386d87f88fce1c24ad7c0f0471 refs/remotes/trunk

Un repositorio Git normal tiene la siguiente pinta:

$ git show-ref
83e38c7a0af325a9722f2fdc56b10188806d83a1 refs/heads/master
3e15e38c198baac84223acfc6224bb8b99ff2281 refs/remotes/gitserver/master
0a30dd3b0c795b80212ae723640d4e5d48cabdff refs/remotes/origin/master
25812380387fdd55f916652be4881c6f11600d6f refs/remotes/origin/testing

En el ejemplo anterior, dispones de dos servidores remotos: uno se llama gitserver y tiene una rama master; el otro se llama origin y tiene dos ramas: master y testing.

Observa como en el ejemplo de las referencias importadas con el comando git svn, las etiquetas se añaden como ramas remotas, no como etiquetas de Git. La importación de Subversion parece que tuviera una referencia remota llamada tags y las etiquetas fueran ramas suyas.

8.1.4. Confirmando cambios al repositorio Subversion

Ahora que ya tienes un repositorio funcional, puedes trabajar sobre el proyecto para después confirmar (commit) los cambios al repositorio, utilizando Git como si fuera un cliente de Subversion. Si modificas un archivo y lo confirmas (commit), tienes una confirmación (commit) local en Git que no existe todavía en el servidor de Subversion:

$ git commit -am 'Adding git-svn instructions to the README'
[master 97031e5] Adding git-svn instructions to the README
 1 files changed, 1 insertions(+), 1 deletions(-)

Ahora debes enviar el cambio al repositorio. Observa cómo esto cambia la forma en la que trabajas con Subversion: puedes hacer varias confirmaciones (commit) por una parte y después enviarlas (push) todas a la vez al servidor de Subversion. Para enviar los cambios, ejecuta el comando git svn dcommit:

$ git svn dcommit
Committing to file:///tmp/test-svn/trunk ...
       M      README.txt
Committed r79
       M      README.txt
r79 = 938b1a547c2cc92033b74d32030e86468294a5c8 (trunk)
No changes between current HEAD and refs/remotes/trunk
Resetting to the latest refs/remotes/trunk

Este comando obtiene todas las confirmaciones (commits) que has realizado en el código, realiza un commit de Subversion para cada una y después reescribe tu commit local de Git para añadirle un identificador único. Esto es importante porque significa que cambian las sumas de compronación SHA-1 de tus commits. Esta es una de las razones por las que no se recomienda trabajar a la vez en un repositorio Git y en otro de tipo Subversion. Si observas el último commit, puedes ver el nuevo valor git-svn-id que se ha añadido:

$ git log -1
commit 938b1a547c2cc92033b74d32030e86468294a5c8
Author: schacon <[email protected]>
Date:   Sat May 2 22:06:44 2009 +0000
    Adding git-svn instructions to the README
    git-svn-id: file:///tmp/test-svn/[email protected] 4c93b258-373f-11de-be05-5f7a86268029

La suma de comprobación SHA que antes empezaba por 97031e5 ahora comienza por 938b1a5. Si quieres enviar cambios tanto a un repositorio Git como a uno de tipo Subversion, debes enviar los cambios (dcommit) primero al repositorio Subversion, porque eso hace que cambien los datos de tu commit.

8.1.5. Descargando los cambios

Cuando trabajas con otros programadores en el mismo proyecto, en algún momento alguien enviará un cambio y después otra persona tratará de enviar un cambio diferente pero no podrá porque se producirán conflictos. Los cambios no se podrán subir hasta que se resuelvan los conflictos. Utilizando git svn los conflictos tienen la siguiente pinta:

$ git svn dcommit
Committing to file:///tmp/test-svn/trunk ...
Merge conflict during commit: Your file or directory 'README.txt' is probably \
out-of-date: resource out of date; try updating at /Users/schacon/libexec/git-\
core/git-svn line 482

Para resolver este problema, ejecuta el comando git svn rebase, que descarga todos los cambios del servidor que todavía no has aplicado y reorganiza (rebase) el código propio que has modificado localmente:

$ git svn rebase
       M      README.txt
r80 = ff829ab914e8775c7c025d741beb3d523ee30bc4 (trunk)
First, rewinding head to replay your work on top of it...
Applying: first user change

Ahora tus cambios están por delante de los últimos cambios del servidor Subversion, por lo que ya puedes enviarlos con el comando dcommit:

$ git svn dcommit
Committing to file:///tmp/test-svn/trunk ...
       M      README.txt
Committed r81
       M      README.txt
r81 = 456cbe6337abe49154db70106d1836bc1332deed (trunk)
No changes between current HEAD and refs/remotes/trunk
Resetting to the latest refs/remotes/trunk

Recuerda que Git que obliga a fusionar todos los cambios remotos que no hayas aplicado localmente antes de poder subir (push) tus cambios. Sin embargo, git svn solo te obliga a hacerlo si los cambios generan conflictos. Si alguien cambia un archivo y después tu subes cambios a otro archivo diferente, el comando dcommit funcionará sin ningún problema:

$ git svn dcommit
Committing to file:///tmp/test-svn/trunk ...
       M      configure.ac
Committed r84
       M      autogen.sh
r83 = 8aa54a74d452f82eee10076ab2584c1fc424853b (trunk)
       M      configure.ac
r84 = cdbac939211ccb18aa744e581e46563af5d962d0 (trunk)
W: d2f23b80f67aaaa1f6f5aaef48fce3263ac71a92 and refs/remotes/trunk differ, \
  using rebase:
:100755 100755 efa5a59965fbbb5b2b0a12890f1b351bb5493c18 \
  015e4c98c482f0fa71e4d5434338014530b37fa6 M   autogen.sh
First, rewinding head to replay your work on top of it...
Nothing to do.

Resulta importante que siempre tengas presente este comportamiento, ya que el resultado es que el proyecto se encuentra en un estado que no existe en ninguno de los dos ordenadores locales que han subido los cambios. Si los cambios son incompatibles pero no generan ningún conflicto, puedes encontrarte con errores que son muy difíciles de detectar. Git se comporta de forma muy diferente. En Git puedes comprobar localmente el estado completo del proyecto antes de subir los cambios, mientras que en Subversion nunca puedes estar seguro de que el estado anterior y posterior al cambio sea idéntico.

Utiliza también este comando para obtener (pull) los cambios del repositorio Subversion incluso aunque tu no hayas hecho cambios locales. Ejecuta git svn fetch para obtener los cambios y git svn rebase para obtener los cambios y después actualizar tus commits locales.

$ git svn rebase
       M      generate_descriptor_proto.sh
r82 = bd16df9173e424c6f52c337ab6efa7f7643282f1 (trunk)
First, rewinding head to replay your work on top of it...
Fast-forwarded master to refs/remotes/trunk.

Ejecutar el comando git svn rebase de vez en cuando te asegura que tu código siempre está actualizado. Asegúrate de que tu directorio de trabajo está limpio antes de ejecutar el comando. Si tienes cambios locales, guarda temporalmente (stash) esos cambios o confírmalos (commit) antes de ejecutar git svn rebase. Si no, el comando no se ejecuta porque detecta que la reorganización del código (rebase) va a provocar algún conflicto.

8.1.6. Problemas con las ramas de Git

Las personas acostumbradas a trabajar con Git suelen crear ramas para solucionar errores o añadir funcionalidades. Después de trabajar en ellas, las fusionan con la rama de integración (dev, master, etc.) Si subes los cambios a un repositorio Subversion con el comando git svn, seguramente querrás reorganizar (rebase) el código en una única rama en vez de fusionar varias ramas. El principal motivo es que Subersion tiene un historial de código lineal y no trata las fusiones (merges) de la misma manera que Git, así que git svn solo continúa hasta el primer padre cuando realiza la conversión de los cambios a commits de Subversion.

Imagina que el historial de tu código es el siguiente: has creado una rama llamada experiment, has realizado dos commits y después la has fusionado con la rama master. Al ejecutar el comando dcommit, obtienes el siguiente resultado:

$ git svn dcommit
Committing to file:///tmp/test-svn/trunk ...
       M      CHANGES.txt
Committed r85
       M      CHANGES.txt
r85 = 4bfebeec434d156c36f2bcd18f4e3d97dc3269a2 (trunk)
No changes between current HEAD and refs/remotes/trunk
Resetting to the latest refs/remotes/trunk
COPYING.txt: locally modified
INSTALL.txt: locally modified
       M      COPYING.txt
       M      INSTALL.txt
Committed r86
       M      INSTALL.txt
       M      COPYING.txt
r86 = 2647f6b86ccfcaad4ec58c520e369ec81f7c283c (trunk)
No changes between current HEAD and refs/remotes/trunk
Resetting to the latest refs/remotes/trunk

Ejecutar el comando dcommit en una rama con los cambios ya fusionado funciona bien. El problema es que si ves el historial de tu proyecto Git, no ha reescrito ninguno de los commits que has realizado en la rama experiment. En su lugar, todos los cambios aparecen en el commit utilizado para fusionar los cambios en el repositorio de Subversion.

Si otra persona clona ese trabajo, todo lo que verá será un único commit que contiene todos los cambios, así que no verá ni la información sobre los commits ni cuándo se realizaron.

8.1.7. Creando ramas en Subversion

Crear ramas en Subversion es muy diferente a hacerlo en Git. Si puedes evitarlas, es mejor que lo hagas. En cualquier caso, puedes crear ramas en Subversion con el comando git svn.

8.1.7.1. Creando una nueva rama en Subversion

Para crear una nueva rama en Subversion, ejecuta git svn branch [nombre-rama]:

$ git svn branch opera
Copying file:///tmp/test-svn/trunk at r87 to file:///tmp/test-svn/branches/opera...
Found possible branch point: file:///tmp/test-svn/trunk => \
  file:///tmp/test-svn/branches/opera, 87
Found branch parent: (opera) 1f6bfe471083cbca06ac8d4176f7ad4de0d62e5f
Following parent with do_switch
Successfully followed parent
r89 = 9b6fe0b90c5c9adf9165f700897518dbc54a7cbf (opera)

Este comando es equivalente a ejecutar svn copy trunk branches/opera sobre el repositorio de Subversion. Cuidado porque este comando no te cambia de rama después de crearla, por lo que si haces algún cambio, se realizará sobre la rama trunk, no sobre la rama opera.

8.1.8. Cambiando la rama activa

Git detecta a qué rama envía los cambios dcommits observando el último cambio de todas las ramas de Subversion en tu historial. Así que debería haber solo una y debería ser la última con un valor git-svn-id en tu historial de ramas.

Si quieres trabajar en más de una rama a la vez, puedes hacer que las ramas locales envíen los cambios con dcommit a alguna rama específica de Subversion. Para ello, debes crearlas en el commit que se utilizó para importar la rama de Subversion. Si quieres crear una rama opera para trabajar independientemente, ejecuta lo siguiente:

$ git branch opera remotes/opera

Si ahora quieres fusionar la rama opera dentro de trunk (que en realidad corresponde a la rama master), puedes hacerlo con un comando git merge normal. No olvides añadir algún comentario descriptivo (con la opción -m), ya que si no, la fusión incluirá el siguiente mensaje automático "Merge branch opera".

Ten en cuenta que, aunque estás utilizando git merge para hacer esta operación, y la fusión (merge) será mucho más sencilla de lo que sería en Subversion (porque Git detecta automáticamente la base a partir de la cual hay que fusionar) esto no un commit normal de Git para fusionar cambios. Pero como estás enviando los cambios a un servidor Subversion que no es capaz de manejar los commits que están relacionados con más de un padre, los cambios se mostrarán como un único commit con todas las modificaciones enviadas.

Después de fusionar una rama dentro de otra, no es fáicl volver atrás y continuar trabajando en esa rama, tal y como haces normalmente en Git. El comando dcommit ejecutado borra toda la información sobre la fusión de la rama, por lo que los cálculos realizados para las futuras fusiones serán incorrectos. En otras palabras, el comando dcommit hace que el comando git merge parezca en realidad el comando git merge --squash.

Lamentablemente no es sencillo solucionar este problema, ya que Subversion no puede almacenar esta información y siempre estarás limitado mientras utilices Subversion. Para evitar más problemas, borra la rama local (en este caso, la rama opera) después de fusionarla en la rama trunk.

8.1.9. Comandos de Subversion

La utilidad git svn proporciona varios comandos para facilitar la transición a Git mediante el uso de funcionalidades similares a las que dispones en Subversion. Estos son algunos de los comandos que te ofrecen lo mismo que tenías en Subversion.

8.1.9.1. Historial con el estilo de Subversion

Si estás acostumbrado a Subversion y quieres ver el historial de tu código con ese mismo estilo, ejecuta git svn log:

##
$ git svn logr87 | schacon | 2009-05-02 16:07:37 -0700 (Sat, 02 May 2009) | 2 lines
autogen change
------------------------------------------------------------------------
r86 | schacon | 2009-05-02 16:00:21 -0700 (Sat, 02 May 2009) | 2 lines
Merge branch 'experiment'
------------------------------------------------------------------------
r85 | schacon | 2009-05-02 16:00:09 -0700 (Sat, 02 May 2009) | 2 lines
 
updated the changelog

Debes tener en cuenta dos cosas importantes relacionadas con git svn log. En primer lugar, funciona sin conectarse al servidor, al contrario del comando svn log que obtiene su información del repositorio Subversion. En segudo lugar, solo muestra los cambios (commits) que se han subido al servidor. Los cambios locales que no has enviado con dcommit no se muestran y tampoco lo hacen los cambios subidos por otras personas al repositorio desde la última vez que te trajiste los cambios remotos. Más que un historial en realidad muestra el último estado conocido de los commits del servidor Subversion.

8.1.9.2. Anotaciones de Subversion

Al igual que el comando git svn log simula el comportamiento del comando svn log, existe un equivalente del comando svn annotate llamado git svn blame [FILE]. Su aspecto es el siguiente:

$ git svn blame README.txt 
 2   temporal Protocol Buffers - Google's data interchange format
 2   temporal Copyright 2008 Google Inc.
 2   temporal http://code.google.com/apis/protocolbuffers/
 2   temporal 
22   temporal C++ Installation - Unix
22   temporal =======================
 2   temporal 
79    schacon Committing in git-svn.
78    schacon 
 2   temporal To build and install the C++ Protocol Buffer runtime and the Protocol
 2   temporal Buffer compiler (protoc) execute the following:
 2   temporal 

De nuevo este comando no muestra los cambios locales no subidos o los cambios remotos que no te has descargado.

8.1.9.3. Información del servidor de Subversion

Para obtener la misma información que proporciona svn info, ejecuta el comando git svn info:

$ git svn info
Path: .
URL: https://schacon-test.googlecode.com/svn/trunk
Repository Root: https://schacon-test.googlecode.com/svn
Repository UUID: 4c93b258-373f-11de-be05-5f7a86268029
Revision: 87
Node Kind: directory
Schedule: normal
Last Changed Author: schacon
Last Changed Rev: 87
Last Changed Date: 2009-05-02 16:07:37 -0700 (Sat, 02 May 2009)

Al igual que blame y log, este comando no se conecta al servidor y por tanto solo muestra la información de la última vez que te comunicaste con el servidor Subversion.

8.1.9.4. Ignorando lo que Subversion ignora

Al clonar un repositorio Subversion que utiliza la propiedad svn:ignore, seguramente querrás que el archivo .gitignore contenga los mismos archivos para no subir accidentalmente al repositorio un archivo que no debería subirse. La utilidad git svn tiene dos comandos para ayudarte a conseguirlo. El primero es git svn create-ignore, que crea automáticamente todos los archivos .gitignore correspondientes para que puedas subirlos en el próximo commit.

El segundo comando es git svn show-ignore, que muestra en la consola las líneas que deberías añadir a tu archivo .gitignore. Si quieres, puedes redirigir la salida de este comando directamente al archivo de exclusiones de tu proyecto:

$ git svn show-ignore > .git/info/exclude

De esta forma no creas archivos varios archivos .gitignore en los diferentes directorios del proyecto. Esta es una buena práctica recomendada cuando eres el único usuario de Git dentro de un equipo de trabajo Subversion y tus compañeros de trabajo no quieren encontrarse con multitud de archivos .gitignore.

8.1.10. Resumen de Git-Subversion

La herramienta git svn es muy útil si te ves obligado a utilizar un servidor Subversion o si el proyecto en el que estás trabajando todavía depende de un servidor Subversion. Piensa siempre que Subversion es una especie de Git limitado, ya que si no, te encontrarás con problemas durante esa transición y esto podría afectar a tus compañeros. Para evitar problemas, sigue estas recomendaciones:

  • Mantén un historial de Git lineal que no contenga fusiones realizadas con el comando git merge. Reorganiza (rebase) cualquier código que realices en ramas diferentes a la principal, no hagas fusiones.
  • No utilices un servidor Git a la vez. Quizás quieras tener uno para que sea más rápido clonar el repositorio para los nuevos programadores que se incorporen al proyecto, pero no subas cambios a ese repositorio que no tengan un valor git-svn-id. Puede ser útil configurar un enganche (hook) pre-receive que compruebe para cada commit si contiene un valor git-svn-id y rechace automáticamente todos los cambios que no lo tengan.

Siguiendo estas recomendaciones, puede resultar hasta soportable trabajar ocn un repositorio Subversion. En cualquier caso, si es posible migrar a un repositorio Git de verdad, hazlo y mejorarás el trabajo de todo el equipo.