Как импортировать 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
сделаю это. Но он получит все изменения, что мне не понравится.
9 ответов
Вам понадобится несколько шагов.
укажите правильные имена стволов, веток и папок и получите 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
Все, что нам нужно сделать сейчас, это удалить старые теги.
Это опирается на ответ Вануана выше, но оно сохраняет сообщение оригинала 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
Это то же самое, что и ответ nicolai.rostov выше, но я просто изменил путь refs, который я заменил refs/remotes/tags
от refs/remotes/origin/tags
Я использую git версию 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
Вы говорите, что вы не получили свои филиалы в кассе.
Это, вероятно, проблема с макетом вашего репозитория SVN.
"Стандартная раскладка" это:
branches/
tags/
trunk/
Если у вас есть ваш макет, как это:
branches/user1/
branches/user2/
Тогда вы потеряете свои ветви, когда будете делать git svn fetch / clone.
Чтобы это исправить, вы должны дать аргумент
--branches=branches/*/*
чтобы сделать клон.
Я написал скрипт, чтобы помочь мигрировать, как вы хотите. Сценарий не идеален, но я надеюсь, что это поможет вам:
Для получения дополнительной информации вы можете посетить: 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.'
Если вы хотите видеть ваши ветки при выполнении git ветки после импорта из svn, вы должны использовать скрипт ruby 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
Для тех, кто должен работать над 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"
Чтобы вытащить новую ветку SVN в ваш локальный репозиторий Git-SVN, я нашел простой метод, который не требует редактирования каких-либо файлов конфигурации или чего-то подобного.
Вам нужен только номер версии последнего коммита в ветке, которую вы хотите добавить в локальный репозиторий git-svn.
Если у вас есть актуальная проверка SVN для новой ветки и установлен TortoiseSVN, вы можете щелкнуть эту папку правой кнопкой мыши и использовать «TortoiseSVN / Показать журнал».
Запишите самую верхнюю фиксацию (например, 45065).
Теперь используйте в Git Bash следующую команду:
git svn fetch -r45065
ПРИМЕЧАНИЕ: Вам необходимо заменить номер
45065
против вашего номера фиксации.
Теперь git перетащит новую удаленную ветку в ваш локальный репозиторий.
Затем вы можете проверить это, создав локальный филиал. Я использую Git Extension для проверки новой ветки, используя «Remote-Branch» и параметр «Создать локальную ветку с именем: ...».
Подсказка: вы можете удалить префикс «origin/» из имени вашей локальной ветки, чтобы избежать предупреждения «refname 'origin/ V8.0' неоднозначно».
У меня была та же проблема - теги и ветки отсутствовали, когда я указывал ревизию:
$ git svn clone -r 34000 -s https://...
Исправление должно было указать диапазон изменений, -r 34000:HEAD
:
$ git svn clone -r 34000:HEAD -s https://...
Список рассылки git подсказал мне.