Мой текущий проект требует, чтобы я поделился кодом с другой командой, которая использует svn, пока моя команда работает на github. Чтобы коммиты были в актуальном состоянии, мне нужно синхронизировать обе системы контроля версий, чтобы слияние было простым. После некоторых экспериментов и неудач я разработал относительно безопасный способ позволить им сосуществовать без каких-либо неприятных конфликтов. В Интернете есть разнообразная документация о том, как это сделать, например, в справке github и stackoverflow.

Как правило, разрешать github и svn помещать изменения в одно и то же репо – это плохо. И с историей могут случиться страшные вещи, которые я узнал на собственном горьком опыте (к счастью, git rebase и reset – настоящие спасатели).

Git построен на концепции локального репозитория, который синхронизируется с одним или несколькими удаленными репозиториями. Что касается svn-соединения, git рассматривает его как еще один удаленный репозиторий с разницей в способе его синхронизации с локальным репозиторием.

Мое локальное репозиторий git настроено с двумя пультами – один – svn, другой – github. Чтобы сохранить два мира в безопасности, я сделаю две ветви. Один отслеживает только пульт svn, а другой отслеживает только пульт github. Затем я обращаюсь с двумя ветвями как с отдельными вилками. Поэтому я не перетаскиваю с другого пульта на ветку, а использую git-merge.

к содержанию ↑

Настройка

Я начинаю с репозитория git, имеющего происхождение от github, и создаю ветку для работы, которая будет отслеживаться на github и совместно использоваться веткой svn – это обычная ветка git или она может быть главной.

git branch mygitbranch
git checkout mygitbranch
git push origin mygitbranch

Отдельно у меня есть репозиторий svn с той же версией исходных файлов, что и на github.

Теперь я создаю ветку svn-tracking как ветку без отслеживания в моем локальном репозитории git:

git branch --no-track mysvnbranch  <id или самый первый коммит>
git checkout mysvnbranch

Затем подключитесь к репозиторию svn, перетащите исходный код в эту ветку и сделайте изменения репозитория svn единственными изменениями в этой ветке.

git svn init https://my.svnrepo.org/svn/repository/whatever/ -s
git svn fetch
git reset --hard remotes/trunk

Итак, мое дерево теперь выглядит примерно так (с отслеживаемым пультом в скобках):

.___ master (remotes/origin/master)
   |._ mygitbranch (remotes/origin/mygitbranch)
_.__._ mysvnbranch (remotes/trunk)
к содержанию ↑

Мержим

В дальнейшем в ветке github-tracked есть изменения, и мне нужно синхронизировать их с репозиторием svn. например

git checkout mygitbranch
git pull origin mygitbranch
_.___ master (remotes/origin/master)
   |__._.__._ mygitbranch (remotes/origin/mygitbranch)
_.__._ mysvnbranch (remotes/trunk)

Переключитесь на отслеживаемую ветку svn, объедините различия с отслеживаемой веткой github и зафиксируйте изменения. Но также не забудьте сначала выполнить переустановку на изменения svn:

git checkout mysvnbranch
git svn rebase    (необходимо получить и переустановить любые изменения, внесенные в svn)
git merge origin/mygitbranch
git mergetool     (если есть конфликты, которые не могут быть разрешены автоматически)
git commit
git svn dcommit

Теперь ветки будут выглядеть так:

_.___ master (remotes/origin/master)
   |__._.__._ mygitbranch (remotes/origin/mygitbranch)
_.__.________\._ mysvnbranch (remotes/trunk)

Аналогично и в обратном случае:

git checkout mygitbranch
git pull origin mygitbranch
git merge remotes/trunk
git commit
git push origin mygitbranch

Дело в том, что ветвь svn-tracked будет отслеживать только удаленный svn. Можно отправить mysvnbranch на github, но опасность состоит в том, что он получит другие запросы, и это приведет к проблеме сохранения синхронизации двух несовместимых историй.

Голосов  (4)
Плагин рейтинга создан автором этого блога. Буду очень признателен, если вы сможете его поддержать (ссылка)
Об авторе

Веб-разработчик. Работа с проектами простой и средней сложности. Верстка, программирование. Simpla, Drupal, Wordpress.

Смотреть посты