Как перенести репозиторий SVN с историей в новый репозиторий Git? - PullRequest
1459 голосов
/ 17 сентября 2008

Я прочитал руководство по Git, FAQ, Git - SVN и т.д., и все они объясняют то и это, но нигде не найти такой простой инструкции как:

Репозиторий SVN в: svn://myserver/path/to/svn/repos

Git репозиторий в: git://myserver/path/to/git/repos

git-do-the-magic-svn-import-with-history \
svn://myserver/path/to/svn/repos \
git://myserver/path/to/git/repos

Я не ожидаю, что это будет так просто, и я не ожидаю, что это будет одна команда. Но я ожидаю, что он не попытается что-либо объяснить - просто сказать, какие шаги предпринять в этом примере.

Ответы [ 32 ]

7 голосов
/ 13 марта 2014

Это руководство на сайте atlassian - одно из лучших, которые я нашел:

https://www.atlassian.com/git/migration

Этот инструмент - https://bitbucket.org/atlassian/svn-migration-scripts - также очень полезен для генерации вашего author.txt среди прочего.

7 голосов
/ 22 июля 2014

Вы должны установить

git
git-svn

Скопировано по этой ссылке http://john.albin.net/git/convert-subversion-to-git.

1. Получить список всех коммиттеров Subversion

Subversion просто перечисляет имя пользователя для каждого коммита. В коммитах Git гораздо больше данных, но в самом простом случае автору коммитов нужно указать имя и адрес электронной почты. По умолчанию инструмент git-svn просто перечислит имя пользователя SVN как в поле автора, так и в поле электронной почты. Но немного поработав, вы можете создать список всех пользователей SVN и их соответствующие имена и адреса электронной почты Git. Этот список может использоваться git-svn для преобразования простых имен пользователей svn в надлежащие коммиттеры Git.

Из корня вашей локальной проверки Subversion выполните эту команду:

svn log -q | awk -F '|' '/^r/ {sub("^ ", "", $2); sub(" $", "", $2); print $2" = "$2" <"$2">"}' | sort -u > authors-transform.txt

Это будет захватывать все сообщения журнала, извлекать имена пользователей, удалять любые дубликаты имен пользователей, сортировать имена пользователей и помещать их в файл «author-transform.txt». Теперь отредактируйте каждую строку в файле. Например, конвертировать:

jwilkins = jwilkins <jwilkins>

в это:

jwilkins = John Albin Wilkins <johnalbin@example.com>

2. Клонировать хранилище Subversion, используя git-svn

git svn clone [SVN repo URL] --no-metadata -A authors-transform.txt --stdlayout ~/temp

Это выполнит стандартное преобразование git-svn (используя файл author-transform.txt, созданный на шаге 1) и поместит репозиторий git в папку «~ / temp» внутри вашего домашнего каталога.

3. Конвертировать svn: игнорировать свойства в .gitignore

Если в вашем репозитории svn использовались свойства svn: ignore, вы можете легко преобразовать его в файл .gitignore, используя:

cd ~/temp
git svn show-ignore > .gitignore
git add .gitignore
git commit -m 'Convert svn:ignore properties to .gitignore.'

4. Переместить репозиторий в пустой репозиторий git

Сначала создайте пустой репозиторий и сделайте так, чтобы его ветвь по умолчанию соответствовала имени ветки svn «trunk».

git init --bare ~/new-bare.git
cd ~/new-bare.git
git symbolic-ref HEAD refs/heads/trunk

Затем поместите временный репозиторий в новый пустой репозиторий.

cd ~/temp
git remote add bare ~/new-bare.git
git config remote.bare.push 'refs/remotes/*:refs/heads/*'
git push bare

Теперь вы можете безопасно удалить ~ / temp репозиторий.

5. Переименуйте ветвь «ствол» в «мастер»

Ваша основная ветка разработки будет называться «trunk», что соответствует имени, которое было в Subversion. Вы хотите переименовать его в стандартную «основную» ветку Git, используя:

cd ~/new-bare.git
git branch -m trunk master

6. Очистить ветки и метки

git-svn превращает все теги Subversions в очень короткие ветви в Git в форме «теги / имя». Вы захотите преобразовать все эти ветви в фактические теги Git, используя:

cd ~/new-bare.git
git for-each-ref --format='%(refname)' refs/heads/tags |
cut -d / -f 4 |
while read ref
do
  git tag "$ref" "refs/heads/tags/$ref";
  git branch -D "tags/$ref";
done

Этот шаг потребует небольшого набора текста. :-) Но не волнуйтесь; ваша оболочка unix предоставит> вторичную подсказку для очень длинной команды, которая начинается с git for-each-ref.

6 голосов
/ 25 сентября 2013

Несколько расширенный ответ, использующий только git, SVN и bash. Он включает в себя шаги для репозиториев SVN, в которых не используется стандартная компоновка с компоновкой каталогов транка / ветвей / тегов (SVN абсолютно ничего не делает для обеспечения реализации такой компоновки).

Сначала используйте этот bash-скрипт для сканирования вашего репозитория SVN на предмет разных людей, которые внесли свой вклад, и для создания шаблона для файла сопоставления:

#!/usr/bin/env bash
authors=$(svn log -q | grep -e '^r' | awk 'BEGIN { FS = "|" } ; { print $2 }' | sort | uniq)
for author in ${authors}; do
  echo "${author} = NAME <USER@DOMAIN>";
done

Используйте это для создания authors файла, в котором вы сопоставляете имена пользователей svn с именами пользователей и электронной почтой, как установлено вашими разработчиками, используя git config свойства user.name и user.email (обратите внимание, что для службы например, на GitHub достаточно только соответствующего адреса электронной почты).

Затем пусть git svn клонирует репозиторий svn в репозиторий git, сообщая ему о сопоставлении:

git svn clone --authors-file=authors --stdlayout svn://example.org/Folder/projectroot

Это может занять невероятно много времени, так как git svn будет индивидуально проверять каждую ревизию для каждого существующего тега или ветви. (обратите внимание, что теги в SVN на самом деле являются просто ветвями, поэтому они заканчиваются в Git). Вы можете ускорить это, удалив старые теги и ветки в SVN, которые вам не нужны.

Запуск этого на сервере в той же сети или на том же сервере также может реально ускорить это. Кроме того, если по какой-либо причине этот процесс прерывается, вы можете возобновить его, используя

git svn rebase --continue

Во многих случаях вы сделали здесь. Но если у вашего репозитория SVN нетрадиционный макет, где у вас просто есть каталог в SVN, который вы хотите поместить в ветку git, вы можете сделать несколько дополнительных шагов.

Самое простое - просто создать новое SVN-репо на вашем сервере, которое следует соглашению, и использовать svn copy, чтобы поместить ваш каталог в транк или ветвь. Это может быть единственным способом, если ваш каталог полностью находится в корне репозитория, когда я в последний раз пытался это git svn просто отказывался делать извлечение.

Вы также можете сделать это, используя git. Для git svn clone просто используйте каталог, который вы хотите поместить в ветку git.

После запуска

git branch --set-upstream master git-svn
git svn rebase

Обратите внимание, что для этого требуется Git 1.7 или выше.

6 голосов
/ 21 сентября 2008

GitHub теперь имеет функцию импорта из репозитория SVN . Впрочем, я никогда не пробовал.

5 голосов
/ 24 февраля 2016

Я разместил пошаговое руководство ( здесь ) для преобразования svn в git, включая преобразование svn-тегов в git-теги и svn-ветвей в git-ветви.

Короткая версия:

1) клон svn с определенного номера ревизии. (номер редакции должен быть самым старым, который вы хотите перенести)

git svn clone --username=yourSvnUsername -T trunk_subdir -t tags_subdir -b branches_subdir -r aRevisionNumber svn_url gitreponame

2) получить данные SVN. Этот шаг занимает больше всего времени.

cd gitreponame
git svn fetch

повторять git svn fetch, пока не завершится без ошибок

3) обновите ветку master

git svn rebase

4) Создание локальных веток из веток svn путем копирования ссылок

cp .git/refs/remotes/origin/* .git/refs/heads/

5) конвертировать svn-теги в git-теги

git for-each-ref refs/remotes/origin/tags | sed 's#^.*\([[:xdigit:]]\{40\}\).*refs/remotes/origin/tags/\(.*\)$#\2 \1#g' | while read p; do git tag -m "tag from svn" $p; done

6) Поместите репозиторий в лучшее место, как github

git remotes add newrepo git@github.com:aUser/aProjectName.git
git push newrepo refs/heads/*
git push --tags newrepo

Если вам нужны подробности, прочитайте мою запись или спросите меня.

5 голосов
/ 02 мая 2016

Мы можем использовать git svn clone команды, как показано ниже.

  • svn log -q <SVN_URL> | awk -F '|' '/^r/ {sub("^ ", "", $2); sub(" $", "", $2); print $2" = "$2" <"$2">"}' | sort -u > authors.txt

Приведенная выше команда создаст файл авторов из коммитов SVN.

  • svn log --stop-on-copy <SVN_URL>

Команда выше даст вам номер первой ревизии, когда ваш проект SVN будет создан.

  • git svn clone -r<SVN_REV_NO>:HEAD --no-minimize-url --stdlayout --no-metadata --authors-file authors.txt <SVN_URL>

Команда выше создает локальный репозиторий Git.

Проблема в том, что он не будет преобразовывать ветви и теги в push. Вам придется делать их вручную. Например, ниже для филиалов:

$ git remote add origin https://github.com/pankaj0323/JDProjects.git
$ git branch -a
* master
  remotes/origin/MyDevBranch
  remotes/origin/tags/MyDevBranch-1.0
  remotes/origin/trunk
$$ git checkout -b MyDevBranch origin/MyDevBranch
Branch MyDevBranch set up to track remote branch MyDevBranch from origin.
Switched to a new branch 'MyDevBranch'
$ git branch -a
* MyDevBranch
  master
  remotes/origin/MyDevBranch
  remotes/origin/tags/MyDevBranch-1.0
  remotes/origin/trunk
$

Для тегов:

$git checkout origin/tags/MyDevBranch-1.0
Note: checking out 'origin/tags/MyDevBranch-1.0'.
You are in 'detached HEAD' state. You can look around, make experimental
changes and commit them, and you can discard any commits you make in this
state without impacting any branches by performing another checkout.

If you want to create a new branch to retain commits you create, you may
do so (now or later) by using -b with the checkout command again. Example:

  git checkout -b new_branch_name

HEAD is now at 3041d81... Creating a tag
$ git branch -a
* (detached from origin/tags/MyDevBranch-1.0)
  MyDevBranch
  master
  remotes/origin/MyDevBranch
  remotes/origin/tags/MyDevBranch-1.0
  remotes/origin/trunk
$ git tag -a MyDevBranch-1.0 -m "creating tag"
$git tag
MyDevBranch-1.0
$

Теперь отправьте master, ветви и теги в удаленный репозиторий git.

$ git push origin master MyDevBranch MyDevBranch-1.0
Counting objects: 14, done.
Delta compression using up to 8 threads.
Compressing objects: 100% (11/11), done.
Writing objects: 100% (14/14), 2.28 KiB | 0 bytes/s, done.
Total 14 (delta 3), reused 0 (delta 0)
To https://github.com/pankaj0323/JDProjects.git
 * [new branch]      master -> master
 * [new branch]      MyDevBranch -> MyDevBranch
 * [new tag]         MyDevBranch-1.0 -> MyDevBranch-1.0
$

утилита svn2git

svn2git Утилита удаляет ручные операции с ветками и тегами.

Установите его с помощью команды sudo gem install svn2git. После этого выполните команду ниже.

  • $ svn2git <SVN_URL> --authors authors.txt --revision <SVN_REV_NO>

Теперь вы можете перечислять ветки, теги и легко их нажимать.

$ git remote add origin https://github.com/pankaj0323/JDProjects.git
$ git branch -a
  MyDevBranch
* master
  remotes/svn/MyDevBranch
  remotes/svn/trunk
$ git tag
  MyDevBranch-1.0
$ git push origin master MyDevBranch MyDevBranch-1.0

Представьте, что у вас есть 20 веток и тегов, очевидно, что svn2git сэкономит вам много времени, и поэтому мне он нравится больше, чем нативные команды. Это хорошая оболочка для нативной команды git svn clone.

Полный пример см. В моей записи в блоге .

4 голосов
/ 18 апреля 2013

TortoiseGit делает это. см. этот пост в блоге: http://jimmykeen.net/articles/03-nov-2012/how-migrate-from-svn-to-git-windows-using-tortoise-clients

Да, я знаю, что отвечать ссылками - это не здорово, но это решение, а?

3 голосов
/ 17 июня 2014

Если вы используете SourceTree, вы можете сделать это прямо из приложения. Перейдите в Файл -> Создать / Клонировать, затем сделайте следующее:

  1. Введите URL-адрес удаленного SVN как «Исходный путь / URL».
  2. Введите свои учетные данные при появлении запроса.
  3. Введите местоположение локальной папки как «Путь назначения».
  4. Дайте ему имя.
  5. В дополнительных опциях выберите «Git» из выпадающего меню «Создать локальный». хранилище типа ".
  6. При желании вы можете указать ревизию для клонирования.
  7. Hit Clone.

Откройте репозиторий в SourceTree, и вы увидите, что ваши коммит-сообщения тоже перенесены.

Теперь перейдите в Репозиторий -> Настройки репозитория и добавьте новые подробности удаленного репо. Удалите пульт SVN, если хотите (я сделал это с помощью опции «Редактировать файл конфигурации».

Нажмите код для нового удаленного репо, когда вы будете готовы, и кодируйте свободно.

3 голосов
/ 13 сентября 2014

Для пользователей GitLab Я рассказал о том, как я перешел с SVN:

https://gist.github.com/leftclickben/322b7a3042cbe97ed2af

Действия по переходу с SVN на GitLab

Настройка

  • SVN размещен на svn.domain.com.au.
  • SVN доступен через http (другие протоколы должны работать).
  • GitLab размещен на git.domain.com.au и:
    • Группа создается с пространством имен dev-team.
    • Как минимум одна учетная запись пользователя создана, добавлена ​​в группу и имеет ключ SSH для учетной записи, используемой для миграции (тестирование с использованием ssh git@git.domain.com.au).
    • Проект favourite-project создается в пространстве имен dev-team.
  • Файл users.txt содержит соответствующие данные пользователя, по одному пользователю на строку, в форме username = First Last <address@domain.com.au>, где username - имя пользователя, указанное в журналах SVN. (Подробности см. В первой ссылке в разделе «Ссылки», в частности, ответ пользователя Кейси).

Версия

  • версия Subversion 1.6.17 (r1128011)
  • git version 1.9.1
  • GitLab версии 7.2.1 ff1633f
  • Ubuntu server 14.04

Команда

bash
git svn clone --stdlayout --no-metadata -A users.txt 
http://svn.domain.com.au/svn/repository/favourite-project
cd favourite-project
git remote add gitlab git@git.domain.com.au:dev-team/favourite-project.git
git push --set-upstream gitlab master

Вот и все! Перезагрузите страницу проекта в веб-интерфейсе GitLab, и вы увидите все коммиты и файлы, перечисленные в списке.

Примечания

  • Если есть неизвестные пользователи, команда git svn clone остановится, в этом случае обновление users.txt, cd favourite-project и git svn fetch продолжится с того места, где оно остановилось.
  • Требуется стандартная trunk - tags - branches схема для репозитория SVN.
  • URL-адрес SVN, заданный команде git svn clone, останавливается на уровне, непосредственно превышающем trunk/, tags/ и branches/.
  • Команда git svn clone выводит много информации, включая некоторые предупреждения вверху; Я проигнорировал предупреждения.
3 голосов
/ 22 марта 2011

Я очень рекомендую эту короткую серию скринкастов Я только что обнаружил. Автор проведет вас через основные операции и продемонстрирует более продвинутые способы использования.

...