Добрый день!
В статье я расскажу, как мы работаем с svn через git и почему не выбрали чистый git.
SVN
Subversion — это централизованная система контроля версий. Это главный ее минус и главный ее плюс :)
Плюс в том, что централизация дает возможность, например, нумеровать коммиты, т.к. их порядок известен.
Так же она минимизирует конфликты (хотя об этом можно и поспорить), т.к. текущее состояние репозитория одно и оно всем известно.
В svn можно хранить несколько проектов в одном репозитории. Вообще интефрейс репозитория в svn очень похож на файловую систему, что обеспечивает минимальный порог вхождения для тех, кто никогда не работал с системами контроля версий.
Главный минус — это merge… Те, кто часто делает мерж средствами svn, понимает о чем я.
Это медленно (даже меееееееедлееенно), требует постоянного соединения с репозиторием, а еще эти svn-properties, которые мешают читать diff.
Казалось бы — решение лежит на поверхности, надо просто сменить систему контроля версий. В нашем же случае нельзя просто так взять и перейти на git.
Причин тому несколько, и все они обусловлены наследием. Если бы мы начинали разработку сейчас, то скорей бы всего выбрали git. У нас репозиторию уже около шести лет, за это время мы создали в нем 129 проектов, а число ревизий перевалило за 88 000.
Мы используем trac в качестве багтрекера. В нем сейчас более 10 тыс тикетов. Во многих есть ссылки на коммиты, подтверждающие исправления. Это богатое наследие терять не хочется.
Так же у svn есть плюс — все проекты лежат в одном репозитории. Trac думает, что проект у нас один, что сильно облегчает работу с ним.
Другими словами, отказ от svn для нас слишком затратен, но мержи...
Решение
Пусть внутри репозитория будет svn, но все желающие будут работать с ним через git. Let's do it!
- Устанавливаем git и git-svn. Метод установки зависит от вашей операционной системы. В моем случае сводится к простому набору команд:
apt-get update && apt-get install subversion git git-svn
- Создаем приятный к использованию ~/.gitconfig
[user] email = e.kokovikhin@co.wapstart.ru name = Evgeniy V. Kokovikhin [core] editor = vim [alias] co = checkout br = branch ci = commit st = status di = diff --color
- Клонируем svn репозиторий:
cd /var/www/project.wapstart/ mkdir project && cd project # создали папку для проекта git svn init --stdlayout https:/path.to.your.svn.server.ru/project # создаст пустой git репозиторий git svn fetch
Последняя команда займет ощутимое время. На нашем репозитории — часа 4.
--stdlayout как бы говорит нам, что расположение проекта у нас стандартное:project ├── trunk ├── branches │ ├── dovgFeature │ └── dovgAnotheFeature └── tags ├── 3.0.1 └── 3.0.2
Собственно все.
Транк теперь называется master, все остальные бранчи именованы как обычно.
Работа с бранчами:
git branch -r # список бранчей
git checkout -b dovgBranch dovgBranch # создать новый локальный бранч dovgBranch из удаленного бранча dovgBranch
git branch # — список локальных бранчей и отметка текущего
Например:
dovg@marvin ~/job/oemdesign/www/plus1.wapstart.loc/plus1 $ git branch
dovgUnique
experimental
* master
moderation
production
referals
targetingCountry
uniqueCookie
uniqueSession
---------
И как теперь с этим работать?
- Работа с svn
git svn rebase # обновить текущую ветку (на самом деле не совсем так) git svn fetch # обновить весь репозиторий git svn dcommit # закоммитить локальные коммиты в svn репозиторий git svn branch <branch-name> # создать бранч :) больше информации в git svn help branch git svn info # информация о ветке svn, в которую смотрит локальная ветка
- Merge. Ради этого мы и делали все это.
git merge --log master # смержит все изменения с красивым логом из главной ветки в текущий бранч.
Для мержа в master (trunk)
git checkout master git merge --no-ff <branch-name> # отмена fast forward merge
Мержи проходят быстро, т.к. не требуют наличие удаленного репозитория. Их больше никто не боится.
- Основы работы с git
git diff — аналог git commit — закоммитить локально «подготовленный» файл git commit -a — закоммитить локально все файлы, которые уже под контролем, но в них были изменения git add — подготовить файл к коммиту. Тут есть отличие от svn. В svn надо добавлять только новые файлы, а в git все измененнные, если вы не пользуетесь git commit -a git reset --hard — прибить все локальные изменения.
Напоследок небольшой FAQ:
- Сделать бранч и переключится в него: git svn branch ticket-666 && git svn fetch && git co -b ticket-666 ticket-666
- Перенести бранч в мастер: git co ticket-666 && git merge --log --no-ff master && git svn dcommit && git co master && git merge --log --no-ff ticket-666 && git svn dcommit
- Сдать бранч в тест (обновить из мастера и закомитить): git co ticket-666 && git merge --log --no-ff master && git svn dcommit
Обновлять периодически репозиторий: git svn fetch
Вместо заключения
Долгое время эта статья провисела во внутренней вики Wapstart. Мне показалось, что она может быть полезна сообществу. Результат перед вами. ;)
Автор: dovg