ПРО GIT: Ветки (бранчи)
февраля 1, 2011 | Published in Development Processes, Управление Версиями | 6 Comments
Цикл статей ПРО GIT:
Введение
Ветки (бранчи)
В прошлой статье о системе управления версиями Git я как-то слишком сухо рассказал о том, что это такое и зачем все это необходимо, позабыв о тех людях, которые совсем не знакомы с таким технологическим процессом разработки как контроль версий. Именно из-за этого своего упущения я решил начать эту статью с так сказать теории о системах управления версиями.
1. Система Управления версиями (СУВ) — что это?
1.1. Прошлый опыт
Возможно название показалось вам сложным и даже напугало вас, однако СУВ -это достаточно простая вещь! Успокойтесь, расслабьтесь, сделайте глубокий вдох и больше никогда ничего не бойтесь!
Вспомните последний раз, когда вы работали в MS Word или Photoshop. Работая практически с любым редактором будь то текстовый, графический, музыкальный или видеоредактор вы всегда допускаете ошибки. Затем вы исправляете эти ошибки, а затем заметив, что ваши исправления неправильны, нажимаете «Undo», «Step back up» или как там оно у вас называется? Еще часто возникает необходимость отредактировать какой-либо текст или по заготовке отрисовать детальный дизайн сайта. Тогда, чтобы не портить заготовку, вы создаете ее копию и вносите изменения в одну из копий, а если что-то пошло не так, то вы либо используете те же «откаты», либо просто удаляете файл, создаете новую копию оставшегося оригинала и заново начинаете работать. Вам ведь все это знакомо, не так ли?
Если ваш ответ утвердителен, значит вы уже знакомы с системами управления версиями и ваше «знакомство» с ними подразумевает активное их использование!
1.2. Дадим определение понятию СУВ
СУВ — системы управления версиями, это инструмент, который в процессе работы позволяет нам каким-либо путем записывать наши изменения рабочих файлов, для возможности последующего отката.
GIT — это абсолютно обычная СУВ!
1.3. Разновидности СУВ
Существует как минимум 3 основных СУВ:
— Локальный
— Централизованные
— Распределенные
1.3.1. Локальные СУВ
Локальные СУВ должны быть знакомы начинающим программистам. Вы наверняка при работе с кодом, перед началом работы создаете копию рабочего каталога для того, чтобы если вы что-то напортачили, то у вас оставался тот прогресс на котором вы остановились в прошлый раз. Лично я делал так: Допустим у меня есть рабочая директория project в этой директории я создавал папку saves в которой хранились другие директории с именами версий 1, 2, 3 и т.д. и в каждой директории находились копии всех рабочий файлов с прогрессом на определенный момент времени. Я уверен, что многие делали подобным образом, возможно именовали категории не 1, 2, 3, а более логичным способом или еще что-то типа того. Все это можно назвать локальной СУВ каменного века! Существуют также специальные программы локальных СУВ, которые позволяют автоматизировать это копирование папок и файлов или использовать другой способ сохранения стадий развития проекта (версий).
Достоинства: Простота
Недостатки: Относительно небольшая область применения, опасность потери данных в случае если ваш компьютер поломался, или его у вас украли или все уничтожил вирус или …
1.3.2. Централизированные СУВ
Когда идет работа над большим проектом с окромным количеством папок, а в них в каждой огромное количество файлов, а в них в каждом огромное количество строк кода, то над таким проектом, как правило, работает несколько человек. Из необходимости организовать работу группы людей и были созданы централизированные СУВ (из тех, о которых я слышал это Subversion и CVS).
Представьте себе монарха восседающего на золотом троне да с золотой короной на златых власах… Представьте теперь сокровищницу с неисчислимыми богатствами. А теперь представьте, как верные вассалы подношают царю налоги собранные со своих крепостных да подарки, чтобы задобрить своего владыку. — Вот примерно таким образом организованы централизированные СУВ.
Есть монарх он же главный разработчик и есть вассалы — разработчики каждый из которых вносит какую-то свою определенную лепту. Сокровищница в данном случае это центральный репозиторий в который добавляются результаты работы участников процесса разработки какого-либо проекта (налоги).
Достоинства: Высокая степень организации процесса разработки, контроль основного (центрального) репозитория, широкая область применения.
Недостатки: Существует риск потерять данные если сервер на котором размещен центральный репозиторий поломается.
1.3.3. Распределенные СУВ
Представьте детскую группу в садике. У детей урок аппликации. У каждого ребенка свои ножницы, своя цветная бумага, клей, заляпанные клеем штаны и полное довольством за свою работу лицо. Дети заканчивают делать свои работы, воспитательница собирает их, выбирает самые хорошие и отправляет их, например, на городскую выставку детского творчества предварительно сделав всем детям альбомы с копиями работ. — Все это похоже на то, как работают распределенные СУВ.
При распределенных СУВ также имеется центральный (основной) репозиторий (воспитательница), но в этот раз центральный репозиторий является не единственным местом хранения версий проекта так как разработчики делают локальные копии центрального репозитория и теперь если один из компьютеров разработчиков или центральный сервер накроется, то потери будут совсем минимальными и работу можно будет достаточно быстро восстановить (альбомы с копиями аппликаций). Как вам, нравится такой подход?
Git относится именно к распределенным СУВ.
Достоинства: Безопасность данных, высокая степень организации процесса разработки, широкая область применения.
Недостатки: Незначительно увеличивается сложность процесса контроля версий.
1.3.4. История Git
Чисто как дань уважения пишу небольшой раздел об истории появления Git (честно говоря я никогда этот раздел в книгах не читаю).
Жил был на свете Антон Городецкий Линус Торвальдс и занимался он с 33 богатырями разработкой ни чего нибудь, а ядра Linux! Сами понимаете, операционные системы — это достаточно сложные программы для разработки которых без использования СУВ не обойтись. Так вот, поначалу худо-бедно богатыри вели контроль версий путем, на сколько я понимаю рабским, то есть, как я понял все это было весьма глупо, производилось вручную и было трудоемко. Затем, в 2002 году Линус Торвальдс и компания богатырей — разработчиков решили воспользоваться СУВ BitBeeper. Затем, по некоторым причинам личного характера разработчики ядра Linux решили отказаться от BitKeepera и Линус Торвальдс в порывах чувств и пребывая в необыкновенной силы порыве энтузиазма создал Git.
Как видите, Git изначально был оптимизирован под крупные проекты с большим сообществом разработчиков, но это не значит, что вы не можете использовать его при разработке чего-то маленького.
Изначально Git представлял собой кучу разных команд, их было реально много и они вводили в путаницу людей. Это конечно же мешало, но мы живем в знаменательную эпоху, когда Git необыкновенно прост! И, кстати, очень быстр, что так же не маловажно!
Вот и вся история…
2. Возвращаемся к баранам: Ветки и все такое
2.1. Память — дело хорошее…
Проверяем на чем мы остановились в прошлой статье:
$ cd
$ cd git_example
$ git status
# On branch master
# Changed but not updated:
# (use "git add ..." to update what will be committed)
# (use "git checkout -- ..." to discard changes in working directory)
#
# modified: app/models/user.rb
#
no changes added to commit (use "git add" and/or "git commit -a")
Мы видим, что у нас имеется изменение в модели User, которое мы еще не закоммитили. Ах, да, это тот комментарий…
2.2. Команда git log
Эта команда вызывает у меня большое уважение и даже некий страх и трепет перед ее величием. Команда git log позволяет нам увидеть историю изменений в нашем проекте (как же все таки гордо звучит слово «ПРОЕКТ»). Чтобы показать вам как все это выглядит просто выполним git log в консоли:
$ git log
commit 2d566e74ac1a5c8144ddd205e1bec742cba67a1d
Author: egoholic
Date: Mon Jan 24 00:58:12 2011 +0200
user model
commit 41f65c1dced1c0885a57dbd5bca9b438828a7adb
Author: egoholic
Date: Mon Jan 24 00:56:42 2011 +0200
initial commit
Мда, не густо! Всего-то 2 коммита:
‘initial commit’ - наш первый коммит с нулевым прогрессом проекта
‘user model’ - Вот видите зачем необходимы комментарии к коммитам!? Теперь мы можем вспомнить, что в этом коммите «заснят» прогресс после добавления модели User.
2.3. Branch — ветка
Branch (далее по тексту бранч или ветка) — это ответвление в контексте нашего проекта. Помните пример из начала статьи про копирование рабочего файла и работы с его копией? Для этих же целей мы будем использовать бранчи. Кстати, мы уже использовали бранчи! Не говорите, что вы не знакомы с этим! Доказательство:
$ git branch
* master
2.3.1. Команда git branch
Команда git branch — имеет три функции: просмотр существующих веток проекта, создание новой ветки и удаление имеющейся ветки. Выше мы использовали команду git branch для того, чтобы увидеть список всех имеющихся веток, а имеется у нас их аж целая одна — master. Звездочка указывает нам на то, что в данный момент мы работаем именно в контексте этой ветки (видите ли выбор не особо богат). Давайте воспользуемся второй функцией команды git branch и создадим еще одну ветку проекта:
$ git branch big_changes
$ git branch
big_changes
* master
Теперь давайте удалим только что созданную ветку:
$ git branch -d big_changes
Deleted branch big_changes (was 2d566e7).
$ git branch
* master
Все просто, не так ли?
2.3.2. Команда git checkout
Очень интересно создавать ветки и не работать в них. Коварные разработчики предрекли такое наше поведение и добавили команду для работы с ветками — git checkout. Теперь мы просто обречены на переключение на новый бранч и работу в его контексте. Давайте переключимся на ветку big_changes, чтобы сделать затем какие-нибудь весомые изменения в проекте:
$ git branch big_changes
$ git checkout big_changes
M app/models/user.rb
Switched to branch 'big_changes'
vladimir@egoholic:~/git_example$ git branch
* big_changes
master
Теперь мы переключились на ветку big_changes и можем работать в ее контексте, ни как не влияя на ветку master (это у нас основная ветка).
С помощью команды git checkout так же можно создавать бранчи с той лишь разницей от git branch , про при использовании git checkout -b мы после создания новой ветки автоматически переключаемся на нее. Пример:
$ git checkout -b cho_branch
M app/models/user.rb
Switched to a new branch 'cho_branch'
$ git branch
big_changes
* cho_branch
master
$ git checkout big_changes
M app/models/user.rb
Switched to branch 'big_changes'
3. Работа в контексте бранча
3.1. Добавление модели Post
Чтобы пользователю не было скучно, добавим ему возможность создавать посты. Для этого необходимо сгенерировать модель Post:
$ rails g model Post title:string text:text invoke active_record create db/migrate/20110131215050_create_posts.rb create app/models/post.rb invoke test_unit create test/unit/post_test.rb create test/fixtures/posts.yml $ git status # On branch big_changes # Untracked files: # (use "git add ..." to include in what will be committed) # # app/models/post.rb # db/migrate/20110131215050_create_posts.rb # test/fixtures/posts.yml # test/unit/post_test.rb nothing added to commit but untracked files present (use "git add" to track)
Теперь нам следует сделать коммит:
$ git add .
$ git commit -m 'add Post model'
[big_changes d3b9840] add Post model
4 files changed, 33 insertions(+), 0 deletions(-)
create mode 100644 app/models/post.rb
create mode 100644 db/migrate/20110131215050_create_posts.rb
create mode 100644 test/fixtures/posts.yml
create mode 100644 test/unit/post_test.rb
Итак, в бранче big_changes у нас имеется модель Post c которой мы будем работать в контексте бранча, а затем, если задуманное удастся, то мы подмешаем наш бранч к основному master-бранчу. Как вы думаете, если мы переключимся в master-бранч и заглянем в папку app/models, увидем ли мы там файл post.rb с моделью Post? А вот давайте и проверим!
$ cd app/models/
$ dir
user.rb
Ну вот, наши общие надежды подтвердились! Не верьте, если кто-то скажет, что это трансерфинг и что наши мысли материализовались! На самом деле это все рук Git!
3.2. Редактируем модели
Итак, возвращаемся к нашему big_changes бранчу и, давайте установим отношения между нашими моделями:
#models/post.rb class Post < ActiveRecord::Base validates :title, :presence => true validates :text, :presence => true belongs_to :user end #models/user.rb class User < ActiveRecord::Base validates :name, :presence => true validates :email, :presence => true has_many :posts, :dependent => :destroy end
Теперь необходимо создать соответствующие моделям таблицы в базе данных путем выполнения Rake — задачи rake db:migrate:
$ rake db:migrate
(in /home/vladimir/git_example)
== CreateUsers: migrating ====================================================
-- create_table(:users)
-> 0.0035s
== CreateUsers: migrated (0.0037s) ===========================================
== CreatePosts: migrating ====================================================
-- create_table(:posts)
-> 0.0033s
== CreatePosts: migrated (0.0035s) ===========================================
Все! Теперь мы можем сделать коммит и присоединить big_changes в master-бранчу, а саму ветку big_changes удалить:
$ git status # On branch big_changes # Changed but not updated: # (use "git add ..." to update what will be committed) # (use "git checkout -- ..." to discard changes in working directory) # # modified: app/models/post.rb # modified: app/models/user.rb # # Untracked files: # (use "git add ..." to include in what will be committed) # # db/schema.rb no changes added to commit (use "git add" and/or "git commit -a") $ git add . $ git commit -m 'edit Post and User models' [big_changes 0d88ed5] edit Post and User models 3 files changed, 40 insertions(+), 0 deletions(-) create mode 100644 db/schema.rb
Коммит создан! Осталось дело за малым — объединить бранчи и удалить более ненужный big_changes.
4. Слияние веток проекта
Чтобы примешать изменения из ветки big_changes к ветке master следует воспользоваться командой git merge. Для этого следует перейти в ветку в которую желаете произвести подмешивание и выполнить команду git merge :
$ git checkout master
Switched to branch 'master'
$ git merge big_changes
Updating 2d566e7..0d88ed5
Fast-forward
app/models/post.rb | 7 +++++++
app/models/user.rb | 6 ++++++
db/migrate/20110131215050_create_posts.rb | 14 ++++++++++++++
db/schema.rb | 29 +++++++++++++++++++++++++++++
test/fixtures/posts.yml | 9 +++++++++
test/unit/post_test.rb | 8 ++++++++
6 files changed, 73 insertions(+), 0 deletions(-)
create mode 100644 app/models/post.rb
create mode 100644 db/migrate/20110131215050_create_posts.rb
create mode 100644 db/schema.rb
create mode 100644 test/fixtures/posts.yml
create mode 100644 test/unit/post_test.rb
$ git branch -d big_changes
Deleted branch big_changes (was 0d88ed5).
Все, подмешивание завершено! Все изменения, которые мы выполнили в ветке big_changes теперь скопированы в нашу основную ветку проекта.
5. Хорошо забытое новое: команда git log
Мы как-то слишком быстро разминулись с этой замечательной командой, не находите? Давайте посмотрим, что она нам выдаст на этот раз:
$ git log commit 0d88ed57e8a1016f700993a72b248bc1dbd6f436 Author: egoholic Date: Tue Feb 1 00:29:16 2011 +0200 edit Post and User models commit d3b98407b20abaa50f02f1e80e3ad7beaace9445 Author: egoholic Date: Mon Jan 31 23:55:07 2011 +0200 add Post model commit 2d566e74ac1a5c8144ddd205e1bec742cba67a1d Author: egoholic Date: Mon Jan 24 00:58:12 2011 +0200 user model commit 41f65c1dced1c0885a57dbd5bca9b438828a7adb Author: egoholic Date: Mon Jan 24 00:56:42 2011 +0200 initial commit
Как и ожидалось, нам были представлены все коммиты, которые мы делали, включая новый в котором мы отредактировали наши модели!
Удачи в освоении Git!
Лучшая благодарность автору — ваши комментарии!
февраля 1, 2011 at 21:11 (#)
Сорри, что придираюсь не по теме — поправьте ссылку на Введение.
С http://rubydev.ru/2011/02/git_1 на http://rubydev.ru/2011/01/git_1
Спасибо за статьи, очень полезно. Все никак руки не доходили. Как раз завтра займусь.
Продолжайте))
февраля 2, 2011 at 06:21 (#)
wocreator, наоборот, спасибо, что заметили ошибку! Все уже исправил. и спасибо за «спасибо»! =)
февраля 2, 2011 at 10:57 (#)
Спасибо! Всё очень наглядно и понятно. Хотелось бы увидеть продолжение про совместную разработку, как работать с репозиториями, мёрджить результат своей работы с работой других людей.
февраля 5, 2011 at 18:37 (#)
Отличная статья, очень интересно. Жду продолжения.
апреля 9, 2011 at 21:37 (#)
Очень интересно. Спасибо!
Было бы любопытно узнать про то как взаимодействовать с github :)
января 13, 2012 at 03:55 (#)
С помощью команды git checkout так же можно создавать бранчи с той лишь разницей от git branch , про при использовании git checkout -b мы после создания новой ветки автоматически переключаемся на нее. Пример:
>про при использовании git
>про