Часто разработчики трудятся в команде над одним проектом, а значит, сразу несколько человек могут изменять один файл одновременно. Чтобы избежать путаницы, в таких случаях используют систему контроля версий, которая позволяет хранить историю изменений проекта и при необходимости помогает вернуться к предыдущей версии.
Версионирование
Чтобы лучше понять проблему версионирования, рассмотрим пример дизайнера, который закончил работать над проектом и отправил финальную версию заказчику. У дизайнера есть папка, в которой хранится финальная версия проекта:
source/
barbershop_index_final.psd
Всё хорошо, дизайнер закончил работу, но заказчик прислал в ответ правки. Чтобы была возможность вернуться к старой версии проекта, дизайнер создал новый файл barbershop_index_final_2.psd
, внёс изменения и отправил заказчику:
source/
barbershop_index_final.psd
barbershop_index_final_2.psd
Этим всё не ограничилось, в итоге структура проекта разрослась и стала выглядеть так:
source/
barbershop_index_final.psd
barbershop_index_final_2.psd
…
barbershop_index_final_19.psd
…
barbershop_index_latest_final.psd
barbershop_index_latest_final_Final.psd
Вероятно, многие уже сталкивались с подобным, например, при написании курсовых работ во время учёбы. В профессиональной разработке создавать новые файлы для версионирования — плохая практика. Обычно у разработчиков в папке проекта хранится множество файлов. Также над одним проектом может работать несколько человек. Если каждый разработчик для версионирования будет создавать новый файл, немного изменяя название предыдущей версии, то в скором времени в проекте начнётся хаос и никто не будет понимать, какие файлы нужно открывать.
Git
Для решения проблемы с сохранением новой версии файлов удобно использовать системы контроля версий. Одна из самых популярных — Git. Работу Git можно сравнить с процессом сохранения и загрузки в компьютерных играх:
- если впереди ждёт тяжёлое сражение, то перед этим лучше заранее сохраниться;
- чтобы это сделать, нужно выполнить специальную команду;
- после чего сохранение попадает в специальную папку и содержит состояние игры;
- теперь при необходимости всегда есть возможность вернуться к предыдущей версии игры.
Папка с данными игры могла бы выглядеть так:
SomeGame/
| - saves
| | - save001.sav
| | - save002.sav
| | …
| | папка с сохранениями
|
| - game.exe
| ...файлы игры
Файлы, необходимые для работы приложения, хранятся в рабочей области. В папке saves
хранится история всех сохранений игры. Git сохраняет код вашего проекта по такому же принципу: сохранения попадают в специальную скрытую папку, а рабочей областью является содержимое корневой папки.
Основные понятия
Список терминов, которые будут вам полезны.
Репозиторий
Проект, в котором была инициализирована система Git, называется репозиторием. При инициализации в проект добавляется скрытая папка .git
. Репозиторий хранит все рабочие файлы и историю их изменений.
Рабочая область и хранилище
barbershop/
| - .git
| | - bea0f8e
| | - hb-427307464A
| | Хранилище
|
| - css
| - index.html
| Рабочая область
Корневая папка проекта — это рабочая область. В ней находятся все файлы и папки, необходимые для его работы.
Хранилище — это содержимое скрытой папки .git
. В этой папке хранятся все версии рабочей области и служебная информация. Этим версиям система автоматически даёт название, состоящее из букв и цифр. В примере выше — это bea0f8e
и d516600
. Не стоит проводить манипуляции с папкой .git
вручную. Вся работа с системой производится командами через специальные приложения или консоль.
Коммит
Точно так же, как и в игре, в системе контроля версий Git можно сохранить текущее состояние проекта. Для этого есть специальная команда — commit
. Она делает так, что новая версия проекта сохраняется и добавляется в хранилище. В файле с сохранением отображаются: все изменения, которые происходили в рабочей области, автор изменений и краткий комментарий, описывающий суть изменений. Каждый коммит хранит полное состояние рабочей области, её папок и файлов проекта.
В итоге проект работает так:
- Репозиторий хранит все версии проекта. В случае передачи этого проекта другому человеку, он увидит всё, что с ним происходило до этого.
- Ничего не теряется и не удаляется бесследно. При удалении файла в новой версии добавляется запись о том, что файл был удалён.
- Всегда можно вернуться к любой из версий проекта, загрузив её из хранилища в рабочую область.
Система контроля версий Git
Git — это распределённая и децентрализованная система управления версиями файлов. Децентрализованная система означает, что у каждого разработчика есть личный репозиторий проекта с полным набором всех версий. А все необходимые для работы файлы находятся на компьютере. При этом постоянное подключение к сети не требуется, поэтому система работает быстро. При командной разработке нужна синхронизация репозиториев, так как проект — один и его состояние должно быть у всех одинаковым.
Работа в команде
Как синхронизовать данные репозиториев между разработчиками? Изначально Git репозитории сами могут синхронизироваться от пользователя к пользователю. Дополнительные программы для этого не нужны. Есть специальные команды в консоли, позволяющие передавать данные из одного репозитория в другой.
Этот способ сложный и редко используется. Чаще всего разработчики синхронизируют локальный репозиторий с удалённым. Удалённый репозиторий — это тот же репозиторий, только его данные находятся в облаке.
Этапы синхронизации
Как сделать так, чтобы разработчик смог передать актуальную версию проекта коллеге?
Для взаимодействия с системой Git в консоль вводятся специальные команды. Не пугайтесь, работу с консолью можно будет заменить на работу с одной из программ, о которых расскажем ниже. Но чтобы лучше понимать суть, придётся запомнить несколько команд. Все они начинаются с ключевого слова git
. Для синхронизации есть две основных команды: pull
(англ. «тянуть») и push
(англ. «толкать»).
Pull
Если работа над проектом ведётся в команде, то перед тем как начать писать код, нужно получить последнюю версию проекта. Для этого нужно выполнить команду pull
. Так мы забираем все изменения, которые были совершены со времени последней синхронизации с удалённым репозиторием. Теперь они у нас в репозитории на локальном компьютере.
Push
Чтобы отправить коллегам последнюю версию проекта выполняем команду push
. Если в удалённом репозитории с момента последней синхронизации не было никаких изменений, то все сохранённые изменения успешно загрузятся в облако, и коллеги получат последнюю версию проекта, выполнив команду pull
. Если же были изменения, то Git попросит вас перед отправкой подтянуть последние версии, сделав pull
.
Типовой рабочий процесс с использованием Git
Разберём типовой процесс разработки сайта в команде. Представим, что Игорь и Алиса — разработчики на одном проекте. Игорь начал верстать проект и сделал первые коммиты, в которых зафиксировал изменения в файле index.html
. Для схематичности названия коммитов будут простые: B1 и B2.
После того как Игорь сделал два коммита, он захотел отправить свои изменения в удалённый репозиторий. Чтобы их передать, Игорь выполнил команду git push
. После чего в облаке появилось две версии проекта. То есть Игорь отправил не только финальную версию проекта, но и все сохранённые изменения.
После пуша данные синхронизировались с удалённым репозиторием. Но как Алисе теперь получить изменения? Для этого она выполняет команду git pull
и получает все изменения из облака к себе на компьютер. Таким образом, состояние проекта у Игоря и Алисы синхронизировались, и они могут дальше продолжить работать над ним.
Параллельные изменения
Что произойдёт, если разработчики изменят одинаковый файл и сделают push
? Предположим, что Игорь и Алиса изменили файл index.html
, сделали коммит с изменениями и запушили его. Игорь оказался быстрее Алисы и сделал push
первым.
В этом случае Git сообщит Алисе, что нельзя пушить свои изменения, потому что она не делала pull
. Дело в том, что после того как Игорь синхронизировался с удалённым репозиторием, версия проекта Алисы стала отличаться от той, что находится на удалённом репозитории, и Git это видит. Система сообщает, что перед тем, как выполнить команду push
, нужно выполнить pull
, чтобы забрать изменения. Алиса делает pull
и ей вновь приходит уведомление от Git. В этот раз он сообщает Алисе о том, что произошёл конфликт.
Конфликт
Дело в том, что Игорь и Алиса изменили одинаковый файл и теперь Алисе предстоит решить конфликт.
Существуют два вида конфликтов:
- Автоматически разрешаемый конфликт.
- Конфликт, который нужно разрешить вручную.
Ниже рассмотрим оба варианта.
Слияние
Допустим, что на третьей строке Игорь добавил в проект шапку, а на четвёртой Алиса добавила футер.
Git видит, что произведённые изменения не затрагивают друг друга. Он сам объединит две версии проектов в одну, совершив слияние. После этого Алиса спокойно синхронизируется с удалённым репозиторием, отправив новую версию проекта.
Во время слияния Git не знает, в каком порядке расположить коммит В3 Игоря и коммит В4 Алисы, из-за которых случился конфликт. Поэтому Git разрешает существовать нескольким версиям проекта одновременно. Как раз для этого и нужен следующий коммит В5, в котором происходит слияние предыдущих параллельных версий. После того как Алиса запушит изменения, она отправляет все версии проектов на удалённый репозиторий. В следующий раз, когда Игорь сделает pull
, он получит полную историю со слиянием конфликта.
Допустим, что Игорь и Алиса продолжили работать над проектом, но в этот раз изменили одинаковую строку в файле index.html
. Вновь Игорь оказался быстрее и первым синхронизировал свои изменения с удалённым репозиторием. Алиса сделала pull
и получила сообщение о конфликте.
В таком случае Git не знает чья версия проекта правильная и поступает очень просто. Он изменяет файл index.html
, добавляя в него изменения и Игоря и Алисы. После этого предупреждает Алису о конфликте и просит выбрать правильный вариант.
Версии проектов разделяются строками второй, четвёртой и шестой. Их нужно удалить и оставить правильный вариант заголовка. После того как Алиса это сделает, она сможет закоммитить изменения и запушить их на удалённый репозиторий. Игорь же при следующей синхронизации с облаком получит тот вариант заголовка, который выбрала Алиса.
Окружение Git
Git — удобная система. Плюсом является то, что вокруг него создано множество сервисов, которые позволяют сделать работу с ним удобнее. Расскажем о тех, что будут вам полезны в начале работы.
GitHub
GitHub — это сайт, сервис и то самое облако, в котором можно хранить удалённые репозитории и через которое коллеги могут синхронизировать свои версии проектов. Как зарегистрироваться, мы рассказали в этой статье.
GUI
Облегчить работу с Git и GitHub могут специальные программы. Такие программы в удобной форме показывают изменения в коде, список коммитов и обладают другими удобными возможностями. Обычно в подобных программах есть возможность выполнять стандартные Git команды: pull
, push
, commit
и прочие — просто нажав на кнопку.
Следующая глава
Глава 2. Словарь терминов для Git и GitHub
Собрали основные термины, использующиеся в Git и GitHub.