Перенос SVN-репозитария в git 22 июля 09

Душа просит git, а старые репозитарии остались под SVN. Что же делать? Простое решение – закоммитить текущее состояние проекта в гит – нас явно не устраивает, хочется ведь и историю сохранить, и ветки перетянуть. Приступим.

Фанбои заявляют, что переход с SVN на гит проходит безболезненно. Ну и пусть себе заявляют, мы-то знаем, что все зависит от сложности репозитария, того, какие возможности SVN использовались, и, также, наличия пустых папок. Мне нужно было переносить ветки и svn:ignore. (И пустые папки, конечно.)

Устанавливаем git-svn

Это, собственно, часть гита, так что достать ее можно без проблем. Например, на Ubuntu это делается так:

sudo apt-get install git-svn

Собираем авторов коммитов

Дело в том, что в SVN пользователи – это просто идентификаторы, а в git – email-ы (Еще один плюс гита налицо.)

Выполняем такой вот скрипт в папке 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} = EMAIL";
done

Результат работы скрипта сохраняем куда-нибудь в ~/svn-authors, не забывая заполнить реальные адреса.

Клонируем репозитарий

Указываем URL репозитария, а НЕ транка!

git svn clone -s --authors-file=/home/user/svn-authors svn://repo/location .
  • -s – понимать стандартные папки SVN (trunk, branches, tags)
  • --authors-file=... – использовать файл с авторами с предыдущего шага

Теперь имеем git-репозитарий с содержимым SVN – но пока еще не полный. (Без пустых папок, ну ты понял.)

Разбираемся с ветками

Вытягиваем удаленные ветки в локальный репозитарий.

git fetch . refs/remotes/*:refs/heads/*

Что с пустыми папками?

А, это. Ну в общем git хранит только информацию о файлах. О папках он вообще ничего не знает. Поэтому папку без файлов закоммитить не удастся, и, соответственно, при переносе из SVN они все теряются (drama). Придется создавать их ручками.

Кстати, git-svn сообщает о несозданных папках в лог, который находится в .git/svn/branch/unhandled.log.

Вытягиваем svn:ignore

Для каждой ветки:

git checkout branch
git svn create-ignore
git commit -a -m "imported svn:ignore"

Само собой, при попытке создать .gitignore для несуществующей (а ранее пустой) папки скрипт выкинет ошибку. Пусть это будет для тебя знаком, что такую папку надо создать.

Вычищаем из репозитария упоминания об SVN

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

Удаляем все svn-ветки – те, которые git считает удаленными (remote). Кроме того, удаляем ту ветку, которая является мастером; практика показывает, что это самая свежая ветка. Еще можно удалить мастер, а потом переименовать самую свежую ветку в мастер.

for branch in `git branch -r`; do git branch -rd $branch; done
git branch -d trunk

Последний штрих: удаляем метаданные git-svn

git config --remove-section svn-remote.svn
rm -Rf .git/svn/

Готово! Имеем полностью перенесенный под git репозитарий. Можно пользоваться им сразу, а можно залить на github или на свой сервер в gitosis (о нем я тоже постараюсь рассказать).

Комментарии

  • dmishe 22 июля 2009

    >>а можно залить на github
    github сам все импортирует с историей вместе.

  • Nikolai 23 июля 2009

    А что делать, если фирма не хочет (пока) переходить на гит, но локально уже гит на реальном проекте попробовать хочется? Какие-то подобные статьи имеются?

  • Max 24 июля 2009

    Если в svn использовались svn:externals, то все так просто не пройдет, ибо это не поддерживается git-svn и собственно самим git тоже.

  • Miroslav Rubanets 24 июля 2009

    мое приключение с гит имело целью использовать его для работы с центральным репозиторием.
    Первый облом – время сетевого импорта.
    Второй облом – он не осилил импорт из локального репо полученного svnsync’ом (svn 1.6, гит июльский ). 3й облом – черепаший ui отказывался выполнять команды с центральным репозиторием (версия была свежая). Из командной строки fetch шел, но указать ему ключик от cygwin ssh мне не удалось (это к слову про еще один кривой юникс под виндой).
    так что пока не впечатлило.
    зы идея выкладывания корпоративного репо на гитхаб жжот напалмом.

    • Леонид Шевцов 24 июля 2009

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

      Черепаший ui – это tortoisegit? Да, он еще очень сырой.

      Не знаю, как с гитом под windows, говорят, что плохо, но с другой стороны рядом со мной сидит человек, он замечательно работает c msysgit с авторизацией по ключу.

  • Алексей 19 сентября 2009

    Спасибо, помогло. Самому было трудно разобраться…

  • mikhailov 1 октября 2009

    а что делать, если заказчик ну никак не хочет слышать про гит – вообще падает в обморок от этого слова :)
    делать так:
    $ git init
    $ echo .svn > .gitignore # Git будет игнорить папки SVN
    $ git add .
    $ git commit -m «git init»
    $ svn propset svn:ignore .git # property ’svn:ignore’ set on ‘.’
    $ svn commit -m «ignoring git folder»
    $ git add .
    $ git commit -m «commit for deploy to heroku»

    И работать с гитом локально, а заказчик будет видеть прежний svn-репозиторий

  • Сергей Морозов 5 октября 2009

    Скажите, правильно ли я понимаю, что для того, чтобы иметь основной, «центральный», репозиторий где-то на удаленном хосте, доступном через SSH, нужно, чтобы на этом хосте был установлен Git?

    Для меня эта необходимость до сих пор неочевидна. Почему для того, чтобы удаленно пользоваться файлами (по сути ведь репозиторий — это файлы), нужно дополнительное серверное ПО?

    Можно ли как-то вынести центральный репозиторий на shared-хостинг, на котором нет возможности устанавливать дополнительное ПО?

    • Леонид Шевцов 5 октября 2009

      Если кратко – Git не умеет работать с удаленным репозитарием как с файлами. Это даже описано в Git FAQ.

      Думаю, разработчики не спешат устранять эту проблему, поскольку можно просто смонтировать репозитарий по sshfs (точнее, смонтировать каталог по sshfs и выкладывать туда репозитарий).

  • mikhailov 10 ноября 2009

    git-svn вполне работоспособная альтернатива тупому svn

Оставить комментарий

  • (или OpenID)
  •