Skip to main content

Введение

О системе контроля версий

Если мы пишем простое приложение, то можно попробовать решить проблему с наскока: просто сесть и написать за раз то, что нам нужно. Но вдруг у нас не получилось с первого раза? Тогда мы будем вынуждены возвращаться к нашему исходному коду снова и снова.

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

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

А вдруг то, что мы посчитали работающим в итоге окажется не работающим? Тогда мы будем вынуждены писать всё заново. Хорошо бы было сохранять все стабильные по нашему мнению программы, вернее, версии. Программа у нас всё-таки одна, а вот её версий-вариантов может быть очень много.

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

Тогда нам придётся создать таблицу Excel, и в ней для каждой версии добавлять строку в которой будут указаны все нужные нам данные, в том числе, где именно лежит сохранённая нами версия. Такую систему очень неудобно поддерживать. Гораздо проще один раз написать программу, которая будет управлять версиями за нас. Иными словами, мы переложим ответственность за всю рутину на программу. Такие программы называют системы контроля версий (Version Control System/VCS).

Виды систем контроля версий

Системы контроля версий бывают очень разными, но всех их можно разделить на три принципиально различных по способу хранения группы. Первую мы уже описали - это полная система контроля версий(Full CVS). В ней мы делаем копию всех файлов и сохраняем. У такого подхода есть один очень серьёзный недостаток. Если у нас большой проект, то изменение одного файла повлечёт за собой необходимость сохранить все остальные. Программистам такой подход никак не может подойти. Ведь каждая версия программы зачастую отличается от остальных несколькими строками в нескольких файлах. Причём основная проблема не в затрачиваемом пространстве, а во времени архивации, копирования, извлечения.

Чтобы как-то оптимизировать работу с версиями, мы можем сохранять только изменённые файлы. Такой подход называется разностным. Он очень полезен, например, при заражении вирусами. Но опять же при таком подходе мы копируем одни и те же данные много раз. Т.е. если файл очень большой, а мы поменяли в нём одну строчку, то весь файл копировать не рационально. Поэтому разработчики придумали третий тип систем контроля версий.

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

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

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

Совместное использование

Помимо сравнения версий программы при работе нескольких программистов есть и более тривиальные задачи. Допустим, что нам нужно для начала просто научиться обмениваться версиями, чтобы что-то сравнивать. Да, можно просто назначить ответственного, который будет по запросу сохранять себе новые версии программы и будет также по запросу выдавать все новые версии. Конечно же, проще поднять сервер, который будет это всё делать. Такие системы контроля версий называют централизованными. Самые известные - это CVS, Subversion Perforce.

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

Здесь в игру вступают распределённые системы контроля версий (РСКВ). В РСКВ (таких как Git, Mercurial, Bazaar или Darcs) клиенты не просто скачивают снимок всех файлов (состояние файлов на определённый момент времени) они полностью копируют репозиторий. Репозиторием в системах контроля версий называется то место, где мы храним все версии программы.

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

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

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

В этом разделе приведена копия главы из официальной документации git.

Иногда я буду использовать тексты и иллюстрации оттуда.

Как и многие вещи в жизни, Git начинался с капелькой творческого хаоса и бурных споров.

Ядро Linux - это достаточно большой проект с открытым исходным кодом. Большую часть времени разработки ядра Linux (1991–2002 гг.) изменения передавались между разработчиками в виде патчей и архивов. В 2002 году проект ядра Linux начал использовать проприетарную децентрализованную СКВ BitKeeper.

В 2005 году отношения между сообществом разработчиков ядра Linux и коммерческой компанией, которая разрабатывала BitKeeper, прекратились, и бесплатное использование утилиты стало невозможным. Это сподвигло сообщество разработчиков ядра Linux (а в частности Линуса Торвальдса, создателя Linux) разработать свою собственную утилиту, учитывая уроки, полученные при работе с BitKeeper. Некоторыми целями, которые преследовала новая система, были:

  • Скорость

  • Простая архитектура

  • Хорошая поддержка нелинейной разработки (тысячи параллельных веток)

  • Полная децентрализация

  • Возможность эффективного управления большими проектами, такими как ядро Linux (скорость работы и разумное использование дискового пространства)

С момента своего появления в 2005 году git развился в простую в использовании систему, сохранив при этом свои изначальные качества. Он удивительно быстр, эффективен в работе с большими проектами и имеет великолепную систему веток для нелинейной разработки (см. главу Ветвление в Git).

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

Забавно, но git можно перевести, как мерзавец. На самом деле он очень удобный и полезный.

Мерзавец

Версии программ в git называются коммитами(commit - зафиксировать). Каждый коммит представляет собой слепок файловой системы. Т.е. мы сохраняем не отдельные файлы, а всю файловую систему внутри папки.

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

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

Все рабочие файлы git складывает в папку .git в корне рабочей папки, иными словами, репозитория.

Состояния файлов

Каждому файлу внутри выбранной нами папки git присваивает своё состояние, их может быть всего три:

  1. Зафиксированное - никаких новых изменений в файле нет, при создании коммита git просто пробросит ссылку на последнее изменение этого файла. Таким изменением может быть и просто сохранение файла после добавления его в список индексации;
  2. Изменённое - файл изменён или просто создан, но пока что не добавлен в список индексации следующего коммита;
  3. Индексированное - изменения в файле будут учтены при создании нового коммита.

Рабочий процесс git

Хотя git очень мощный инструмент, работа с ним может быть сведена к трём основным этапам:

  1. Создаём и изменяем файлы нашей рабочей версии. Т.е. настоящие файлы в рабочей папке.
  2. Выбираем те изменённые файлы, которые нужно добавить в новый коммит.
  3. Создаём коммит.

Весь остальной функционал нужен уже для взаимодействия между коммитами.