Всем привет!
После довольно длительного периода времени, наконец, появилась
возможность позаниматься нашим проектом, бо накопилось там уже кое-чего,
просится новый релиз, да и кое-какие хотелки старые надо бы попробовать
реализовать.
Напишу много букв, дабы как можно полнее донести мотивы, прошу не судить
за это строго. :)
Случилось так, что уже почти полтора года в текущих проектах в качестве
системы управления версиями использую git вместо svn (в этом году
пересадил на неё всех своих пацанов), и могу сказать только одно...
после git на svn даже смотреть не хочется. Честное слово. При всём
уважении к svn, много лет помогавшей в работе (только благодарность ей и
её авторам за это), она, скорее, является системой управления
архивированием проекта, а не системой управления версиями, это хорошо
понимаешь, поработав с тем же git'ом. Главная причина - работа с
ветвлением. В svn этого, можно сказать, нет. Я всегда чувствовал некий
недостаток, используя svn, как будто чего-то не хватает, как будто
какое-то ограничение... и потом я понял, что это.
Вот ситуация. Работаешь с кодом, в какой-то момент возникла идея, надо
бы попробовать, но ломать текущее состояние не хочется. Ясно - надо
завести ветку и экспериментировать в ней. Будет результат, слить его
обратно в рабочую. И вот тут оно и проявляется. Создать ветку как? На
сервере? Это как-то не очень кузяво - ветка может получиться чисто
экспериментальной и никуда не пойти, т.е. это по сути окажется "мусор".
И зачем это публиковать на сервере? Не говоря уже о не очень бодрой
работе с удалённым сервером (не знаю, у кого как, а у меня с
sf.net
обмен данными весьма неторопливый). Ещё момент: если что-то сделано
неправильно - например, не тот url указал (ошибся с уровнем вложенности
папок), то эти косяки безвозвратно фиксируются в репозитории проекта,
что ни разу не нравится - мусорные коммиты на публичном сервере проекта.
Создать ветку локально через svn copy? Да, такой путь и предпочитаю -
если что-то сделано криво, так это у меня локально всё лежит, можно и
переделать, ничего не ломая, не портя в главном репе. Но это возня с
кучей папок и, по сути, клон всего репозитория со всей его структурой
(trunk, tags, branches) на уровне локального проекта, переход между
ветками не путём переключения их в текущей рабочей директории, а просто
переход в другую директорию (например, из trunk в
branches/<branch_name>). В итоге получается тяжеловесная, негибкая
структура, работать с которой очень неудобно.
Слияние в svn тоже не несёт особой радости. Конечно, по сравнению с cvs
тут гиганский прогресс (как и во многом другом), но тем не менее svn
merge всегда довольно "волнующее" мероприятие с потенциальными сюрпризами.
Как это происходит в git. Вот работаю с кодом и захотелось мне
поэкспериментировать, создаю ветку:
git co -b <branch_name>
при этом в проекте ничего не меняется, т.е. состояние файлов и
директорий то же самое, просто в репозитории (а репозиторий, напомню,
локальный) заводится метка-указатель на текущий коммит (коммит в git -
это просто "слепок" всех объектов (файлов и директорий) проекта), т.е.
на текущий коммит (текущее рабочее состояние проекта) указывает два
указателя - ветка, в которой я был, и ветка, которую я создал, эта
последняя является активной, и именно она будет перемещаться с
коммитами, а если я захочу откатиться в точку, откуда форкнул процесс,
достаточно будет дать команду как выше, только с именем прежней ветки.
Всё происходит практически мгновенно и без ошибок.
Ветка - название в git, не очень отражающие суть, это скорее
традиционное название. Ветка, если соотноситься со смыслом этого слова,
должна бы указывать на совокупность связанных между собой коммитов, как
это имеет место в svn или mercurial (это, кстати, по ходу, главное
отличие ртути от гита), но в git это не так, в git ветка - это просто
указатель на коммит, который, будучи текущим (текущая активная ветка),
автоматически перемещатся при создании нового коммита, указывая на него.
Поэтому создание ветки в git - очень дешёвая, простая операция. Теперь я
могу писать экспериментальный код, делать что угодно, не опасаясь ничего
сломать, и при необходимости быстро и без проблем вернуться к любому
состоянию. Это позволяет создавать ветки, не задумываясь о накладных
расходах, не переходя в другие директории, не меняя ничего в рабочей
директории руками - всё делает git, делает быстро и без ошибок.
Почему я так подробно описываю то, что достаточно хорошо подано в
документации к git'у? Это потому, что именно поддержки этого "паттерна"
в работе svn мне и не хватало. Тут я могу форкнуть процесс разработки,
не теряя точки, от которой "пошёл в сторону", причём делается это
мгновенно и тривиально, т.е. без напрягов во всех смыслах совершенно, и,
что не менее важно, я не загаживаю историю проекта мусорными коммитами -
на удалённый сервер я публикую только те изменения, которые нужны и важны.
На svn меня всегда тормозило осознание того, что, все коммиты становятся
достоянием публики, что публичная история репозитория будет загажена
мусорными коммитами, поэтому всегда старался довести состояние проекта
при фиксации до какого-то целостного законченного вида. Это, как
правило, порождало неслабые такие коммиты с обширными комментариями.
Т.е. рекомендация делать коммиты почаще и поменьше не работала. Тяготела
именно практика использования системы управления версиями как некого
инструмента для полуавтоматизированного архивирования состояний проекта.
Но, как бы, "творческого полёта", что-ли, когда не задумываешься особо,
в каком виде будет история, а просто прямо с любой позиции делаешь форк
и пошёл по нему - не покатило - секунда и откатился назад, покатило -
слил в точку ветвления, в svn нет.
Сейчас у меня уже выработался определённый стиль работы, который
разительно отличается от прежнего: сейчас вся работа делатеся в
короткоживущих ветках:
feature branches - разрабатывается всё новое;
hotfix branches - фиксятся ошибки, вносятся/тестируются неотложные правки.
После все нужные изменения сливаются в рабочую ветку, которая содержит
всегда только рабочие коммиты, а оттестированные стабильные коммиты из
неё периодически переносятся в отдельную релизную ветку. Т.е. есть две
постоянные ветки, и в них никакой разработки не ведётся, в них
фиксируются только рабочие состояния.
Таким образом, в любой момент всегда, можно сказать, "в мгновение ока",
доступны любые стабильные и любые рабочие состояния проекта вне
зависимости от того, что в каждый текущий момент разрабатыватся. Т.е.
можно смело начинать делать что угодно, не опасаясь ситуации, что может
потребоваться в любой момент перейти к любому релизу. При этом даже не
надо покидать текущую рабочую директорию - всё делается в одном и том же
месте.
До кучи очень удобные, простые и полезные фичи git'а, такие как stage,
stash, cherry-pick, rebase и многие другие, делающие работу намного
более продуктивной и безопасной (в смысле потери данных).
В общем, это большущее удобство, внутренний комфорт и уверенность, и
отказываться от этого очень ломает. Поэтому вот сейчас, когда дошли руки
до проекта, хочется иметь тот же комфорт, к которому уже успел
привыкнуть. Для себя в этом случае просто заведу локальный репозиторий и
буду в нём ковырять, а потом финальную часть солью в репозиторий
проекта. Но это полумера, а связываться с git-svn что-то не очень хочется.
Обсудил вопрос с Антоном, как использующим git, он посоветовал в этой
ситуации то же самое. Но попутно заметил, что как раз время обратить ещё
раз внимание на этот вопрос, а заодно и переехать с
sf.net на github.
Против sf имеется аргумент: оказывается, у этого ресурса некоторое время
назад сменился хозяин, и стали происходить некрасивые вещи:
http://www.opennet.ru/opennews/art.shtml?num=42318
http://www.opennet.ru/opennews/art.shtml?num=42354
что, понятное дело, не радует.
Главное препятствие, которое я вижу на этом пути - это необходимость
всем участникам проекта освоить git. Подробность, с которой написан
текст выше, преследует одну цель: показать собственный опыт (чего
хотелось, что не моглось и что смоглось :)), может быть это как-то,
что-ли, вдохновит.
Чесслово, я жалею, что не начал использовать git раньше, это просто
другая жизнь. Очень бы хотелось двигать проект в этом направлении, но
насилия не приемлю ни в каком виде, глубоко убеждён, что только на
основе общего согласия и можно достичь хорошего результата.
Поэтому выражаю от себя лично и от лица Антона предложение ко всем
остальным участникам проекта:
1. рассмотреть возможность освоения VCS git;
2. рассмотреть возможность перевода проекта на хостинг github.
Не обазательно всё делать резко и сразу. Делать без напряга, спокойно.
*******************************
Попутно замечание: порог вхождения, чтобы начать что-то делать, у git'а
совсем невысокий. Реально достаточно прочитать первые три главы (они
небольшие):
http://git-scm.com/book/ru/v1/Введение
http://git-scm.com/book/ru/v1/Основы-Git
http://git-scm.com/book/ru/v1/Ветвление-в-Git
чтобы начать полноценно работать. Конечно, понимание нюансов, как
обычно, придёт чуть позже, но это не мешает начать работать. На вопросы
и Антон, и я с удовольствием ответим.
Далее установить клиента, при желании настроить alias'ы (ну, чтобы не
писать каждый раз git status, а достаточно было git st или вообще gst (я
щас такой алиас использую)). Реально при наличии немалого количества GUI
клиентов, они, имхо, нафиг не нужны. Очень удобная и эффективная консоль
(unix-style). Для просмотра лога в удобном виде там есть простенькая GUI
смотрелка, входящая в состав базового пакета.
*******************************
В общем, вот как-то так. Прошу высказываться.
--
HZ