Мой текущий проект требует, чтобы я поделился кодом с другой командой, которая использует 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, но опасность состоит в том, что он получит другие запросы, и это приведет к проблеме сохранения синхронизации двух несовместимых историй.
Плагин рейтинга создан автором этого блога. Буду очень признателен, если вы сможете его поддержать (ссылка)