Git as Subversion

276c0eb100694119be34a11b30ded535.jpgНекоторое время назад при старте нового проекта было решено попробовать использовать Git вместо Subversion. Через некоторое время коллектив разделился на тех, кто любит Git (программисты), и тех, кто его ненавидит (дизайнеры и художники). Эксперимент по замене Subversion на Git провалился и на горизонте замаячила перспектива возвращения Subversion.Почесав репу и содрогнувшись от связанных с Subversion воспоминаний мужики решили: «А что, мы же программисты!» и запилили свой Subversion с Git-ом и печеньками. Так родился проект git-as-svn.

Теперь мы можем использовать и Git, и Subversion с одним и тем же репозиторием. Причем доступ через Subversion напрямую использует данные Git-репозитория, в отличие, скажем, от SubGit, где для Subversion используется отдельный репозиторий.

Справедливости ради надо отметить, что оба лагеря были по-своему правы. В пользу Git можно сказать следующее: У Git-а можно делать по ветке на задачу и спокойно коммитить промежуточные результаты без риска все разломать. Git, по сравнению с Subversion, нереально быстрый. Против Git: Более высокий порог вхождения: Git объективно сложнее, чем Subversion; TortoiseGit далеко не такой удобный как TortoiseSvn; многие вещи надо делать через консоль; много больше способов отстрелить себе ногу. У Git не очень хорошо с клиентами под Windows. Для работы в Subversion-стиле (обновил → поработал → залил → поработал → залил…) нужно много больше телодвижений. Нет разделения прав внутри репозитория. При большом количестве постоянно заливающего народу, люди начинают биться головами (между pull и push успевает кто-то вклиниться). И самое главное: Git не даёт никаких преимуществ и создаёт дополнительные проблемы, если файлы не поддаются мержу.Когда стало ясно, что эксперимент по замене Subversion на Git провалился, начали поиск решения из сложившейся ситуации. В процессе поиска были обнаружены:

Поддержка Subversion на GitHub.Можно приобрести в комплекте с GitHub Enterprise за сотни нефти. Стремный проект SubGit.SubGit пытается через хуки поддерживать в синхронном состоянии Git и Subversion репозитории. Это архитектурное решение выглядит очень шатким, хотя, надо отметить, что реализация кажется рабочей. Люто тормозящая python-реализация Subversion-фронтэнда для Git-репозитория.Самое главное в этом проекте — его небольшой объем. После этого задача реализации Subversion-фронтенда для Git-репозитория стала казаться просто безумной, а не абсолютно безумной, как было ранее. :) Данный проект представляет собой реализацию Subversion-фронтэнда для Git-репозитория. Он позволяет работать с репозиторием при помощи, как минимум: консольного Subversion-клиента; TortoiseSVN; SvnKit. На данный момент поддерживается: svn checkout, update, switch, diff svn commit (!) svn log svn cat, ls svn replay (svnsync) partial checkout sparse working copy (svn --depth/--set-depth) git submodules аутентификация через LDAP По производительности работа не просто сопоставима, но местами даже превосходит родной Subversion-сервер.Как работает коммит? Одна из самых важных деталей системы — сохранение изменений. В общих чертах, идея следующая: В момент команды svn commit клиент отправляет на сервер свои изменения. Сервер при этом запоминает их. В этот же момент происходит первая проверка на актуальность клиентских данных. Сервер берет голову ветки и начинает формировать новый коммит на базе полученных от клиента данных. В этот момент происходит ещё одна проверка на актуальность клиентских данных. Проверяется целостность svn properties для заливаемых данных. Сервер пытается консольным Git-клиентом сделать push нового коммита в текущую ветку этого же репозитория. Далее по результату push-а: — если все хорошо — загружаем последние изменения из git-коммитов и радуемся; — если не fast forward — загружаем последние изменения из git-коммитов и идём к шагу 2; — если отбили хуки — сообщаем клиенту; — если другая ошибка — сообщаем клиенту. Таким образом, за счёт использования в данной операции консольного Git-а мы избегает гонки с заливкой напрямую через Git, и получаем хуки в качестве приятного бонуса.Где хранятся svn-данные репозитория? Для представления Subversion репозитория нужен ряд данных, которые в Git либо отсутствуют (например, данные о том, откуда скопирован файл), либо очень дорого получить (например, номер ревизии, когда файл менялся в последний раз). Чтобы не заниматься их расчетом каждый запуск, они кэшируются в ветках refs/git-as-svn/*. Этот же кэш позволяет не ломаться соответствии Git-коммитов Subversion-ревизиям из-за операций force push. ;-) На данный момент приходится мириться со следующими ограничениями: нельзя средствами Subversion менять svn properties; не сохраняется история копирования файлов. Svn properties Основная беда svn properties в том, что некоторые свойства надо поддерживать в синхронном состоянии между Git и Subversion. Чтобы эти данные не расходились, svn properties генерируются на базе содержимого файлов из Git-репозитория (например, svn: ignore генерируется на основании .gitignore). При коммите же происходит проверка сохраняемых свойств данным репозитория. Это накладывает важное ограничение: нужно корректно формировать svn: auto-props, иначе при добавлении файлов пользователю придётся приводить их руками к виду, который ожидает сервер.Самое злобное свойство: svn: eol-style. Основная беда в том, что поведение Git-а по умолчанию в контексте eol-ов сломано и соответствует файлу .gitattributes с содержимым:

* text=auto eol=native То есть, с настройками по-умолчанию Git меняет содержимое текстовых файлов.После долгих страданий было найдено решение проблемы eol-ов: в корень Git-репозитория нужно добавить файл .gitattributes, начинающийся со строки:

* -text Это потребует от Git не трогать окончания строк у файлов до тех пор, пока его об этом явно не попросят. На данный момент проект находится в неторопливой разработке и эксплуатируется в одной из команд Mail.Ru Group. В результате, люди вольны использовать подходящий для их нужд инструмент: дизайнеры используют TortoiseSvn и заливают им изменения напрямую в master, а программисты пользуются Git-ом и живут в своих уютненьких веточках. Обстановка в целом стала здоровее, и у коллег перестали сжимать кулаки, когда кто-то рядом произносит слова Git или Subversion. Чтобы запустить git-as-svn нужно: Установить Java 8. Скачать последнюю сборку с github.com/bozaro/git-as-svn/releases/latest. Распаковать архив. Запустить сервер. java -jar git-as-svn.jar --config config.example --show-config В результате будет создан Git репозиторий с одним тестовым коммитом, доступный по URL svn://localhost/example/ из под пользователя test с паролем test. В качестве клиента настоятельно рекомендуется использовать клиент для Subversion 1.8+.

© Habrahabr.ru