Как импортировать ветки svn и теги в git -svn?
У меня есть центральный SVN-репозиторий, который я должен выполнить, но у меня есть страсть к git (как и любой другой разработчик, которого я знаю). Дело хорошо известно.
Потом я прочитал о git-svn и попробовал. Поскольку мне не нужна полная история, примерно через два месяца, я сделал так:
git svn clone -r 34000 -s https://svn.ourdomain.com/svn/repos/Project/SubProject
Подпроект имел, как обычно, подкаталоги trunk
, tags
и branches
. Отлично.
Затем, чтобы получить последнюю ревизию, я сделал
git svn rebase
Некоторые загрузки позже, отлично. Последняя ревизия, логи и т.д. Хорошо, теперь я переключусь на свою ветку функций.
$ git branch
* master
$ git branch -r
trunk
$ git branch -a
* master
remotes/trunk
Вопросы: где мои ветки? Я сделал что-то не так? Как мне поступить, чтобы мои ветки попали в новый репозиторий git?
git-svn, где бы я ни читал об этом, имел дело с ветками и тегами, но поведение не то, что я ожидал. Спасибо!
РЕДАКТИРОВАТЬ: Я только что узнал, что git svn fetch
сделает это. Но он получит все ревизии, что мне не понравится.
Ответы
Ответ 1
Вам понадобится несколько шагов.
-
укажите правильные имена папок, ветвей и тегов и выберите svn repo:
git svn init -t tags -b branches -T trunk https://mysvn.com/svnrepo
git svn fetch
-
Так как теги в svn являются вещественными ветвями, создайте теги git из ветвей тегов:
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
-
Удаление ветвей тегов
git for-each-ref --format="%(refname:short)" refs/remotes/tags | cut -d / -f 2- |
while read ref
do
echo git branch -rd $ref
done
-
Так как теги, отмеченные на предыдущем шаге, указывают на фиксацию "создать тег", нам нужно получить "реальные" теги, т.е. совершают записи "создания тега".
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
-
Все, что нам нужно сделать, это удалить старые теги.
Ответ 2
Это опирается на ответ Vanuan выше, но он сохраняет сообщение исходного тега svn
в новом теге 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
Ответ 3
Это то же самое, что и ответить nicolai.rostov выше, но я просто изменяю путь refs
Я заменил refs/remotes/tags
на refs/remotes/origin/tags
Я использую git version 2.1.1
в терминале cygwin
.
$ 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
Ответ 4
Вы говорите, что вы не получили свои ветки в своем оформлении.
Вероятно, это проблема с компоновкой вашего репозитория svn.
"Стандартный макет":
branches/
tags/
trunk/
Если у вас есть свой макет, как это:
branches/user1/
branches/user2/
Затем вы потеряете свои ветки, когда будете делать git svn fetch/clone.
Чтобы исправить это, вы должны указать аргумент
--branches=branches/*/*
до git клона.
Ответ 5
Если вы хотите видеть свои ветки при выполнении ветки git после импорта из svn, вы должны использовать ruby script svn2git (и git2svn)
Это лучше, чем git svn clone, потому что если у вас есть этот код в 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
проведет историю фиксации для создания нового репо git.
Он будет импортировать все ветки и теги в качестве удаленных ветвей SVN, тогда как то, что вы действительно хотите, это git -нативные локальные ветки и объекты тега git. Поэтому после импорта этого проекта вы получите:
$ 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 ]
После svn2git
выполняется с вашим проектом, вы получите это вместо:
$ 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
Ответ 6
Я написал скрипт, чтобы помочь мигрировать, как вы хотите. Сценарий не идеален, но я надеюсь, что это поможет вам:
Для получения дополнительной информации вы можете посетить: 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.'
Ответ 7
Для тех, кто должен работать над Windws на работе, вот современное решение с версией git 2.17.0 (и теоретически также работает для версий ранее)
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"
Ответ 8
У меня была та же проблема - теги и ветки отсутствовали, когда я указал ревизию:
$ git svn clone -r 34000 -s https://...
Исправление заключалось в том, чтобы указать диапазон изменений, -r 34000:HEAD
:
$ git svn clone -r 34000:HEAD -s https://...
Список рассылки git дал мне подсказку.