ПРО GIT: Ветки (бранчи)

февраля 1, 2011  |  Published in Development Processes, Управление Версиями  |  6 Comments

Git logoЦикл статей ПРО 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!

Лучшая благодарность автору — ваши комментарии!

Tags:

Responses

  1. wocreator says:

    февраля 1, 2011 at 21:11 (#)

    Сорри, что придираюсь не по теме — поправьте ссылку на Введение.
    С http://rubydev.ru/2011/02/git_1 на http://rubydev.ru/2011/01/git_1

    Спасибо за статьи, очень полезно. Все никак руки не доходили. Как раз завтра займусь.
    Продолжайте))

  2. admin says:

    февраля 2, 2011 at 06:21 (#)

    wocreator, наоборот, спасибо, что заметили ошибку! Все уже исправил. и спасибо за «спасибо»! =)

  3. racoon says:

    февраля 2, 2011 at 10:57 (#)

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

  4. says:

    февраля 5, 2011 at 18:37 (#)

    Отличная статья, очень интересно. Жду продолжения.

  5. sld says:

    апреля 9, 2011 at 21:37 (#)

    Очень интересно. Спасибо!
    Было бы любопытно узнать про то как взаимодействовать с github :)

  6. anon says:

    января 13, 2012 at 03:55 (#)

    С помощью команды git checkout так же можно создавать бранчи с той лишь разницей от git branch , про при использовании git checkout -b мы после создания новой ветки автоматически переключаемся на нее. Пример:

    >про при использовании git
    >про

Leave a Response

Для подсветки кода используйте BB - коды: [language]...[/language], где language может быть: ruby, javascript, css, html.