Accueil > Blog-notes > Migrer un projet SVN vers GIT

Migrer un projet SVN vers GIT

Depuis que j’ai compris que Git c’est facile, je suis de plus en plus enclin à l’utiliser couramment.

De plus, j’apprécie vraiment le service et les facilités proposés par GitHub comme son interface de consultation, la gestion des issues, le zip automatique des tags.

Mais j’ai aussi un historique de développement sous SVN, avec plein de petits projets développés et versionnés sur mon serveur SVN accouplé à une interface TRAC.

C’est donc au cas par cas que je migre chacun de ces petits projets sous Git, ce qui me permet tout à la fois de passer à Git, d’améliorer grandement mon confort de consultation par l’interface web, et de faciliter les contributions externes.

Nous allons voir deux cas pratiques de migration, en commençant par un projet simple sans branche, puis en essayant d’importer un projet avec ses branches et ses tags.

Un cas simple

Pour l’exemple, on va ici créer un projet GitHub pour le plugin SPIP Crayons, actuellement versionné sur [l’espace SVN partagé de la communauté SPIP appelé SPIP-Zone, dans le dossier _plugins_/crayons

1. Importer de SVN vers Git

On va utiliser pour importer la fonction git svn.

La syntaxe est simple. Pour importer le Repository SVN svn://zone.spip.org/spip-zone vers un repertoire local gitzone versionné sous Git, on utiliserait la syntaxe

Ici, on ne veut pas importer tout le dépot, mais seulement un sous répertoire. On précise donc le chemin complet. On s’abstient aussi de préciser le nom du dossier local, qui sera automatiquement celui du dernier dossier du chemin :

Voila, on a maintenant un dossier Git [1] :

On retrouve bien tout l’historique des commits. On voit aussi que Git a conservé les auteurs des commits SVN, ici identifiés par leurs emails. Mais on aimerait évidemment que les auteurs GitHub soient reconnus pour faciliter la navigation et l’utilisation de l’interface, et respecter au mieux les crédits de chacun.

2. Réattribuer les auteurs

Pour cela il suffit de définir la correspondance entre les auteurs des commits SVN et les auteurs nommés, dans un fichier que l’on indiquera avec l’option --authors-file. Comme il faut fournir la correspondance pour tous les auteurs, commençons par générer un template à partir des logs SVN. On adapte la contribution à notre cas où les auteurs sont déjà des adresses mails, pour en extraire la première partie :

Il reste a copier ce template dans un fichier nommé authors, et de corriger les auteurs dont le compte GitHub n’est pas bon (c’est souvent le même pseudo que dans l’adresse mail, mais pas toujours).

Supprimons notre premier import, et recommençons avec la correspondance des auteurs :

Regardons le résultat :

On a bien cette fois les auteurs des commits qui apparaissent sous leur vrai nom.

3. Nettoyer les messages de commit

En revanche on voit que les logs de commit ont été complétés par une référence au repository SVN d’origine, avec mention du commit SVN. C’est souvent très bien, mais c’est parfois gênant quand le repository d’origine est privé et que vous voulez éviter de le divulguer.

Pour cela, on peut ré-écrire tous les messages de commit grâce à la fonction filter-branch de Git. Attention, ré-écrire les messages de commit va modifier aussi les hash de tous les commits ; Git va donc ré-écrire tout l’historique. Cela est faisable dans un cas comme ici où notre dépôt n’a pas encore été publié ou partagé, mais dès que nous l’aurons poussé, ce type d’opération n’est plus envisageable (sauf à accepter de casser tous les historiques et des autres utilisateurs).

Ré-écrivons donc nos messages avec un sed bien senti :

et vérifions :

Voilà, on a retrouvé nos messages de commits originaux (mais perdu le lien avec les commits SVN).

5. Pousser fort

Il ne reste plus qu’à créer un dépôt GitHub, de le relier à notre dépôt local, et de tout envoyer :

Et c’est gagné !

Un dépôt avec branches et tags

Cette fois nous allons faire un peu plus compliqué : importons dans Git un dépôt qui contient des branches et tags, en récupérant évidemment tout cela sous Git.

Pour l’exemple, on choisit ici le plugin SPIP Corbeille, versionné lui aussi sur l’espace SVN partagé de la communauté SPIP appelé SPIP-Zone

1. Référencer les auteurs

On commence par créer le fichier d’auteurs avec notre commande magique, que l’on copie dans un fichier cette fois nommé authors2 :

2. Importer

Puis on importe en utilisant les options --trunk, --branches, --tags de git svn. Notre dossier corbeille est organisé depuis peu en 3 sous-dossiers trunk/, branches/ et tags/, nous les indiquons donc comme tel :

C’est cette fois un peu plus long car l’analyse du dépôt SVN est plus compliquée. Une fois fini, regardons ce que git-svn nous a importé :

Notre historique ne semble contenir qu’un commit. En fait c’est ici parce que le dernier commit SVN a été une opération de déplacement fichier à fichier pour créer le dossier trunk/, et Git a eu du mal à reconstituer l’historique.

On peut afficher tout l’historique :

On voit alors le graphe complet des branches du dépôt.

3. Référencer les branches importées

Listons les branches importées :

On voit que git-svn a importé toutes les branches et tags sous forme de branches distantes, y compris a différentes périodes correspondant en général à des opérations de copie ou déplacement. Aucun tag n’a été créé.

Il suffit donc de recréer les branches et tags correctement à partir des branches distantes référencées ici. Pour vérifier le contenu d’une branche, on la checkout :

Puis on la créé localement :

Faisons de même pour la seconde branche et son tag :

4. Pousser encore

Il ne reste qu’à pousser tout cela :

Conclusion

Dans notre dernier cas, la reprise de l’historique n’est pas une franche réussite. La faute en incombe à la dernière opération de réorganisation du repository SVN :
Pour créer une organisation en 3 sous-dossiers trunk/, branches/ et tags/, on a créé le sous dossier trunk et on y a déplacé les fichiers un à un. Cela est à éviter, car pour l’import, les fichiers « apparaissent » dans trunk/. Il est préférable de déplacer le dossier complet sous SVN pour faciliter une migration ultérieure sous Git.

Hormis ce soucis, l’import de SVN vers Git à l’aide de la commande git svn permet donc de migrer assez facilement, qui plus est en découpant un gros dépôt SVN en de multiples petits dépôts Git.

— 17 juin 2011

Notes

[1Pour l’utilisation de la syntaxe raccourcie git lg, relisez Git c’est facile

Vos commentaires

  • Le 7 avril 2012 à 13:06, par Gitstack En réponse à : Migrer un projet SVN vers GIT

    Bonjour,

    Merci pour ce tutoriel fort utile et il est vrai que la commande git svn simplifie le travail. Elle est donc intéressante.

    Sinon, je suis assez d’accord pour dire que Git est assez simple à gérer et utiliser et j’ai l’impression que de plus en plus de projets s’y mettent. On verra à la longue mais l’outil prend de l’ampleur.

  • Le 25 septembre 2012 à 16:31, par Greg En réponse à : Migrer un projet SVN vers GIT

    Merci pour ce tuto.

    Par contre, je trouve un peu fastidieux de refaire les tag a la main.
    Dans mon cas, les tags sont représenté par un nouveau commit.

    J’ai donc fait un petit script pour retagguer :
    https://gist.github.com/3782266

    Pour info, voila l'arbre que j'ai eu après l'import du SVN : 
    * 0b2fddc - (HEAD, master) Added gitkeep (Grégoire Pineau 76 minutes ago)
    * 9518324 - (trunk) Added views_data_export module (julien.manganne 5 hours ago)
    | * ba56819 - (tags/2012_09_19_1.1.20) created tag v1.1.20 (gregoire.pineau 6 days ago)
    |/
    * 2d936a7 - (trunk, 2012_09_19_1.1.20) Tâche #9698 - Rajout d'un tag (GA) dans le template global (julien.manganne 6 days ago)
    | * d420424 - (tags/2012_07_23_1.1.19) created tag v1.1.19 (gregoire.pineau 9 weeks ago)
    |/
  • Le 6 juin 2013 à 13:25, par ponsfrilus En réponse à : Migrer un projet SVN vers GIT

    Sauf erreur, l’option —no-metadata lors du git svn clone évite les ids des commits svn.

  • Le 2 janvier 2014 à 12:50, par Ismail SEBBANE En réponse à : Migrer un projet SVN vers GIT

    Bonjour,

    Après avoir exécuter la commande svn git clone d’un repo SVN , j’ai ce message d’erreur aprés quelques minutes :

    RA layer request failed : REPORT of ’/repositories/GALEC-SCANER-DEV/ !svn/vcc/default’ : Could not read chunk delimiter : connection was closed by server (http://repository.neoxia.net) at /usr/local/git/lib/perl5/site_perl/Git/SVN/Ra.pm line 282

    Quelqu’un a déja rencontré ce problème ? avez vous des solutions ?

    MERCI

  • Le 2 janvier 2014 à 17:14, par Ismail SEBBANE En réponse à : Migrer un projet SVN vers GIT

    J’ai trouvé la solution a mon problème , l’erreur viens quand on a un gros repo avec des fichiers volumineux, git svn clone n’arrive pas jusqu’au bout !

    La dernière révision récupéré avant l’erreur étais r480.
    sachant que mon repo a 600 révisions (svn log) donc j’ai joué les commandes suivantes :

    git svn clone -r1:400 http://url-repo
    git svn fetch -r400:500
    git svn fetch -r500:600
    git svn rebase

    Je ne sais pas si c’est la meilleur solution mais ça marchais pour moi :)

    MERCI

  • Le 2 janvier 2014 à 17:28, par Ismail SEBBANE En réponse à : Migrer un projet SVN vers GIT

    Pour info, c’est ce site qui m’a aidé a résoudre mon problème :
    http://randomallsorts.blogspot.fr/2011/10/using-git-svn-with-large-repository.html

  • Le 1er juillet 2015 à 10:00, par BELTRAMI En réponse à : Migrer un projet SVN vers GIT

    Pour ceux qui seraient sur Windows ;)

    $author = svn log -q <<repo>> | Select-String -Pattern '^r' -list | %{ $_.Line.Split("|")[1];}| Sort-Object | Get-Unique | | %{ echo "$_ = ${_%@*} <{$_}>" | Out-File -Encoding default -Append author.txt
  • Le 2 novembre 2017 à 10:09, par Mims En réponse à : Migrer un projet SVN vers GIT

    Simple et bien expliqué :)

    Merci !

Vos commentaires

Qui êtes-vous ?

Pour afficher votre trombine avec votre message, enregistrez-la d’abord sur gravatar.com (gratuit et indolore) et n’oubliez pas d’indiquer votre adresse e-mail ici.

Ajoutez votre commentaire ici

Ce champ accepte les raccourcis SPIP {{gras}} {italique} -*liste [texte->url] <quote> <code> et le code HTML <q> <del> <ins>. Pour créer des paragraphes, laissez simplement des lignes vides.

Suivre les commentaires : RSS 2.0 | Atom