Git для начинающих. Часть 1. Что такое системы контроля версий?
Система контроля версий (Version Control System, VCS) представляет собой программное обеспечение, которое позволяет отслеживать изменения в документах, при необходимости производить их откат, определять, кто и когда внес исправления и т.п. В статье рассмотрены виды VCS, принципы их работы, а также приведены примеры программных продуктов.
Что такое система контроля версий?
Наверное, всем знакома ситуация, когда при работе над проектом, возникает необходимость внести изменения, но при этом нужно сохранить работоспособный вариант, в таком случае, как правило, создается новая папка, название которой скорее всего будет “Новая папка” с дополнением в виде даты или небольшой пометки, в нее копируется рабочая версия проекта и уже с ним производится работа. Со временем количество таких папок может значительно возрасти, что создает трудности в вопросе отката на предыдущие версии, отслеживании изменений и т.п. Эта ситуация значительно ухудшается, когда над проектом работает несколько человек.
Для решения таких проблем как раз и используется система контроля версий, она позволяет комфортно работать над проектом как индивидуально, так в коллективе. VCS отслеживает изменения в файлах, предоставляет возможности для создания новых и слияние существующих ветвей проекта, производит контроль доступа пользователей к проекту, позволяет откатывать исправления и определять кто, когда и какие изменения вносил в проект. Основным понятием VCS является репозиторий (repository) – специальное хранилище файлов и папок проекта, изменения в которых отслеживаются. В распоряжении разработчика имеется так называемая “рабочая копия” (working copy) проекта, с которой он непосредственно работает. Рабочую копию необходимо периодически синхронизировать с репозиторием, эта операция предполагает отправку в него изменений, которые пользователь внес в свою рабочую копию (такая операция называется commit) и актуализацию рабочей копии, в процессе которой к пользователю загружается последняя версия из репозитория (этот процесс носит название update).
Централизованные и распределенные системы контроля версий
Системы контроля версий можно разделить на две группы: распределенные и централизованные.
Централизованные системы контроля версий
Централизованные системы контроля версий представляют собой приложения типа клиент-сервер, когда репозиторий проекта существует в единственном экземпляре и хранится на сервере. Доступ к нему осуществлялся через специальное клиентское приложение. В качестве примеров таких программных продуктов можно привести CVS, Subversion.
CVS (Concurrent Versions System, Система одновременных версий) одна из первых систем получивших широкое распространение среди разработчиков, она возникла в конце 80-х годов прошлого века. В настоящее время этот продукт не развивается, это в первую очередь связано с рядом ключевых недостатков, таких как невозможность переименования файлов, неэффективное их хранение, практически полное отсутствие контроля целостности.
Subversion (SVN) – система контроля версий, созданная на замену CVS. SVN была разработана в 2004 году и до сих пор используется. Несмотря на многие преимущества по сравнению с CVS у SVN все-таки есть недостатки, такие как проблемы с переименованием, невозможность удаления данных из хранилища, проблемы в операции слияния ветвей и т.д. В целом SVN был (и остается) значительным шагом вперед по сравнению с CVS.
Распределенные системы контроля версий
Распределенные системы контроля версий (Distributed Version Control System, DVCS) позволяют хранить репозиторий (его копию) у каждого разработчика, работающего с данной системой. При этом можно выделить центральный репозиторий (условно), в который будут отправляться изменения из локальных и, с ним же эти локальные репозитории будут синхронизироваться. При работе с такой системой, пользователи периодически синхронизируют свои локальные репозитории с центральным и работают непосредственно со своей локальной копией. После внесения достаточного количества изменений в локальную копию они (изменения) отправляются на сервер. При этом сервер, чаще всего, выбирается условно, т.к. в большинстве DVCS нет такого понятия как “выделенный сервер с центральным репозиторием”.
Большое преимущество такого подхода заключается в автономии разработчика при работе над проектом, гибкости общей системы и повышение надежности, благодаря тому, что каждый разработчик имеет локальную копию центрального репозитория. Две наиболее известные DVCS – это Git и Mercurial.
Начнем с Mercurial, эта система представляет собой свободную DVCS, которая построена таким образом, что в ней отсутствует понятие центрального репозитория, для работы с этой VCS используется (как правило) консольная утилита hg. Mercurial обладает всеми возможностями системы контроля версий, такими как ветвление, слияние, синхронизация с другими репозиториями. Данный проект используют и поддерживают большое количество крупных разработчиков, среди них Mozilla, OpenOffice, OpenJDK и многие другие. Сам продукт написан на языке Python и доступен на большинстве современных операционных систем (Windows, Mac OS, Linux), также существует значительное количество утилит с графическим интерфейсом для работы с Mercurial. Основным конкурентом Mercurial на рынке распределенных систем контроля версий является Git, который, на сегодняшний день, выиграл гонку за лидерство.
Git – распределенная система контроля версий, разработанная Линусом Торвальдсем для работы над ядром операционной системы Linux. Среди крупных проектов, в рамках которых используется git, можно выделить ядро Linux, Qt, Android. Git свободен и распространяется под лицензией GNU GPL 2 и, также как Mercurial, доступен практически на всех операционных системах. По своим базовым возможностям git схож с Mercurial (и другими DVCS), но благодаря ряду достоинств (высокая скорость работы, возможность интеграции с другими VCS, удобный интерфейс) и очень активному сообществу, сформировавшемуся вокруг этой системы, git вышел в лидеры рынка распределенных систем контроля версий. Необходимо отметить, что несмотря на большую популярность таких систем как git, крупные корпорации, подобные Google, используют свои VCS.
Это была вводная лекция по системам контроля версий. В дальнейшем, все изложение будет касаться только git.
Что такое контроль версий?
Каким образом контроль версий содействует успеху продуктивных команд разработчиков и DevOps
Контроль версий, также известный как управление исходным кодом, — это практика отслеживания изменений программного кода и управления ими. Системы контроля версий — это программные инструменты, помогающие командам разработчиков управлять изменениями в исходном коде с течением времени. В свете усложнения сред разработки они помогают командам разработчиков работать быстрее и эффективнее. Системы контроля версий наиболее полезны командам DevOps, поскольку помогают сократить время разработки и увеличить количество успешных развертываний.
Программное обеспечение контроля версий отслеживает все вносимые в код изменения в специальной базе данных. При обнаружении ошибки разработчики могут вернуться назад и выполнить сравнение с более ранними версиями кода для исправления ошибок, сводя к минимуму проблемы для всех участников команды.
Практически во всех программных проектах исходный код является сокровищем: это ценный ресурс, который необходимо беречь. Для большинства команд разработчиков программного обеспечения исходный код — это репозиторий бесценных знаний и понимания проблемной области, которые они скрупулезно собирали и совершенствовали. Контроль версий защищает исходный код от катастрофических сбоев, от случайных ухудшений, вызванных человеческим фактором, а также от непредвиденных последствий.
Разработчики программного обеспечения, работающие в командах, постоянно пишут новый исходный код и изменяют существующий. Код проекта, приложения или программного компонента обычно организован в виде структуры папок или «дерева файлов». Один разработчик в команде может работать над новой возможностью, а другой в это же время изменять код для исправления несвязанной ошибки, т. е. каждый разработчик может вносить свои изменения в несколько частей дерева файлов.
Контроль версий помогает командам решать подобные проблемы путем отслеживания каждого изменения, внесенного каждым участником, и предотвращать возникновение конфликтов при параллельной работе. Изменения, внесенные в одну часть программного обеспечения, могут быть не совместимы с изменениями, внесенными другим разработчиком, работавшим параллельно. Такая проблема должна быть обнаружена и решена согласно регламенту, не создавая препятствий для работы остальной части команды. Кроме того, во время разработки программного обеспечения любое изменение может само по себе привести к появлению новых ошибок, и новому ПО нельзя доверять до тех пор, пока оно не пройдет тестирование. Вот почему процессы тестирования и разработки идут рука об руку, пока новая версия не будет готова.
Хорошее программное обеспечение для управления версиями поддерживает предпочтительный рабочий процесс разработчика, не навязывая определенный способ работы. В идеале оно также работает на любой платформе и не принуждает разработчика использовать определенную операционную систему или цепочку инструментов. Хорошие системы управления версиями обеспечивают плавный и непрерывный процесс внесения изменений в код и не прибегают к громоздкому и неудобному механизму блокировки файлов, который дает зеленый свет одному разработчику, но при этом блокирует работу других.
Группы разработчиков программного обеспечения, не использующие какую-либо форму управления версиями, часто сталкиваются с такими проблемами, как незнание об изменениях, выполненных для пользователей, или создание в двух несвязанных частях работы изменений, которые оказываются несовместимыми и которые затем приходится скрупулезно распутывать и перерабатывать. Если вы как разработчик ранее никогда не применяли управление версиями, возможно, вы указывали версии своих файлов, добавляя суффиксы типа «финальный» или «последний», а позже появлялась новая финальная версия. Возможно, вы использовали комментирование блоков кода, когда хотели отключить определенные возможности, не удаляя их, так как опасались, что этот код может понадобиться позже. Решением всех подобных проблем является управление версиями.
Программное обеспечение для управления версиями является неотъемлемой частью повседневной профессиональной практики современной команды разработчиков программного обеспечения. Отдельные разработчики ПО, привыкшие работать в команде с эффективной системой управления версиями, обычно признают невероятную пользу управления версиями даже при работе над небольшими сольными проектами. Привыкнув к мощным преимуществам систем контроля версий, многие разработчики не представляют как работать без них даже в проектах, не связанных с разработкой ПО.
Преимущества систем контроля версий
Программное обеспечение контроля версий рекомендуется для продуктивных команд разработчиков и команд DevOps. Управление версиями помогает отдельным разработчикам работать быстрее, а командам по разработке ПО — сохранять эффективность и гибкость по мере увеличения числа разработчиков.
За последние несколько десятилетий системы контроля версий (Version Control Systems, VCS) стали гораздо более совершенными, причем некоторым это удалось лучше других. Системы VCS иногда называют инструментами SCM (управления исходным кодом) или RCS (системой управления редакциями). Один из наиболее популярных на сегодняшний день инструментов VCS называется Git. Git относится к категории распределенных систем контроля версий, известных как DVCS (эта тема будет рассмотрена подробнее чуть позже). Git, как и многие другие популярные и доступные на сегодняшний день системы VCS, распространяется бесплатно и имеет открытый исходный код. Независимо от того, какую систему контроля версий вы используете и как она называется, основные ее преимущества заключаются в следующем.
Полная история изменений каждого файла за длительный период. Это касается всех изменений, внесенных огромным количеством людей за долгие годы. Изменением считается создание и удаление файлов, а также редактирование их содержимого. Различные инструменты VCS отличаются тем, насколько хорошо они обрабатывают операции переименования и перемещения файлов. В историю также должны входить сведения об авторе, дата и комментарий с описанием цели каждого изменения. Наличие полной истории позволяет возвращаться к предыдущим версиям, чтобы проводить анализ основных причин возникновения ошибок и устранять проблемы в старых версиях программного обеспечения. Если над программным обеспечением ведется активная работа, то «старой версией» можно считать почти весь код этого ПО.
Ветвление и слияние. Эта возможность полезна не только при одновременной работе участников команды: отдельные люди также могут извлечь из нее пользу и работать над несколькими независимыми направлениями. Создание «веток» в инструментах VCS позволяет иметь несколько независимых друг от друга направлений разработки, а также выполнять их слияние, чтобы разработчики могли проверить, что изменения, внесенные в каждую из веток, не конфликтуют друг с другом. Многие команды разработчиков программного обеспечения создают отдельные ветки для каждой функциональной возможности, для каждого релиза либо и для того, и для другого. Наличие множества различных рабочих процессов позволяет командам выбирать подходящий для них способ использования ветвления и слияния в VCS.
Отслеживаемость. Возможность отслеживать каждое изменение, внесенное в программное обеспечение, и связывать его с ПО для управления проектами и отслеживания ошибок, например Jira, а также оставлять к каждому изменению комментарий с описанием цели и назначения изменения может помочь не только при анализе основных причин возникновения ошибок, но и при проведении другого анализа. История с комментариями во время чтения кода помогает понять, что этот код делает и почему действие реализовано именно таким образом. Благодаря этому разработчики могут вносить корректные и совместимые изменения в соответствии с долгосрочным планом разработки системы. Это особенно важно для эффективной работы с унаследованным кодом, поскольку дает разработчикам возможность точнее оценить объем дальнейшей работы.
Разрабатывать программное обеспечение можно и без управления версиями, но такой подход подвергает проект огромному риску, и ни одна профессиональная команда не порекомендует применять его. Таким образом, вопрос заключается не в том, использовать ли управление версиями, а в том, какую систему управления версиями выбрать.
Среди множества существующих систем управления версиями мы сосредоточимся на одной: системе Git. Подробнее о других типах программного обеспечения для контроля версий.
Готовы изучить Git?
Ознакомьтесь с этим интерактивным обучающим руководством.
Основы VCS на примере Git
https://git-scm.com/ – тут крутые entry видео, документация и прочее.
Помимо возможности просмотра предыдущих версий файлов (не только текстовых) VCS позволяют:
Если более детально:
Исходя из плюсов можно определенно сказать, что VCS имеет смысл использовать даже если ты единственный программист.
Git
Файлы в Git могут находиться в стадиях:
Каждый Git проект имеет три секции:
Директория Git (Git directory) – по сути база твоего проекта. Тут сохраняются все snapshot проекта. Git в результате commit сохраняет в Git директории не просто разницу между предыдущим состоянием и текущим (diff), а полностью файлы. (commited files)
Commit представляет собой по сути snapshot файлов, которые были поставлены на commit. В комментариях к commit нужно указывать нужную информацию о причинах commit, например номера тикетов или ссылок на документы, rfc, переписки и прочее. Если коммит длинный – то комментарий к commit не нужно указывать непосредственно в cli, а просто ввести commit. Тогда откроется текстовый редактор, в нем первой строкой краткое описание, а далее подробный текст изменения. Есть даже сайт посвященный стилю commit https://commit.style/.
Commit идентифицируется ID в виде HASH, расчитанного по алгоритму SHA1. Hash сделан чтобы можно было сравнивать что данные которые ты внес соответствуют данным, которые сохранены т.к. любое изменение данных приводит к изменению hash этих данных. Git ругнеться если hash от данных не будет соответсвовать hash commit. Изменение может быть безобидным – сетевая проблема, проблема с диском, но и намеренным внедрением (mitm). При использовании в командах можно указывать только первые символы hash, а не весь hash, git найдет нужный commit по вхождению в hash (обычно достаточно всего первых 4 символов).
HEAD – индикатор текущего commit для текущего branch в репозитории (по сути за ним скрывается ID текущего commit), что-то типо закладки для отслеживания местоположения (используется в командах git reset, diff, branch, status).
Github
Github – бесплатный web-based сервер репозиториев на основе git. Предоставляет доп. плюшки в виде wiki, bug tracking, task management. Бесплатен только если проект (репозиторий) публичен, если нужен приватный репозиторий – заплати денег, хотя и не много. GitHub является крупнейшим веб-сервисом для хостинга IT-проектов и их совместной разработки. Основан на системе контроля версий Git и разработан на Ruby on Rails и Erlang. Проекты можно выгружать через git clone или даже в zip. Есть аналоги – BitBucket, Gitlab. Github куплен microsoft.
Базовая работа и команды
Указание username и почты (чтобы размечать тебя в commit в публичных репозиториях). В git config можно указать даже pgp/gpg ключ для подписи коммитов.
Переходим в директорию с проектом (тут будут файлы самого проекта и файлы, которые хранят изменения в файлах проекта)
Добавляем элемент или всю папку в hold на commit (переводим модифицированный файл в commit, добавляем новый файл в tracked и переводим его в commit – проставляем на файлы staged статус)
Убираем элемент или всю папку из staging area
Можно удалять и перемешать файлы в репозитории – говорим Git не отслеживать файл, удаляем/перемещаем его из Git directory. Файл уходит в staged, поэтому нужно сделать commit для завершения удаления/перемещения.
GITIGNORE
Полезно часто просто игнорировать все файлы кроме python-скриптов (или исполняемых файлов другого языка, который нужен).
COMMIT
Делаем commit – создаем snapshot с данными.
-m – добавляем коммент прямо из консоли. По style так писать нежелательно, но в целом так делают даже в кратком review на сайте Git 🙂 Как по мне если изменение минорное – очень полезная вещь.
-a – автоматически добавляет все файлы, которые отслеживаются (находяться в репозитории Git) на commit (нет необходимости делать git add, если только это не новый файл)
Перезаписть последний commit новым (удаление старого commit, все что в текущий момент в staging area будет закоммичено). Можно использовать не только когда сменились данные, но и когда нужно только поправить комментарий. Время commit будет равно времени изначального commit, а не времени amend, все остальные данные будут перезаписаны (коммент, id). Крайне нежелательно использовать для публичных commit, вместо этого нужно использовать revert.
Восстановить или откатить
Чтобы восстановить конкретный файл из последнего commit, новый файл еще не в staging area (после изменения или удаления ДО применения add/rm на новую версию файла)
Чтобы восстановить конкретный файл из последнего commit, новый файл уже в staging area (после изменения или удаления И применения add/rm на новую версию файла)
Откат текущего состояния на определенный commit делается через checkout.
Откат изменений, внесенных определенным commit делается через revert. Revert делает новый коммит, который отменяет все изменения, сделанные в указанном коммите (HEAD – в последнем коммите или commit_hash_id, можно указать не полностью) – т.е. если строка была добавлена, то в результате revert эта строка будет удалена. Таким образом можно посмотреть что было не так в “плохом” commit после отката.
Сравнение и Логи
Статус файлов, в каком состоянии они находятся
Логи
Опции:
-p – показать что поменялось в файлах между текущим и предыдущим commit,
-2 – показать только два последних commit,
–decorate – добавление информации о branch, в какой branch сейчас смотрит HEAD или проще говоря для какого branch в логах показаны commit
–stat – просмотр какие файлы поменялись
origin/master – можно указать удаленный repo и branch, для которого будут показаны логи
BRANCHING AND MERGING
Branch – указатель на определенный commit. Каждый branch указывает на отдельную линию разработки в проекте. Master – branch по умолчанию, создаваемый при инициализации Git. Принято его считать и использовать как основную, production или known-good, ветку проекта. При изменениях проекта, например добавления новой фичи делается еще один branch, на основе которого происходит работа, без необходимости изменения production ветки. Branch’и позволяют очень легко экспериментировать с новыми идеями в проекте и используются повседневно. Основной профит branch состоит в том, что они не хранят и не копируют данные, они просто указывают на определенный commit.
Показать все branch в репозитории, звездой помечается в каком ты сейчас находишься
Создаем branch на основе текущего branch (не обязательно master)
Для переключения между branch’ами нужно использовать checkout, в результате команды 1) working tree изменяется с предыдущего branch на последний новый, т.е. меняются файлы в соответствии с branch 2) HEAD указывает на последний commit в новом branch, а не в старом 3) меняется commit history т.к. она ведется для branch
Можно создать branch и сразу переключиться в него через checkout
Удаление branch (ругнеться если есть неза’merge’нные в master изменения в удаляемом branch)
Соединяем данные и history log branch с текущим branch. Git использует два алгоритма для merge:
Сбросить процедуру merge, если конфликты слишком сложные, чтобы их быстро разрешить. Данные в working tree будут восстановлены на основе текущего branch, не включая конфликты. При использовании –hard все незакомиченные изменения в текущем branch будут сброшены!
КОЛЛАБОРАЦИЯ
Обычный пользователь, ответственный за какую то ветку (branch)
Админ после этого собирает к себе на комп (git pull) и объединяет изменения последних коммитов в репозитории (git merge), с вопросами какие изменения сохранить в случае наличия конфликтов и прочим
УДАЛЕННЫЕ РЕПОЗИТОРИИ (github)
git clone – копируем удаленный репозиторий для локального использования (используется вместо git init, остальные команды все аналогичные, до тех пор пока не понадобится обновить удаленный репозиторий – там нужно добавить в обычной последовательности действий push). Репозиторий будет скопирован и будет иметь имя по умолчанию origin.
Вместо создания клона можно создать связь с удаленным репозиторием. Можно использовать HTTP (обычно только RO доступ к repo), HTTPS, SSH, Git. Связь автоматически создается при использовании git clone.
Просмотреть все связи с удаленными репозиториями (-v показывает URL и какой будет использовать для fetch from repo и push to repo, обычно один и тот же)
git pull – получаем изменения из repo. Обновление данных локального репозитория на основе удаленного. Git автоматически это не делает. Например, когда на работу пришел и нужно получить изменения, запушенные в репозиторий из дома. Команда которая делает одновременно fetch из remote repo (url shortcut) и merge на основе удаленного repo. По умолчанию branch определяется на основе текущего branch, но можно поменять. Перед git pull можно посмотреть что изменилось в repo с помощью команды git diff HEAD..origin
git merge – обновляем данные нашего репозитория на основе данных удаленного.
Fork для изменения без прав + pull request для запроса на редактирование основной ветки





