Как импортировать svn ветви и теги в git-svn? - PullRequest
64 голосов
/ 11 февраля 2010

У меня есть центральный SVN-репозиторий, который я должен выполнить, но у меня есть страсть к git (как и любой другой разработчик, которого я знаю). Дело хорошо известно.

Потом я прочитал о git-svn и попробовал. Поскольку мне не нужна полная история, примерно через два месяца, я сделал это так:

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

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 сделает это. Но он получит все ревизии, что мне не понравится.

Ответы [ 8 ]

73 голосов
/ 12 августа 2012

Вам понадобится несколько шагов.

  1. укажите правильные имена папок стволов, веток и тегов и получите svn repo:

    git svn init -t tags -b branches -T trunk https://mysvn.com/svnrepo
    git svn fetch
    
  2. Поскольку теги в 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
    
  3. Удалить метки

    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. Поскольку теги, отмеченные на предыдущем шаге, указывают на фиксацию «создать тег», нам нужно получить «реальные» теги, т. Е. Родители коммитов «создать тег».

    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. Все, что нам нужно сделать сейчас, это удалить старые теги.

22 голосов
/ 10 февраля 2013

Это основано на ответе Вануана выше, но оно сохраняет сообщение оригинального тега 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
12 голосов
/ 30 ноября 2014

Это то же самое, что и ответ nicolai.rostov выше, но я просто изменяю путь ссылки Я заменил 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
7 голосов
/ 23 февраля 2010

Вы говорите, что не получили свои филиалы при оформлении заказа.

Вероятно, это проблема макета вашего репозитория SVN.

«Стандартная раскладка»:

branches/

tags/

trunk/

Если у вас есть такой макет:

branches/user1/

branches/user2/

Тогда вы потеряете свои ветви, когда выполните git svn fetch / clone.

Чтобы это исправить, вы должны дать аргумент

--branches=branches/*/* для мерзкого клона.

5 голосов
/ 11 февраля 2010

Если вы хотите видеть ваши ветки при выполнении 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
4 голосов
/ 26 августа 2018

Я написал скрипт, который поможет перенести, как вы хотите. Сценарий не идеален, но я надеюсь, что это поможет вам:

Для получения дополнительной информации, вы можете посетить: 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.'
2 голосов
/ 11 мая 2018

Для тех, кто должен работать над 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"
0 голосов
/ 25 октября 2015

У меня была такая же проблема - при указании ревизии отсутствовали теги и ветки:

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

Исправлено было указать диапазон ревизий, -r 34000:HEAD:

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

Список рассылки git подсказал мне.

...