4.3 Что такое системы контроля версий и зачем они нужны: на примере Git

В истории развития информационных технологий есть ряд изобретений и программистов, определивших облик индустрии на много лет вперёд.

Яркий пример — как появилась система контроля версий Git, один из важнейших для программистов инструментов. Он не просто изменил индустрию, а лёг в основу движения разработчиков открытого кода — в виде проекта GitHub.

Интерфейс GitHub. Источник

Но обо всём по порядку. В этом параграфе мы:

  • поговорим о том, зачем вообще нужны системы контроля версий (VCS) и какую проблему они решают;
  • рассмотрим суть Git;
  • увидим, как появились и развивались VCS;
  • отдельно остановимся на истории появления Git;
  • и, наконец, расскажем, зачем нужен GitHub и как он появился.

Прежде чем начать — небольшой дисклеймер.

Этот параграф — для любителей истории компьютерных наук.

Если вас больше интересуют практические навыки — советуем обратить внимание на первые два раздела и двигаться к следующему параграфу.

Зачем нужны системы контроля версий

Начнём с небольшого экскурса. Каждый программист в своей практике сталкивается с проблемой исправления собственного кода и сохранения стабильно работающего кода.

Это сделать просто, если у вас всего пара файлов. А если перед вами их десятки и сотни? Если каждый файл — это 100–1000 строк кода? А в команде работают ещё 10 человек? Что тогда?

На помощь приходит система контроля версий. Дальше для удобства будем использовать сокращение VCS (Version Control System). Это программа, созданная для упрощения разработки ИТ-продукта. VCS хранит множество версий одного и того же файла, позволяет возвращаться к ранним версиям документа и обратно, а также описывать суть внесённых изменений.

Системы контроля версий настолько прочно вошли в жизнь программиста, что это буквально третье, что он изучает после примера Hello World и выбранного языка программирования.

Но прежде чем перейти к их эволюции, нам нужен какой-то пример перед глазами. А то получится, как если бы мы описывали эволюцию инопланетян, которых вы никогда в глаза не видели: очень интересно, но в целом бесполезно.

Поэтому сейчас мы коротко рассмотрим сам Git — в чём его суть.

Суть Git

Центральная сущность Git — это репозиторий. То есть хранилище кода, в котором лежат файлы и папки проекта, плюс история изменений.

Каждый программист, который работает над проектом, может сохранить себе на компьютер копию репозитория для дальнейшей работы. Предположим, мы внесли изменения в три файла.

В одном из них переименовали функцию, которая умножает переданное число на 10. Не страшно, если вы не понимаете синтаксис, это не суть.

Название было слишком общим, а мы конкретизировали:

3.2

Git построчно сравнит для каждого файла в репозитории: как выглядел код до изменений и как он выглядит после. Эта разница называется дифф (англ. difference — разница).

Мы хотим опубликовать изменения только в одном файле из трёх. Для этого мы помечаем его как «готов к публикации» (staged). Затем мы его коммитим (commit). После — публикуем (push).

Но в этот момент репозиторий присылает нам ошибку: «История репозитория изменилась, и перед публикацией ваших изменений нужно синхронизироваться». Мы понимаем, что наш коллега успел залить новую версию файла.

Тогда мы скачиваем себе последнюю версию нашей кодовой базы из репозитория (pull) и видим, в чём именно причина конфликта:

3.2

Ага! Ему тоже не понравилось, как называлась функция, и он тоже решил её переименовать. Теперь нам нужно решить конфликт (resolve), то есть вручную выбрать финальную версию.

Тут нужно действовать с осторожностью: если мы выберем нашу версию, важно после решения конфликта проверить, где ещё в коде используется эта функция, и тоже её переименовать.

Потому что интерпретатор попытается использовать функцию multiply вместо multiply_by_ten — и словит ошибку выполнения.

А если выберем версию коллеги, то переименовать места использования функции в нашем коде.

После того как мы решили конфликт, мы снова идём по цепочке stage → commit → push. И на этот раз наши изменения улетают в репозиторий, их могут скачать себе другие разработчики.

Пара слов о сленге

Когда программисты хотят получить последнюю версию репозитория, это называется «спуллить».

Когда хотят зафиксировать изменения, говорят «закоммитить». А когда отправляют свой код в репозиторий — «запушить».

Сам репозиторий, кстати, — это «репа».

Поздравляем, теперь вы чуть ближе к тому, чтобы заговорить с ними на одном языке!

Коммит отражает дифф между состоянием репозитория до и после изменений. Мы можем двигаться по цепочке коммитов. Например, переключиться на два коммита назад, чтобы увидеть, как выглядел наш код раньше.

То есть Git показывает нам, какие файлы мы меняли в коде по сравнению с эталонной версией, и ругается, если мы изменили этот файл одновременно с другим разработчиком. А ещё даёт возможность изучать, как менялся проект. Этого уже оказалось достаточно, чтобы программисты по всему миру вздохнули с облегчением.

Мы можем ещё долго говорить про Git, но это не цель текущего параграфа. Чуть познакомились, суть уловили — и хватит пока. Но если вам любопытно — вот ссылка на документацию.

Теперь же посмотрим, как умные люди пришли к Git.

Как появились VCS

Одной из первых систем управления версиями была SCCS, её разработал Марк Рочкинд из компании Bell Labs в 1972 году. В это время Bell Labs вела активную разработку операционной системы Unix. Естественно, при таком объёме кода изменения нужно было как-то учитывать и синхронизировать.

В отсутствие систем контроля версий разработчики могли только сохранять каждую новую версию с изменениями в отдельный файл на своём компьютере. Система управления версиями позволила автоматизировать процесс хранения новых версий кода и дала возможность отката к любой из версий. Набор команд SCCS включён в стандарт операционной системы Unix. Первый публичный релиз системы состоялся в 1977 году.

Деннис Ритчи и Кен Томпсон — американские программисты, которые совместно создали язык программирования C и операционную систему Unix. Источник

SCCS была закрытой системой, доступной только программистам из Bell Labs. Поэтому в 1982 году немецкий программист Уолтер Тихи создал открытую систему контроля версий — RCS. Как и SCCS, она была написана на языке С.

Эта система уже приобретала черты современных систем контроля версий: она минимизировала объём хранимых данных, сжимая их, но всё ещё не предоставляла возможность коллективной работы. Чтобы внести изменения, нужно было заблокировать работу с файлом для других участников, что создавало массу неудобств.

Уолтер Тихи. Источник

К тому же RCS и SCCS были локальными системами контроля версий. Они располагались на одном компьютере, что осложняло работу группы программистов.

В 1986 году нидерландский программист Дик Грун, развивая предыдущее поколение систем контроля версий, создал CVS. Он добавил поддержку работы по сети. Это дало начало второму поколению систем контроля версий.

Появилась возможность хранить центральный репозиторий на сервере. Теперь клиенты получали доступ к сохранённым данным через локальную сеть или интернет. Данный класс систем получил название «централизованные системы контроля версий».

Пользователи могли вносить изменения в файлы, хранящиеся в общем, центральном репозитории, к которому подключались по сети. Но, как и при работе с предыдущими системами, для того чтобы внести изменения, нужно было заблокировать доступ к работе для других участников.

Впоследствии выяснилось, что, если соединение было ненадёжным, при работе с CVS возникали проблемы. В случае сбоя в момент передачи данных могло произойти рассогласование репозиториев на локальных компьютерах программистов.

Это могло привести, например, к потере результата работы кого-то из участников, если бы разработчик, который ранее не смог обновить проект, загрузил бы на сервер свои данные. В этом случае он обнулил бы наработки своих коллег.

Идея CVS получила развитие в системе SVN (Subversion), которую в 2000 году выпустила компания CollabNet Inc. В отличие от своего предшественника, SVN гарантировала, что либо изменения будут внесены, либо, при возникновении проблемы, полностью отменятся. SVN была ориентирована на проектную работу: одна запись изменений в репозиторий могла вносить изменения не для каждого файла по отдельности, а для сгруппированного блока файлов.

SVN подходила для небольших команд разработчиков, её можно было применять в корпорациях, где требовался только один, централизованный репозиторий. Но он ничем не мог помочь десяткам разработчиков, раскиданных по всему миру и непрерывно вносящих изменения в операционную систему Linux.

И тут мы готовы поговорить о том, как появился Git.

Краткая история Git

С 1995 года начали активно выходить коммерческие версии операционных систем на базе ядра Linux. В 1998 году ОС Linux стали использовать такие крупные компании, как Sun, IBM и Oracle.

Линус Торвальдс, создатель ядра Linux, был единственным человеком, который мог одобрять и вносить изменения. Его почтовый ящик был завален письмами разработчиков ОС со всего мира, и их число нарастало. Линус не всегда успевал своевременно ответить, и это тормозило разработку.

Линус Торвальдс. Источник

30 сентября 1998 года программист Ларри Маквой предложил новый подход к решению проблемы роста сообщества разработчиков и ограничения мейнтейнера по приёму изменений. В своём письме Линусу «Решение проблем роста» Маквой предлагал внедрить инструменты, позволяющие разделить часть работы Линуса между другими разработчиками.

Кто такой мейнтейнер

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

Мейнтейнер (от англ. maintain — поддерживать) занимается следующими - задачами:

  • Разрабатывает и улучшает код — вносит новые функции, исправляет баги.
  • Проводит ревью — оценивает изменения кода от желающих внести свой вклад в развитие проекта.
  • Управляет Issues — обрабатывает жалобы на баги, отвечает на вопросы и предложения сообщества.
  • Отвечает за версионирование и документацию — выпускает новые версии проекта, контролирует совместимость, поддерживает актуальность README-файла, руководств, API-документации.

Мейнтейнеры делают всё это добровольно и бесплатно. Впрочем, многие могут получать донаты от спонсоров — частных лиц и корпораций.

Мейнтейнеры важны, потому что без них проект придёт в упадок: предложения изменений будут висеть месяцами, баги — копиться, а сообщество — терять интерес к проекту.

С 1990 года Маквой грезил идеей системы, где не было бы единственного, главного сервера, на котором хранится главный репозиторий. Вместо этого он хотел создать систему управления версиями, где у каждого разработчика была бы локальная копия репозитория с историей изменений. В то время он работал в компании Sun. Часть его идей легла в основу первой распределённой системы контроля версий TeamWare, которая распространялась под платной лицензией.

После ухода в 1994 году из Sun Ларри Маквой потратил три года на развитие своих идей о децентрализованной системе контроля версий. А когда он снова столкнулся с обсуждением такой проблемы, как снижение скорости разработки Linux из-за трудностей с приёмом изменений в коде, предложил свою помощь.

Ларри Маквой. Источник

После очной встречи Линусу Торвальдсу и Ларри Маквою удалось разработать концепцию, которая могла бы облегчить проверку кода. Маквой оптимистично пообещал, что работа займёт у него полгода, но понадобилось ещё несколько лет, чтобы довести идею до ума.

Маквой основал компанию BitMover и нанял нескольких разработчиков. В мае 2000 года компания выпустила первую версию BitKeeper. Участники сообщества Linux начали тестировать BitKeeper с декабря 1999 года, а в 2002-м к ним присоединился и Линус. С этого момента основные разработчики стали использовать BitKeeper при разработке ядра Linux.

Ларри Маквой предоставил BitKeeper разработчикам ядра Linux бесплатно, но с некоторыми ограничениями:

  • не отключать сервис Open Logging, который отправлял журнал с изменениями разработчиков на сервер BitMover;
  • не использовать BitKeeper тем, кто разрабатывал аналогичное ПО для контроля версий;
  • получать разрешение BitMover, если разработчики хотели запустить BitKeeper вместе с другими подобными программами.

Сообщество Linux отреагировало неоднозначно. Многие считали, что непубличность исходных кодов нарушает принципы распространения свободного программного обеспечения. Маквой пошёл на уступки сообществу и создал зеркало, основанное на CVS. Однако информация в этом зеркале была неполной по сравнению с историей версий, хранимой в BitKeeper.

Линус смотрел на эту проблему прагматичнее, чем сообщество. BitKeeper облегчал его работу, снижал нагрузку на него и основных разработчиков ядра. Для него этого было достаточно, чтобы продолжать использовать BitKeeper.

Однако конфликт накалялся. Ограничения, наложенные на BitKeeper со стороны Ларри Маквоя, привели к тому, что в феврале 2005 года австралийский программист Эндрю Триджелл начал разработку бесплатного клиента BitKeeper. Триджелл твёрдо верил, что его действия принесут пользу как сообществу Linux, так и компании BitMover.

Эндрю Триджелл. Источник

Линус до последнего пробовал разрешить конфликт между Маквоем и Триджеллом, но это ему не удалось. Триджелл продолжал разработку, и, чтобы защитить бизнес-модель от распространения, Маквой решил отозвать лицензию на свободное использование BitKeeper. Намного позже, спустя десять лет, Ларри Маквою всё же пришлось сменить лицензию, и в 2016 году BitKeeper стал открытым продуктом.

Но 6 апреля 2005 года Линус объявил в рассылке, что ядро Linux прекращает работу с BitKeeper. А уже на следующий день он сделал рассылку рабочей версией Git и игрой. Её участникам предлагалось разобраться в особенностях работы Git на примере предложенного Линусом репозитория и написать программы для обмена информацией с сервером.

Линус написал прототип Git за пару дней. Он был прост и не содержал многих функций, необходимых для зрелой системы контроля версий. Но это был открытый программный продукт от лидера крупнейшего сообщества открытого исходного кода.

По словам Линуса, при написании Git он вдохновился примером системы контроля версий Monotone. Однако Monotone была медленной, а ядро Linux уже тогда занимало значительный объём кода. Поэтому Git хранил не промежуточные версии изменений документов, а итоговые файлы, что увеличивало скорость их выгрузки.

Линус зародил Git, но изначально не планировал поддерживать его в течение длительного времени. С самого начала он искал себе замену, чтобы вернуться к разработке ядра Linux. Спустя три месяца после появления рабочей версии Git, 26 июля 2005 года, Линус объявил о передаче роли мейнтейнера этого проекта Джунио Хамано, который ранее принимал участие в обсуждении архитектуры будущего сервиса и занимался его разработкой.

В том же конфликте с BitKeeper, так же стремительно и параллельно с Git, появилась система контроля версий Mercurial. Первая версия была выпущена в 2005 году. Mercurial, в отличие от большинства систем контроля версий, была написана на Python.

Вот таймлайн, чтобы вы не запутались:

3.2

От Git к GitHub

По-настоящему популярным Git сделало появление сервиса GitHub.

Основатель GitHub Крис Уонстрот говорил, что «GitHub — это как Википедия для программистов», и он был прав. GitHub — это просто хостинг репозиториев Git, ресурс, на котором легко делиться своим кодом.

Идеи GitHub зародились в сообществе языка программирования Ruby. В то время Ruby переживал бурный рост: в 2005 году появился веб-фреймворк Ruby on Rails, а с 2009 по 2012 год сообщество программистов, работающих на этом языке, выросло более чем в три раза.

До появления GitHub работа с Git требовала много ручных усилий: нужно было вручную настраивать удалённый сервер с репозиторием, раздавать участникам доступ, использовать командную строку для всех операций.

В целом ничего сложного: просто рутинно. А в октябре 2007 года программисты Том Престон-Вернер и Крис Уонстрот решили упростить этот процесс, чтобы репозиторий можно было развернуть через веб-интерфейс и буквально за пару кликов.

Они встретились в одном из баров Сан-Франциско и приступили к работе. Работали, как вспоминает Уонстрот по субботам, в свободное от другого проекта время.

Том разработал пользовательский интерфейс и использовал библиотеку Ruby под названием Grit для взаимодействия с репозиториями Git, а Крис создал сайт с помощью Ruby on Rails.

Как только основные функции были готовы, Крис Уонстрот сразу же внедрил GitHub в стартап, которым он занимался вместе с Филлипом Джеффри Хайеттом. Хайетт впечатлился и стал третьим сооснователем GitHub.

Сайт был открыт для публики 10 апреля 2008 года. К концу 2011 года в проекте было зарегистрировано уже более миллиона пользователей и создано более двух миллионов репозиториев. В марте 2017 года на сайте существовало более 58 миллионов репозиториев. Такой бурный рост проекта сначала привёл к крупным вложениям инвесторов, а затем — к покупке GitHub компанией Microsoft в 2018 году.

Уже в 2011 году появился крупный аналог GitHub — сервис GitLab, также написанный на языке Ruby. Туда в мае 2018 года переехал проект GNOME более чем с 400 проектами и 900 участниками. Как и GitHub, он существует до сих пор.

Собственные репозитории кода есть и в России:

  • «РТК-Феникс» («Ростелеком»).
  • «Сфера» (ИТ-холдинг T1).
  • GitVerse (Сбербанк).
  • GitFlic («РеСолют»).
  • Библиотека ИТ-решений с открытым кодом Mos.Hub (Правительство Москвы).

Но они уступают по популярности GitHub и GitLab. Впрочем, кто знает, как повернётся история в будущем.

C VCS и Git разобрались! Продолжим рассказ о разработке: в следующем параграфе узнаем, что такое грязный и чистый код и при чём тут спагетти.


Чтобы добавить в заметки выделенный текст, нажмите Ctrl + E
Предыдущий параграф4.2. Как устроены процессы в современном ИТ
Следующий параграф4.4. Что такое грязный код