09 novembre 2012

from svn to git

Ce billet est plus un mémo pour moi-même afin de ne pas chercher à chaque fois comment effectuer une conversion svn -> Git. (billet fortement inspiré de http://john.albin.net/git/convert-subversion-to-git)

Le but ici n'est pas "juste" de migrer vers git mais de maintenir un lien entre les deux repositories, autrement dit de créer un miroir git du repo subversion.

1. lister les committers

il faut fournir à git le mapping entre les committers SVN et les méta-données associées dans git. Pour cela un petit parsing du svn log va nous aider. En se plaçant dans une copie de travail du repo subversion :

svn log -q | awk -F '|' '/^r/ {sub("^ ", "", $2); sub(" $", "", $2); print $2" = "$2" <"$2">"}' | sort -u > authors.txt

Il peut être nécessaire de faire un peu de ménage dans le fichier généré

2. faire un clone git du repo svn

git svn nous fournit toute la mécanique nécessaire. Attention ça peut prendre un bon moment sur de gros repositories ... 

git svn clone [URL] -A authors.txt --stdlayout


3. extraire les tags

git svn n'est pas très doué avec les tags et les converti en branches - ce qu'ils sont techniquement dans subversion me direz-vous. Un petit script va nous aider à en faire de "vrai" tags git.

git for-each-ref --format='%(refname)' refs/remotes/tags |
cut -d / -f 4 |
while read ref
do
  git tag "$ref" "refs/remotes/tags/$ref";
  git branch -D "tags/$ref";
done

A ce stade, j'applique un recette utilisée sur Jenkins pour la migration en douceur des plugins du SVN java.net vers github

4. conserver une branche de synchro svn

Je crée une branche "svn" initialement identique au master issu de subversion, et je la pousse sur mon repo git 

git checkout -b svn
git remote add origin git@github.com:ndeloof/foo.git
git push origin svn

Cette branche pourra être maintenue synchronisée avec le svn par un job jenkins (git svn rebase), pendant que les pull-requests et autres évolutions seront intégrées dans master.

d'ailleurs, nous allons créer un fichier ignore adapté :

git checkout master
git svn show-ignore > .gitignore
git add .gitignore
git commit -m 'Convert svn:ignore to .gitignore.'
git push origin master



voilà, j'espère que ça aidera. Si vous avez d'autre "recettes"  je suis preneur

3 commentaires:

Jean a dit…

Subgit ( http://subgit.com/ )simplifie grandement toute cette mécanique ...et permet de garder les deux repos synchro pas seulement une branche ...

nicolas deloof a dit…

Merci pour l'info. Par contre "SubGit needs direct access to Subversion repository over filesystem" c'est donc assez contraignant si on a pas la main sur l'infra.

Ghusse a dit…

Souvent, le passage de l'un à l'autre s'accompagne d'une restructuration en projets plus petits.

Avec SVN, on a souvent un gros repository qui contient plusieurs projets. Avec GIT, une bonne pratique est de séparer tout ça, pour éviter d'avoir des repo trop gros.