web-dev-qa-db-fra.com

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

J'ai un référentiel central SVN auquel je dois m'engager, mais j'ai une passion pour git (comme tout autre développeur que je connais). Le cas est bien connu.

Ensuite, j'ai lu sur git-svn et l'ai essayé. Puisque je n'ai pas besoin de l'historique complet, juste de deux mois à peu près, j'ai fait comme ceci:

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

Comme d'habitude, le sous-projet comportait les sous-répertoires trunk, tags et branches. Génial.

Ensuite, pour obtenir la dernière révision, je me suis

git svn rebase

Quelques téléchargements plus tard, génial. Dernière révision, journaux, etc. Ok, je vais maintenant 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 soient dans le nouveau dépôt Git? 

git-svn, où que je sois lu, a traité judicieusement les branches et les tags, mais le comportement n’est pas celui que j’attendais. Merci!

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

64
Luís Guilherme

Vous aurez besoin de plusieurs étapes.

  1. fournissez les noms de dossier des troncs, des branches et des étiquettes appropriés et récupérez svn repo:

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

    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 de la balise

    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. Etant donné que les balises marquées à l’étape précédente pointent vers un commit "create tag", nous devons en déduire des balises "réelles", c’est-à-dire les parents de "create tag" commits.

    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.

72
Vanuan

Ceci s’inspire de la réponse de Vanuan ci-dessus, mais conserve le message de la balise svn originale dans la nouvelle balise git.

$ 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
22
n.r.

C'est la même chose que la réponse de nicolai.rostov ci-dessus, mais je viens de changer le chemin d'accès refs J'ai remplacé refs/remotes/tags par refs/remotes/Origin/tags J'utilise git version 2.1.1 dans cygwin Terminal.

$ git for-each-ref --format="%(refname:short) %(objectname)" refs/remotes/Origin/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
11
Mohamed EL HABIB

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

C'est probablement un problème avec la mise en page de votre svn repo.

La "mise en page standard" est:

branches/

tags/

trunk/

Si vous avez votre mise en page comme ceci:

branches/user1/

branches/user2/

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

Pour résoudre ce problème, vous devez donner l'argument

--branches=branches/*/* à git clone.

7
rmk

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

C'est mieux que git svn clone car si vous avez ce code en 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 passera par l'historique de validation pour créer un nouveau dépôt Git.
Il importera toutes les branches et tous les tags en tant que branches SVN distantes, alors que ce que vous voulez vraiment, ce sont des branches locales git-native et des objets git tag . 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 ]

Une fois que svn2git est terminé avec votre projet, vous obtiendrez ceci:

  $ 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
5
VonC

J'ai écrit un script pour vous aider à migrer comme vous le souhaitez. Le script n'est pas parfait, mais j'espère que cela pourra vous aider:

Pour plus d'informations, vous pouvez visiter: https://github.com/MPDFT/svn-to-git

#!/bin/bash

####### Project name 
PROJECT_NAME="myproject"
EMAIL="mycompany.com"

###########################
####### SVN 
# SVN repository to be migrated
BASE_SVN="http://svn.mycompany.com/svn/repo/sistemas/myproject"

# Organization inside BASE_SVN
BRANCHES="branches"
TAGS="tags"
TRUNK="trunk"

###########################
####### GIT 
# Git repository to migrate
GIT_URL="https://git.mycompany.com/git/repo/sistemas/myproject.git"

###########################
#### Don't need to change from here
###########################

# Geral Configuration
ABSOLUTE_PATH=$(pwd)
TMP=$ABSOLUTE_PATH/"migration-"$PROJECT_NAME

# Branchs Configuration
SVN_BRANCHES=$BASE_SVN/$BRANCHES
SVN_TAGS=$BASE_SVN/$TAGS
SVN_TRUNK=$BASE_SVN/$TRUNK

AUTHORS=$PROJECT_NAME"-authors.txt"

echo '[LOG] Starting migration of '$SVN_TRUNK
echo '[LOG] Using: '$(git --version)
echo '[LOG] Using: '$(svn --version | grep svn,)

mkdir $TMP
cd $TMP

echo
echo '[LOG] Getting authors'
svn log -q $BASE_SVN | awk -F '|' '/^r/ {sub("^ ", "", $2); sub(" $", "", $2); print $2" = "$2" <"$2"@"$EMAIL">"}' | sort -u >> $AUTHORS

echo
echo '[RUN] git svn clone --authors-file='$AUTHORS' --trunk='$TRUNK' --branches='$BRANCHES' --tags='$TAGS $BASE_SVN $TMP
git svn clone --authors-file=$AUTHORS --trunk=$TRUNK --branches=$BRANCHES --tags=$TAGS $BASE_SVN $TMP

echo
echo '[LOG] Getting first revision'
FIRST_REVISION=$( svn log -r 1:HEAD --limit 1 $BASE_SVN | awk -F '|' '/^r/ {sub("^ ", "", $1); sub(" $", "", $1); print $1}' )

echo
echo '[RUN] git svn fetch -'$FIRST_REVISION':HEAD'
git svn fetch -$FIRST_REVISION:HEAD

echo
echo '[RUN] git remote add Origin '$GIT_URL
git remote add Origin $GIT_URL

echo
echo '[RUN] svn ls '$SVN_BRANCHES
for BRANCH in $(svn ls $SVN_BRANCHES); do
    echo git branch ${BRANCH%/} remotes/svn/${BRANCH%/}
    git branch ${BRANCH%/} remotes/svn/${BRANCH%/}
done

git for-each-ref --format="%(refname:short) %(objectname)" refs/remotes/Origin/tags | grep -v "@" | cut -d / -f 3- |
while read ref
do
  echo git tag -a $ref -m 'import tag from svn'
  git tag -a $ref -m 'import tag from svn'
done

git for-each-ref --format="%(refname:short)" refs/remotes/Origin/tags | cut -d / -f 1- |
while read ref
do
  git branch -rd $ref
done

echo
echo '[RUN] git Push'
git Push Origin --all --force
git Push Origin --tags

echo 'Sucessufull.'
4
carolnogueira

Pour ceux qui travaillent sur Windows au travail, voici une solution mise à jour avec la version 2.17.0 de Git (et fonctionnant théoriquement également pour les versions antérieures)

git svn init -t tags -b branches -T trunk https://mysvn.com/svnrepo

git svn fetch

for /f "tokens=1-2 delims= " %a in ('git for-each-ref --format="%(refname:lstrip=-1) %(objectname)" refs/remotes/Origin/tags') do git tag -a %a %b -m "import tag from svn"
1
Qianlong

J'ai eu le même problème - des étiquettes et des branches étaient manquantes lorsque j'ai spécifié la révision:

$ git svn clone -r 34000 -s https://...

Le correctif consistait à spécifier une plage de révisions, -r 34000:HEAD:

$ git svn clone -r 34000:HEAD -s https://...

La liste de diffusion git m'a donné l'indice.

0
cweiske