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.
Vous aurez besoin de plusieurs étapes.
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
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
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
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
Il ne nous reste plus qu'à supprimer les anciennes balises.
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
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
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.
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
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.'
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"
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.