Несмотря на кажущиеся преимущества распределенной СУВ Git перед централизованной Subversion доказать обоснованность такой миграции оказалось не таким уж и простым делом.
Оказалось, что и в Subversion можно:
- Создавать ветки и объединять их merge toolами визуально и мышкой.
- Там тоже можно откатывать и перемещать коммиты
- Не так уж людям нужно и наличие stashа в Git и даже локальных веток. Доказать, что наличие локального репозитория является преимуществом оказалось не так уж просто, т.к.
а) Мы не распределены, а сидим в одном месте
б) Сеть у нас работает, обрывов не случается и бекапы есть.
в) Как правило, у нас много небольших проектов, в которых все сразу коммитят в master или trunk и наличие веток не представляется таким уж большим преимуществом.
г) Единственное на чем удалось завязать борьбу - это на том, что сделать merge в Subversion все-таки сложнее, чем в Git, а также наличие lockов, которые порой просто не дают работать всем остальным, хотя это и не мешает сделать дополнительную ветку (branch).
В итоге я прочитал следующую лекцию:
0️⃣ История Git. BitKeeper.
1️⃣ Локальный репозиторий и преимущества работы с ним.
в CVS/SVN вы работали с двумя сущностями:
[рабочий каталог] < -> [общий репозиторий]
в GIT схема другая, там три сущности:
[рабочий каталог] < -> [локальный репозиторий] < -> [удалённые репозитории]
2️⃣ Создание веток и частые коммиты
3️⃣ Перемещение коммита с тестами до функционала (и проверка того, что тесты падают).
4️⃣ Текст коммита обязан содержать мотивацию принятия решений и изменений, присутствующих в коде коммита.
5️⃣ Code-review и merge request в gitlab
6️⃣ Есть мощные библиотеки на Perl, Java, Ruby, Python, которые успешно работают с Git и позволяют интегрировать эту СКВ(систему контроля версий) с Hudson, Jenkins, web-сервисами.
7️⃣ Github (мне достаточно и этой причины)
8️⃣ Надежность Умерший сервер в централизованной VCS — это серьёзная проблема, при отсутствие своевременного бекапа — это глобальная катастрофа. В распределенных системах — каждый клон — это фактически бекап всего репозитория.
Используемая литература:
http://asmodeus.com.ua/library/programing/git/from_cvs_to_git.html
https://habrahabr.ru/post/104198/
http://www.whygitisbetterthanx.com/
http://cemick.blogspot.ru/2015/08/svn-git-git.html
https://yalantis.com/blog/code-review-via-gitlab-merge-requests-code-review-must/
http://97things.oreilly.com/wiki/index.php/Challenge_assumptions_-_especially_your_own
https://about.gitlab.com/2014/09/29/gitlab-flow/
http://www-cs-students.stanford.edu/~blynn/gitmagic/intl/ru/ch04.html
http://lib.custis.ru/Линус Торвальдс о GIT_на Google_Talks
https://habrahabr.ru/post/268951/
http://www-cs-students.stanford.edu/~blynn/gitmagic/intl/ru/ch05.html
0️⃣ История Git. BitKeeper.
В 2005 году Торвальдс выпустил релиз Linux 2.6.12-rc2 и заявил, что не продолжит разработку операционной системы, пока не будет замены репозитория BitKeeper, которым сообщество Linux пользовалось до 2005 года. От BitKeeper пришлось отказаться в силу разногласий с ее разработчиками по вопросам его бесплатного использования в opensource-разработке.
Он(git) сделан инопланетянами для инопланетян и их союзников(отрывок из форума).
Там и появились первые команды bk clone, bk push, bk pull. Так как BitKeeper требовал платной лицензии, то Линус в 2005 написал за 2 недели 80_000 строк кода и сделал копию этой функциональности в Git.
1️⃣ Локальный репозиторий и преимущества работы с ним.
Ведь то, что у вас центральный репозиторий, означает, что все, кто работают над проектом, должны складывать данные именно туда.
И что это значит? Поскольку вы не хотите, чтобы все подряд правили данные в центральном репозитории, из-за того, что большинство людей — идиоты, то вам приходится выделять людей, которые, по-видимости, идиотами не являются. И чаше всего в этой группе оказывается слишком мало людей, потому что очень сложно понять, насколько человек шарит, и наоборот, даже если эта группа будет очень мала, проблемы у вас все равно будут.
В общем, эта проблема доступа к коммитам, которую некоторые компании пытаются не замечать, просто давая всем доступ для коммитов, эта проблема создает огромный психологический барьер и в большинстве проектов с открытым кодом приходится тратить бесконечные часы для того, чтобы определиться с политикой коммитов.
Другая заморочка — это ветки. Даже если вы очень эффективно реализовали ветвления, сам факт того, что вы создаете ветки и каждый может их увидеть, потому что все централизовано, означает, что волей-неволей вам не захочется делать никаких веток. Как вы назовете свою ветку? Вы назовете ее «test»? Ага-ага, уже есть 5000 других веток, названных «test1», «test2», … «test5000», так что вам теперь придется выдумывать новые правила именования ваших веток, потому что у вас централизованная система с централизованным пространством имен у ветвей, что совершенно неизбежно при работе с централизованной системой. Как же это работает в распределенной среде разработки?
В CVS/SVN вы работали с двумя сущностями:
[рабочий каталог] < -> [общий репозиторий]
Всякое изменение в рабочем каталоге сохранить некуда, кроме как в общий
репозиторий. Если изменился общий репозиторий, то сохранить изменение вообще
нельзя, предварительно не выполнив операцию update (и не выполнив слияние при
необходимости).
в GIT схема другая, там три сущности:
[рабочий каталог] < -> [локальный репозиторий] < -> [удалённые репозитории]
Операции "сохранить текущую работу в виде коммита" и "синхронизироваться с
внешними изменениями" оказываются полностью независимыми друг от друга.
В локальном репозитории можно создавать любое количество коммитов,
расположенных на любом количестве веток, не оглядываясь на какие бы то ни было
изменения удалённых репозиториев.
Независимо от этого, любую из локальных веток можно различным образом
синхронизировать с какой-нибудь веткой в каком-нибудь удалённом репозитории.
место, из которого ты склонировал, обозначается как удаленный репозиторий под названием "origin"
git clone github.com/funny_guy/just_for_lulz_cod
git pull origin master
, которая получит все изменения и попытается слить их в твою текущую ветку.
git push origin master
- запушить в origin master ветку
git push
отправь текущую ветку в удаленную ветку с тем же именем.
2️⃣ Создание веток и частые коммиты
git branch my_game
git checkout my_game
git branch -b my_game
- создание ветки и переход на нее одновременно
Ветка — это только имя, которое указывает на какой-то коммит.
Ветка foo — это 41-байтный текстовый файл, содержащий хэш коммита (SHA1 хэш патча - коллекции изменений).
C ужасный-драйвер-broadcom
/
A---B---D---E---F origin/master
C-----------. ужасный-драйвер-broadcom
/ \
A---B---D---E---F---G origin/master
Хотим ли особо акцентировать внимание на изменение в коде либо просто закончили итерацию, на все один ответ - коммит. В Git нет проблемы зафиксировать каждый логический блок изменений в рамках задачи отдельным коммитом.
Правила оформления задачи в ветках.
Каждую задачу, как правило, можно декомпозировать на несколько шагов. Отделив, например, рефакторинг от непосредственно кода, исправляющего ошибку.
3️⃣ Перемещение коммита с тестами до функционала (и проверка того, что тесты падают).
Правило "юнит тесты до функциональности". Это правило говорит о том, что юнит тесты должны располагаться в дереве коммитов до исправления ошибки, которую они тестируют. В результате всегда можно проверить работу юнит теста до исправления ошибки и после. Убедиться, что тест и исправление написаны верно.
Пример, где в начале коммиты с тестами, а потом исправление ошибки.Можно легко откатить репозиторий до исправления ошибки и убедится, что тесты написаны правильно и валяться.
4️⃣ Текст коммита обязан содержать мотивацию принятия решений и изменений, присутствующих в коде коммита.
Нужно ввести правила написания текста коммита.
Я бы это видел, как id задачи в ERP IT плюс мотивация принятия решения.
Как писать коммит у нас жестко формализовано. Сами правила начали появляться еще при SVN, но только переход на Git заставил к ним относиться строго. Главное требование гласит: текст коммита обязан содержать мотивацию принятия решений и изменений, присутствующих в коде коммита. Перед выкладыванием на сервер каждая задача проходит ревью кода. И вот тут основной момент - ревьюверу задачи должно быть понятно все только на основе информации из коммита: непосредственно кода и текста описания коммита. Если возникают вопросы, то описание коммита перерабатывается.
Цель описания в коммите - не описание изменений, а описание почему именно так, а не иначе.
В SVN это правило было тяжело соблюдать. Как правило, задача уходила на сервер одним коммитом, что бы не получить в централизованном репозитории не консистентного состояния. Описание всех изменений в одном коммите теряет свою красоту и эффективность. В git'е каждую задачу можно декомпозировать до небольших логических шагов, о чем в следующем правиле.
Повышается культура работы с кодом.
Система постоянно меняется, практически невозможно постоянно актуализировать все требования к приложения и его описания. Но теперь репозиторий взял на себя новую ответственную роль. Стал рассказывать не только кто и когда написал код, но и почему(такую роль бывает берет на себя багтрекер, но это слишком далеко от кода). Можно проследить мысль автора, узнать мотивы. Это формирует еще один уровень метаинформации. С помощью такого слоя информации мы стараемся закрыть наиболее критическое место описания системы. Практика показывает, что гораздо проще восстановить предисторию и все причины принятия конкретного решения для будущей переоценки, если они привязаны к коду и расположены прямо в репозитории.
5️⃣ Code-review и merge request в gitlab
git commit -m "Awesome commit message (Fixes #21 and Closes group/otherproject#22) @username"
Workflow Рабочий процесс
- Клонируем репозиторий
git clone git@example.com:project-name.git
- Создаем ветку к которой будем реализовывать фичу
git checkout -b $feature_name
- Пишем код.
- Добавляем файлы в индекс
git add -A
добавление в git по кусочкам
git add -p
- Коммитим изменения
git commit -am "My feature is ready"
- Получение изменений с сервера (раз в час)
git pull
- Слияние с master
git merge master
- Посылаем ветку (branch) на GitLab
git push origin $feature_name
- Прогон тестов на CI(Hudson/Jenkins) сервере для нашей ветке
- Проверка кода на странице коммита
- Создаем merge request
- Ваш тимлид рассмотрит код и объединит его с основной веткой (master)
git checkout master
git merge style
И мы потихонечку стали перебираться на Git, gitlab, договорившись пока, во время обучения, что
можно коммитить в master, чтобы не стопорить процесс разработки.
Так же возможность бранчевания, ветвления для многих является достаточно сложным понятием и к нему нужно привыкать постепенно.