75 votes

Comment importer les branches et les tags svn dans git-svn ?

J'ai un dépôt central SVN dans lequel je dois commiter, mais j'ai une passion pour git (comme tous les autres développeurs que je connais). Le cas est bien connu.

Puis j'ai lu un article sur git-svn et je l'ai essayé. Comme je n'ai pas besoin de l'historique complet, juste de deux mois environ, j'ai fait comme ça :

git svn clone -r 34000 -s https://svn.ourdomain.com/svn/repos/Project/SubProject

SubProject avait, comme d'habitude, les sous-répertoires trunk , tags y branches . Super.

Ensuite, afin d'obtenir la dernière révision, j'ai fait

git svn rebase

Quelques téléchargements plus tard, super. Dernière révision, logs, etc. Ok, maintenant je vais passer à ma branche de fonctionnalité.

$ git branch 
* master

$ git branch -r  
  trunk

$ git branch -a  
* master
  remotes/trunk

Les questions sont : Où sont mes branches ? Ai-je fait quelque chose de mal ? Comment dois-je faire pour que mes branches se retrouvent dans le nouveau repo git ?

git-svn, partout où j'ai lu à son sujet, a traité sagement les branches et les balises, mais le comportement n'est pas celui que j'attendais. Merci !

EDITAR : Je viens de découvrir que git svn fetch le fera. Mais il y aura toutes les révisions, ce que je n'aimerais pas.

2 votes

Cela ne répondra pas à votre question, d'où le commentaire : En utilisant git-svn, vous briserez les fonctionnalités de suivi de fusion de subversion, car git-svn ne les supporte pas. A mon avis, ce seul problème disqualifie git-svn pour une utilisation sérieuse avec un dépôt subversion. Je n'ai pas trouvé d'information pour savoir si cette fonctionnalité sera un jour développée - probablement pas, car les gens préfèrent passer à un DVCS plutôt que d'utiliser de telles astuces.

0 votes

J'ai lu quelque part que la transformation des fusions git en commits en utilisant --squash ne casse pas le suivi des fusions subversion.

5 votes

Pour la disposition standard "trunk/branches/tags", que vous semblez utiliser, vous pourriez essayer --stdlayout , comme dans git svn clone --stdlayout svn://... - voir stackoverflow.com/questions/5361559/

82voto

Vanuan Points 4751

Vous aurez besoin de plusieurs étapes.

  1. fournir les noms de dossiers trunk, branches et tags appropriés et récupérer le repo svn :

    git svn init -t tags -b branches -T trunk https://mysvn.com/svnrepo
    git svn fetch
  2. Puisque les tags dans svn sont des branches réelles, créez des tags git à partir des branches tag :

    git for-each-ref --format="%(refname:short) %(objectname)" refs/remotes/tags |  cut -d / -f 3- |
    while read ref
    do
      echo git tag -a $ref -m 'import tag from svn'
    done
  3. Supprimer les branches d'étiquettes

    git for-each-ref --format="%(refname:short)" refs/remotes/tags | cut -d / -f 2- |
    while read ref
    do 
      echo git branch -rd $ref
    done
  4. Puisque les tags marqués dans l'étape précédente pointent vers un commit "create tag", nous devons dériver les "vrais" tags, c'est-à-dire les parents des commits "create tag".

    git for-each-ref --format="%(refname:short)" refs/tags |
    while read ref
    do
      tag=`echo $ref | sed 's/_/./g'` # give tags a new name
      echo $ref -\> $tag
      git tag -a $tag `git rev-list -2 $ref | tail -1` -m "proper svn tag"
    done
  5. Il ne nous reste plus qu'à supprimer les anciennes balises.

3 votes

La commande "cut" ne fonctionnait pas pour moi pour la migration des tags, probablement à cause d'une sortie différente de la commande "git". Cette ligne de commande modifiée a fonctionné pour moi : git for-each-ref --format="%(refname:short) %(objectname)" refs/remotes/tags | while read tag ref; do echo git tag -a $tag -m \"Import $tag from svn\" $ref; done

6 votes

La même chose ici. Notez également que vous devez supprimer le "echo" dans les commandes une fois que vous êtes satisfait de ce que cela fait et que vous voulez activer la commande réelle. J'ai fini avec la ligne suivante qui marque directement le parent et utilise le message SVN : git for-each-ref --format="%(refname:short) %(objectname)" refs/remotes/tags | cut -d / -f 2- | while read tag ref ; do msg=$(git log --pretty=format:'%s' -1 ${ref}) ; git tag -f -a $tag -m "$msg" ${ref}^ ; done

0 votes

Quelle est la sortie de git for-each-ref --format="%(refname:short)" refs/remotes/tags dans votre cas ?

25voto

nicolai.rostov Points 344

Cela s'inspire de la réponse de Vanuan ci-dessus, mais cela préserve la message de l'original svn dans la nouvelle git étiquette.

$ git for-each-ref --format="%(refname:short) %(objectname)" refs/remotes/tags \
| while read BRANCH REF
  do
        TAG_NAME=${BRANCH#*/}
        BODY="$(git log -1 --format=format:%B $REF)"

        echo "ref=$REF parent=$(git rev-parse $REF^) tagname=$TAG_NAME body=$BODY" >&2

        git tag -a -m "$BODY" $TAG_NAME $REF^  &&\
        git branch -r -d $BRANCH
  done

9voto

rmk Points 2349

Vous dites que vous n'avez pas obtenu vos branches dans votre caisse.

Il s'agit probablement d'un problème de mise en page de votre dépôt svn.

La "disposition standard" est la suivante :

branches/

tags/

trunk/

Si vous avez votre disposition comme ça :

branches/user1/

branches/user2/

Ensuite, vous perdrez vos branches lorsque vous ferez git svn fetch / clone.

Pour corriger cela, vous devez donner l'argument

--branches=branches/*/* pour cloner git.

0 votes

Mais qu'en est-il si les branches sont situées dans la racine comme ici svn.code.sf.net/p/azconvert/code ? Les dossiers phpport y otherfiles semblent être des branches.

6voto

VonC Points 414372

Si vous voulez voir vos branches lorsque vous faites une branche git après un import de svn, vous devez utiliser le ruby script. svn2git (et git2svn)

C'est mieux que git svn clone car si vous avez ce code dans svn :

  trunk
    ...
  branches
    1.x
    2.x
  tags
    1.0.0
    1.0.1
    1.0.2
    1.1.0
    2.0.0

git-svn va parcourir l'historique des livraisons pour construire un nouveau dépôt git.
Il importera toutes les branches et les balises comme des branches SVN distantes, alors que ce que vous voulez vraiment, ce sont des branches locales et des objets balises git natifs. Ainsi, après avoir importé ce projet, vous obtiendrez :

  $ git branch
  * master
  $ git branch -a
  * master
    1.x
    2.x
    tags/1.0.0
    tags/1.0.1
    tags/1.0.2
    tags/1.1.0
    tags/2.0.0
    trunk
  $ git tag -l
  [ empty ]

Après svn2git est terminé avec votre projet, vous obtiendrez ceci à la place :

  $ git branch
  * master
    1.x
    2.x
  $ git tag -l
    1.0.0
    1.0.1
    1.0.2
    1.1.0
    2.0.0

0 votes

Mais en faisant cela, n'ai-je pas tué toute possibilité de commettre dans le repo svn ? Aussi, ma question n'était pas ça. Je n'ai pas mes branches. Donc ce n'est pas une question d'organisation du code.

0 votes

J'ai utilisé svn2git et il a traité toutes mes branches et mes tags comme des tags ... En d'autres termes, quand je fais git branch, il me montre seulement * master. Et quand je fais git tag -l il me montre toutes les branches et tags de SVN ... Cela n'a pas de sens. Est-ce que j'ai raté quelque chose ?

0 votes

@ShariqueAbdullah pas sûr. J'utilise SubGit ces jours-ci : stackoverflow.com/a/18693798/6309

0voto

Andreas Schmid Points 41

Comme tout le monde a rejeté mes corrections à la réponse ci-dessus (manque de ` dans la ligne 4 de la 4ème étape et drapeau -f pour "git tag"), qui a parfaitement fonctionné pour moi après avoir corrigé le bug, voici la version corrigée :

Vous aurez besoin de plusieurs étapes (testé avec la version 1.7.12.4 de git).

  1. fournir les noms de dossiers trunk, branches et tags appropriés et récupérer le repo svn :

    git svn init -t tags -b branches -T trunk https://mysvn.com/svnrepo
    git svn fetch
  2. Puisque les tags dans svn sont des branches réelles, créez des tags git à partir des branches tag :

    git for-each-ref --format="%(refname:short) %(objectname)" refs/remotes/tags |  cut -d / -f 2- |
    while read tag ref
    do
      echo git tag -a $tag -m 'import tag from svn' $ref
    done
  3. Supprimer les branches d'étiquettes

    git for-each-ref --format="%(refname:short)" refs/remotes/tags | cut -d / -f 2- |
    while read ref
    do 
      echo git branch -rd $ref
    done
  4. Puisque les tags marqués dans l'étape précédente pointent vers un commit "create tag", nous devons dériver les "vrais" tags, c'est-à-dire les parents des commits "create tag".

    git for-each-ref --format="%(refname:short)" refs/tags |
    while read ref
    do
      tag=`echo $ref | sed 's/_/./g'` # give tags a new name
      echo $ref -\> $tag
      git tag -af $tag `git rev-list -2 $ref | tail -1` -m "proper svn tag"
    done
  5. Il ne nous reste plus qu'à supprimer les anciennes balises.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X