Год назад мы в проекте выполнили переход с SVN на Git. Нас привлекали возможности бранчевания и работы с репозиторием без сети. "Сарафанное радио" регулярно доставляло сообщения о преимуществах модели распределенных систем контроля ревизий. В итоге, переход себя полностью оправдал, и Git раскрыл множество прекрасных возможностей, о которых во время перехода даже не подозревали. Но самое замечательное, что побочным эффектом оказалось поднятие общего уровня и культуры разработки.
В первой части я расскажу о своих ощущениях после перехода на Git. Если вы уже знакомы с ним, то возможно вам следует перейти сразу ко второй части, где я попытался снизить градус слащавости и пафоса и перейти уже наконец то к делу. Во второй и третьей части я коснусь практических вопросов, которые проливают свет о влияние гита на культуру разработки.
В первой части я расскажу о своих ощущениях после перехода на Git. Если вы уже знакомы с ним, то возможно вам следует перейти сразу ко второй части, где я попытался снизить градус слащавости и пафоса и перейти уже наконец то к делу. Во второй и третьей части я коснусь практических вопросов, которые проливают свет о влияние гита на культуру разработки.
Дифирамбы Git'у
Часто пользователи SVN не видят обоснованных причин для перехода на Git (на самом деле слово Git можно смело заменить на DVCS, однако опыт у меня есть только связанный с Git, потому дальше Git будет мелькать чаще). И в действительности среди плюсов на поверхности лежит лишь концепция распределенности и мифическая легкость ветвления (бранчевания). Как сказал мой друг, парадокс гита заключается в том, что вначале не можешь понять чем Git хорош, а потом не знаешь как это рассказать. Это надо только прочувствовать. Сухое сравнение разных концепций не всегда убедительно. Многие возможности есть в обоих VCS. А по некоторым возможностям SVN имеет преимущества. Кто-то скажет, что у них разные области и назначения, но используют то их чаще всего одинаково. Технические аспекты лучше всего смотреть в официальном руководстве для гита https://git-scm.com/book/ru/v1 (на мой взгляд лучшее руководство по гит), поэтому дальше в статье будут ощущения и эмоции.
С каждым днем только крепнет уверенность, что уже ничто не заставит вернуться обратно. Сказать честно, вначале было много сомнений, стоит ли игра свеч, а не будет ли это потеря времени? Теперь смело заявляю, что Git это намного больше чем SVN, или VCS в парадигме SVN (sic!). Система хранения ревизий с точки зрения SVN является просто хранилищем кода и его изменений, преследуя такие простые практические цели как обмен общими файлами проекта, навигация и возможность вернуться к нужной версии или найти виновника и задачу, в рамках которых был поломан продукт. Слышу от оппонентов: "мне Git не нужен, так как я работаю один/у нас нет веток/в гите нельзя работать с бинарными форматами/ гит слишком сложен/ и т.п." На самом деле он нужен всем (программистам, дизайнерам он может и не подходить) и вот почему.
Git меняет представление о назначение VCS. Поднимает культуру работы с кодом проекта. История изменения кода не менее важна, чем сам код, а может даже более. Git предоставляет возможности выставить акцент на истории изменения кода. В системе контроля версий начинает формироваться слой документации и требований к продукту в самой непосредственной близости к коду. И немаловажным фактором является возможность следовать новым нехитрым практикам работы с репозиторием и кодом, которые дисциплинируют разработчика. Что положительно сказывается на коде. Код становится более логичным, красивым и вылизанным.
Почему же в гите все это можно обеспечить? Краеугольный камень - это распределенность. Что она дает? Обычно говорят, что распределенность дает возможность работать без подключения к интернету и обмениваться ревизиями минуя центральный репозиторий. Да - это верно. Но не на это я хочу обратить внимание. Главное, что репозиторий у вас ЛОКАЛЬНЫЙ. Вот именно так: капсом и болдом. Это позволяет манипулировать ветками и коммитами без опасения повлиять на работу коллег. У нас есть правило, звучащее как "в репозиторий должен попадать только рабочий, целостный код, прошедший ревью". На сколько сложно это правило соблюдать в SVN, на столько легче его соблюдать в гите.
Что же еще делать в гите легко и является ежедневной рутиной, о чем SVN джедаи могли бы только мечтать? В Git'e легко создавать ветки, выполнять слияние, манипулировать коммитами. Вам, как заправскому шулеру, ничего не стоит строить цепочки коммитов, дробить коммиты на более мелкие, менять коммиты местами, менять описание текста коммита и его состав. Каждая операция требует минимального времени выполнения, никакой передачи данных по сети или копирования каталогов.
Ну ок. Все мы уже поняли, что Git хорош как Чак Норис в ковбойской шляпе и из хорошей задачи можно устроить отличный фарш из коммитов. Но зачем? Вот типичные моменты рабочего процесса под Git:
- Ветки создаются под каждую задачу или просто для проверки какой-либо идеи;
- Коммиты создаем часто, очень часто. Хотим ли особо акцентировать внимание на изменение в коде либо просто закончили итерацию, на все один ответ - коммит. В Git нет проблемы зафиксировать каждый логический блок изменений в рамках задачи отдельным коммитом. В SVN такое желание приведет к неконсистентному состоянию кода в центральном репозиторие;
- Увлеклись, написали кучу кода, и вот у нас в одном файле изменения, которые относятся к разным логическим частям? В Git это совершенно не проблема - разные логические части одного файла Git позволяет зафиксировать разными коммитами;
- Забыли написать тесты и проверить их работу до написания функционала? Не проблема, пишем тесты и новый коммит вставляем перед коммитом задачи;
- Хотим отправить изменения в центральный репозиторий, но перед этим избавиться от избытка лишней информации и вместо 15 коммитов, отправить 4 сгруппированных? Все верно - и это не проблема.
- Я уже не говорю про классические преимущества DVSC, такие как совместная работа над одной задачей разных членов команды.
Звучит как фантастика? Отнюдь - просто обычные будни работы с Git. Когда долго не работаешь с SVN забываешь, что там эти операции не возможны. Гит дает чувство пьянящей свободны, нет практически ничего, что вы не могли бы в нем делать. Все делается очень легко: манипулирование ветками и коммитами напоминает игру. И вы от это получаете удовольствие, потому что все ваши, даже сложные, задумки реализуются, а желания предугадываются. Ну и конечно вы получается удовольствие от того, что в памяти всегда свежи ощущения от SVN.
Наши практики по работе с репозиторием кода
Гит добавляет в методологию разработки новые аспекты, которых вовсе не ожидаешь, пока не начнешь его использовать. Эти аспекты мы раскрывали постепенно, шаг за шагом вводя простые правила:
1. | На первом шаге у нас была одна постоянная ветка, бранчи использовались очень эпизодически и не было стабильной версии продукта. Да и так бывает. Бывало даже так, что одним коммитом фиксировалось сразу несколько задач. С этого мы начинали. | ||
2. | Потом появились ветки SVN (до SVN использовали VSS и Perforce). SVN - хорошая система. Какое-то время использовали собственную модель бранчевания, потом сдались и перешли на стандартную раскладку trunk, tags, branches. В branches мы создавали ветки только под большие задачи. Прошло много времени, но я хорошо помню боль и отчаянье от работы с ветками в SVN. Это было долго - долго создавать ветки, долго переключать, долго смотреть лог, а слияния веток превращались в испытание. Но с проблемами можно было мириться, если работать только с долго живущими ветками. | ||
3. | А следом появилось ревью кода. Это была практика, которая все перевернула. Сейчас мне сложно представить разработку без ревью. | ||
4. | Идеальным дополнением к ревью кода стал Git. Модель Git (DVCS) как нельзя лучше подходит для ревью кода. Следующие пункты раскроют это утверждение. | ||
5. |
Первым делом мы ввели правила написания текста коммита. Как писать коммит у нас жестко формализовано. Сами правила начали появляться еще при SVN, но только переход на Git заставил к ним относиться строго. Главное требование гласит: текст коммита обязан содержать мотивацию принятия решений и изменений, присутствующих в коде коммита. Перед выкладыванием на сервер каждая задача проходит ревью кода. Ревью кода выполняется с помощью инструмента CodeReviewer. И вот тут основной момент - ревьюверу задачи должно быть понятно все только на основе информации из коммита: непосредственно кода и текста описания коммита. Если возникают вопросы, то описание коммита перерабатывается. Можно найти множество плюсов подобного подхода:
Теперь текст коммита стал вот таким:
"fix: исправить фокусировку на следующию ячейку после нажатия Enter #issue 40436
При этом мы придерживаемся правила - код должен документировать сам себя. Комментарий в коде - признак плохого кода. Цель описания в коммите - не описание изменений, а описание почему именно так, а не иначе. В тексте коммита можно описать альтернативные варианты решения с плюсами и минусами. К слову сказать, текст коммита у нас так же ревьювируется как и код. В SVN это правило было тяжело соблюдать. Как правило, задача уходила на сервер одним коммитом, что бы не получить в централизованном репозитории не консистентного состояния. Описание всех изменений в одном коммите теряет свою красоту и эффективность. В git'е каждую задачу можно декомпозировать до небольших логических шагов, о чем в следующем правиле. | ||
6. |
Правила оформления задачи в ветках.
Каждую задачу, как правило, можно декомпозировать на несколько шагов. Отделив, например, рефакторинг от непосредственно кода, исправляющего ошибку. Каждый шаг - отдельный коммит в отдельной ветке задачи. В последствии вся ветка попадет в центральный репозиторий, сохраняя для поколений структурированное решение задачи. Теперь даже коммит, который был выполнен "заодно" и не являющийся непосредственно необходимым для закрытия задачи, находится в контексте задачи (в той же ветке), позволяя видеть цель и мотивацию автора.
Задача в SVN - это большой, размазанный по разным модулям патч. Больших усилий стоит разобраться в таком патче. Гораздо проще, когда каждая задача - это структурное решение, и можно пробежаться по отдельным шагам. В таком решении отделяются "зерна от плевел".
Репозиторий стал неотъемлемой частью кода проекта.
Пример: По ходу ревью в код могут вносится изменения, каждое такое изменение может вносится squash коммитом. Это коммит, который в последствие с помощью команды rebase можно объединить с другим коммитом (что бы ощутить мощь Git достаточно пробежаться по оглавлению способов изменить историю https://git-scm.com/book/ru/ и http://97things.oreilly.com/wiki/index.php/Record_your_rationale). Таким образом, можно будет и в ревью видеть развитие мысли автора. А после завершения ревью одной командой rebase можно изменить историю и получить красивое дерево коммитов, без лишнего мусора, объединив squash, fixup коммиты с базовыми. | ||
7. | Правило "юнит тесты до функциональности". Это правило говорит о том, что юнит тесты должны располагаться в дереве коммитов до исправления ошибки, которую они тестируют. В результате всегда можно проверить работу юнит теста до исправления ошибки и после. Убедиться, что тест и исправление написаны верно. Пример: |
Про культуру
Система постоянно меняется, практически невозможно постоянно актуализировать все требования к приложения и его описания. Но теперь репозиторий взял на себя новую ответственную роль. Стал рассказывать не только кто и когда написал код, но и почему(такую роль бывает берет на себя багтрекер, но это слишком далеко от кода). Можно проследить мысль автора, узнать мотивы. Это формирует еще один уровень метаинформации. С помощью такого слоя информации мы стараемся закрыть наиболее критическое место описания системы. Практика показывает, что гораздо проще восстановить предисторию и все причины принятия конкретного решения для будущей переоценки, если они привязаны к коду и расположены прямо в репозитории. Почему важно сохранять подобного рода информацию можно почитать еще здесь 97things.oreilly.com/wiki/index.php/Challenge_assumptions_-_especially_your_own и во многих других местах. Но при при чем здесь культура?
Чтобы понимали, что я имею в виду под культурой, приведу отрывок из книги Бориса Евсеевича Чертока "Ракеты и Люди", за который меня наверное уже недолюбливают как друзья, так и коллеги, слишком уж часто я его вспоминаю:
"В первые годы работы над ракетной техникой практически никто из руководителей, критикующих завод, не мог конкретно сформулировать, что нужно сделать для повышения культуры производства, определить роль каждого начальника цеха, мастера и рабочего. Было слишком много общих решений. Устинов беспощадно расправлялся с начальниками цехов и производств за грязь и бескультурье. При посещениях завода он начинал с туалетов. Обычно в цехах задолго до подхода к туалету разносился характерный «аромат». В самих туалетах надо было ходить по лужам. Устинов приходил в ярость и гремел: «Какой сортир, такой и начальник цеха. Пока не добьетесь образцовой чистоты в своих сортирах, не будет чистоты и в цехах».С тех пор прошло очень много лет. Проблема чистоты общественных туалетов на наших заводах и в институтах так же, впрочем, как и в стране в целом, не решена. Это оказалось куда труднее, чем создать самое грозное ракетно-ядерное оружие и завоевать мировой приоритет в космонавтике.Явный дефицит культуры, общей производственной чистоты и гигиены до сих пор является одной из причин низкого качества многих отечественных изделий. За время войны и в последующие годы забота об элементарном комфорте в цехах, создание рабочему достойной и привлекательной общей обстановки считались излишней и непозволительной роскошью. Затраты на чистоту, комфорт, элементарный сервис с лихвой окупаются повышением производительности и качества. "
Если театр начинается с вешалки, то проект начинается с репозитория. Отношение к репозиторию закладывает отношение ко всему проекту. Аккуратность, формализованность, структурированность, обоснованность, ответственность и прозрачность - качества, которые культивируются приведенными выше правилами работы с репозиторием, переносятся и на другие аспекты проекта. Сам workflow выполнения задачи сопротивляется поспешным, не продуманным, ошибочным и не обоснованным решениям. Код должен выглядеть хорошо и аккуратно не только внутри, но и снаружи. Мелочей не бывает. При переходе на Git о таких вещах, к сожалению, почти не задумывались. Git конечно, не серебряная пуля и не Святой Грааль, но крайне эффективный инструмент, который может сильно изменить ландшафт методологии разработки.
Гит раскрывает свои возможности постепенно. Постоянно открываем что-то новое. В начале используется базовый набор команд. Но потом постепенно открываются все новые и новые возможности и пути оптимизации операций и повышения собственной эффективности. Кажется, что мы используем от 20 - 40% возможностей Git. Мы продолжаем познавать Git, постоянно экспериментируем и дорабатываем наши правила и стандарты. Возможно читатель поделится и своими успешными практиками.
Несколько полезных ссылок
Некоторые правила я не описал, а некоторые из приведенных правил у нас формализованы и описаны гораздо подробнее. Многие правила для подробного описания потребуют статью. Наибольшую важность несет в себе ревью и стандарт написания текста коммита. Крайне рекомендую ресурсы, на основе которых у нас формировались правила, касающиеся написания текста коммита:
- http://git.kernel.org/cgit/git/git.git/tree/Documentation/SubmittingPatches?id=HEAD
- https://docs.google.com/document/d/1QrDFcIiPjSLDn3EL15IJygNPiHORgU1_OOAqWjiDU5Y/edit#
- https://wiki.openstack.org/wiki/GitCommitMessages
- http://stackoverflow.com/questions/3580013/should-i-use-past-or-present-tense-in-git-commit-messages
Комментариев нет:
Отправить комментарий