-
1. Вступ
- 1.1 Про систему контролю версій
- 1.2 Коротка історія Git
- 1.3 Основи Git
- 1.4 Git, зазвичай, тільки додає дані
- 1.5 Три стани
- 1.6 Командний рядок
- 1.7 Інсталяція Git
- 1.8 Початкове налаштування Git
- 1.9 Отримання допомоги
- 1.10 Підсумок
-
2. Основи Git
- 2.1 Створення Git-репозиторія
- 2.2 Запис змін до репозиторія
- 2.3 Перегляд історії комітів
- 2.4 Скасування речей
- 2.5 Взаємодія з віддаленими сховищами
- 2.6 Теґування
- 2.7 Псевдоніми Git
- 2.8 Підсумок
-
3. Галуження в git
- 3.1 Гілки у кількох словах
- 3.2 Основи галуження та зливання
- 3.3 Управління гілками
- 3.4 Процеси роботи з гілками
- 3.5 Віддалені гілки
- 3.6 Перебазовування
- 3.7 Підсумок
-
4. Git на сервері
- 4.1 Протоколи
- 4.2 Отримання Git на сервері
- 4.3 Генерація вашого публічного ключа SSH
- 4.4 Налаштування Серверу
- 4.5 Демон Git
- 4.6 Розумний HTTP
- 4.7 GitWeb
- 4.8 GitLab
- 4.9 Варіанти стороннього хостингу
- 4.10 Підсумок
-
5. Розподілений Git
-
6. GitHub
-
7. Інструменти Git
- 7.1 Вибір ревізій
- 7.2 Інтерактивне індексування
- 7.3 Ховання та чищення
- 7.4 Підписання праці
- 7.5 Пошук
- 7.6 Переписування історії
- 7.7 Усвідомлення скидання (reset)
- 7.8 Складне злиття
- 7.9 Rerere
- 7.10 Зневадження з Git
- 7.11 Підмодулі
- 7.12 Пакування
- 7.13 Заміна
- 7.14 Збереження посвідчення (credential)
- 7.15 Підсумок
-
8. Налаштування Git
-
9. Git and Other Systems
- 9.1 Git як клієнт
- 9.2 Міграція на Git
- 9.3 Підсумок
-
10. Git зсередини
- 10.1 Кухонні та парадні команди
- 10.2 Об’єкти Git
- 10.3 Посилання Git
- 10.4 Файли пакунки
- 10.5 Специфікація посилань (refspec)
- 10.6 Протоколи передачі
- 10.7 Супроводження та відновлення даних
- 10.8 Змінні середовища
- 10.9 Підсумок
-
A1. Додаток A: Git в інших середовищах
- A1.1 Графічні інтерфейси
- A1.2 Git у Visual Studio
- A1.3 Git в Eclipse
- A1.4 Git у Bash
- A1.5 Git у Zsh
- A1.6 Git у Powershell
- A1.7 Підсумок
-
A2. Додаток B: Вбудовування Git у ваші застосунки
- A2.1 Git з командного рядка
- A2.2 Libgit2
- A2.3 JGit
- A2.4 go-git
-
A3. Додаток C: Команди Git
- A3.1 Налаштування та конфігурація
- A3.2 Отримання та створення проектів
- A3.3 Базове збереження відбитків
- A3.4 Галуження та зливання
- A3.5 Поширення й оновлення проектів
- A3.6 Огляд та порівняння
- A3.7 Зневаджування
- A3.8 Латання (patching)
- A3.9 Електронна пошта
- A3.10 Зовнішні системи
- A3.11 Адміністрування
- A3.12 Кухонні команди
3.2 Галуження в git - Основи галуження та зливання
Основи галуження та зливання
Розглянемо простий приклад галуження та зливання на схемі, котра трапляється в реальності:
-
Вам потрібно внести зміни до веб-сайту.
-
Створюєте гілку для своєї задачі.
-
Працюєте в цій гілці.
В якийсь момент вам дзвонять і кажуть, що є більш важлива задача та потрібно термінове виправлення. Ви зробите таке:
-
Переключитеся на головну гілку.
-
Створите гілку-виправлення.
-
Після тестування зливаєте гілку-виправлення та надсилаєте в основну гілку.
-
Переключаєтеся на першопочаткову гілку та продовжуєте роботу над задачею.
Основи галуження
Скажімо, ви працюєте над проектом і вже маєте кілька комітів у гілці master
.
Тепер вирішили працювати над задачею, котра в системі вашої компанії зареєстрована як №53.
Щоб створити нову гілку для цієї задачі та одразу перейти на неї, виконайте команду git checkout
з параметром -b
:
$ git checkout -b iss53
Switched to a new branch "iss53"
Це скорочений запис наступного:
$ git branch iss53
$ git checkout iss53
Ви працюєте над змінами до сайту та комітите зміни.
Таким чином ваша гілка iss53
починає рухається вперед, оскільки ви на неї раніше переключилися (тобто вказівник HEAD
вказує на цю гілку):
$ vim index.html
$ git commit -a -m 'added a new footer [issue 53]'
iss53
рухаєтьсяВам подзвонили та доповіли про проблему на сайті, якої потрібно якнайшвидше позбутися.
Завдяки Git, вам не потрібно відсилати це виправлення разом із змінами в iss53
, також, ви не докладете багато зусиль для того щоб скасувати поточні зміни та працювати над виправленням в основній гілці.
Все що потрібно, це знову переключитися на основну гілку master
.
Проте, зверніть увагу на те, що якщо у вашій робочій директорії чи області з підготовленими файлами є незакомічені зміни, це спричинить конфлікт з гілкою master
та Git не дозволить зробити це переключення.
Найкраще спочатку очистити вашу робочу область перед переключеннями.
Способи як це зробити (сховати (stash) та виправити (commit amend)) ми розглянемо пізніше в Ховання та чищення.
Зараз вважаємо, що ми закомітили всі зміни в iss53
, отже, можна перейти на гілку master
:
$ git checkout master
Switched to branch 'master'
Тепер ваша робоча директорія точно в такому стані, як була до того, як ви почали працювати над №53 і ви можете сфокусуватися на терміновому виправленні. Важливо запам’ятати: коли перемикаєтеся між гілками, Git відновлює вашу робочу директорію, щоб вона виглядала так як після вашого останнього коміту. Git додає, видаляє та змінює файли автоматично, щоб впевнитися що ваша робоча копія точно відповідає тому якою була гілка на час вашого останнього коміту.
Далі вам знову потрібно зробити ще одне швидке виправлення.
Створимо гілку hotfix
і будемо там працювати поки не закінчимо:
$ git checkout -b hotfix
Switched to a new branch 'hotfix'
$ vim index.html
$ git commit -a -m 'fixed the broken email address'
[hotfix 1fb7853] fixed the broken email address
1 file changed, 2 insertions(+)
hotfix
, базована на master
Тепер можете запускати тести, щоб впевнитися що зміна годиться і нарешті злити (merge) гілку hotfix
назад до master
щоб викласти зміни на виробництво.
Робиться це за допомогою команди git merge
command:
$ git checkout master
$ git merge hotfix
Updating f42c576..3a0874c
Fast-forward
index.html | 2 ++
1 file changed, 2 insertions(+)
Зверніть увагу на фразу “fast-forward” у цьому злитті.
Через те, що коміт C4
, який зливався, належав гілці hotfix
, що була безпосередньо попереду поточного коміту C2
, Git просто переміщує вказівник вперед.
Іншими словами, коли ви зливаєте один коміт з іншим, і це можна досягнути слідуючи історії першого коміту, Git просто переставляє вказівник, оскільки немає змін-відмінностей, які потрібно зливати разом - це називається “перемоткою” (“fast-forward”).
Тепер ваша зміна міститься в знімку коміту, на який вказує master
і ви можете викладати зміни.
master
перемотаний на hotfix
Після того, як ваше супер важливе виправлення викладено, можна повернутися до роботи, яку було відкладено через швидке виправлення.
Але спочатку видалимо гілку hotfix
— нам вона більше не потрібна, а master
вказує на той самий знімок коду.
Для цього виконайте git branch
з опцією -d
:
$ git branch -d hotfix
Deleted branch hotfix (3a0874c).
Тепер перемикайтеся на вашу незакінчену гілку для №53 і продовжуйте роботу.
$ git checkout iss53
Switched to branch "iss53"
$ vim index.html
$ git commit -a -m 'finished the new footer [issue 53]'
[iss53 ad82d7a] finished the new footer [issue 53]
1 file changed, 1 insertion(+)
iss53
Зауважте, що зміни з гілки hotfix
відсутні в гілці iss53
.
Якщо вам потрібні ці зміни підчас роботи над №53, ви можете злити master
з iss53
командою git merge master
, або просто почекати до того моменту коли ви будете інтегровувати iss53
в master
.
Основи зливання
Допустимо, ви вирішили, що робота над №53 завершена і готова до злиття з гілкою master
.
Для цього ви виконаєте злиття гілки iss53
до master
саме так, як раніше робили це з гілкою hotfix
.
Все що потрібно це перемкнутися на вашу робочу гілку і виконати команду git merge
:
$ git checkout master
Switched to branch 'master'
$ git merge iss53
Merge made by the 'recursive' strategy.
index.html | 1 +
1 file changed, 1 insertion(+)
Виглядає трошки інакше, ніж те, що ми робили з гілкою hotfix
.
У цьому випадку історія змін двох гілок почала відрізнятися в якийсь момент.
Оскільки коміт поточної гілки не є прямим нащадком гілки, в яку ви зливаєте зміни, Git мусить трохи попрацювати.
В цьому випадку Git робить просте триточкове злиття, користуючись двома знімками, що вказують на гілки та третім знімком - їх спільним предком.
Замість того, щоб просто пересунути вказівник гілки вперед, Git створює новий знімок, що є результатом 3-точкового злиття, і автоматично створює новий коміт, що вказує на нього. Його називають комітом злиття (merge commit) та його особливістю є те, що він має більше одного батьківського коміту.
Варто зауважити, що Git сам визначає найбільш підходящого спільного нащадка, якого брати за основу зливання; це відрізняє Git від старіших систем таких як CVS чи Subversion (до версії 1.5), де розробник, що виконує зливання, сам повинен вказувати що брати за основу зливання. Це надзвичайно полегшує зливання, порівняно з іншими системами.
Тепер, коли ваші зміни злиті, гілка iss53
вам більше не потрібна.
Можете закривати задачу №53 та видаляти гілку:
$ git branch -d iss53
Основи конфліктів зливання
Трапляється, що цей процес не проходить гладко.
Якщо ви маєте зміни в одному й тому самому місці в двох різних гілках, Git не зможе їх просто злити.
Якщо підчас роботи над №53 ви поміняли ту саму частину файлу, що й у гілці hotfix
, ви отримаєте конфлікт, що виглядає приблизно так:
$ git merge iss53
Auto-merging index.html
CONFLICT (content): Merge conflict in index.html
Automatic merge failed; fix conflicts and then commit the result.
У цьому випадку Git не створив автоматичний коміт зливання.
Він призупинив процес допоки ви не вирішите конфлікт.
Для того, щоб переглянути знову які саме файли спричинили конфлікт, виконайте git status
:
$ git status
On branch master
You have unmerged paths.
(fix conflicts and run "git commit")
Unmerged paths:
(use "git add <file>..." to mark resolution)
both modified: index.html
no changes added to commit (use "git add" and/or "git commit -a")
Все, що має конфлікти, які не були вирішені є в списку незлитих (unmerged) файлів. У кожен такий файл Git додає стандартні позначки-вирішенння для конфліктів, отже ви можете відкрити ці файли і вирішити конфлікти самостійно. У вашому файлі з конфліктом появиться блок, схожий на таке:
<<<<<<< HEAD:index.html
<div id="footer">contact : email.support@github.com</div>
=======
<div id="footer">
please contact us at support@github.com
</div>
>>>>>>> iss53:index.html
Розглянемо, як це розуміти. Версія файлу в HEAD
(з вашої master
гілки, оскільки ви запустили зливання, будучи на ній) у верхній частині блоку (все вище =======
), а версія з iss53
- все, що нижче.
Щоб розв’язати цю несумісність, вам потрібно вибрати одну із версій, або самостійно (вручну) поредагувати вміст файлу.
Наприклад, ви можете вирішити цей конфілікт, замінивши блок повністю:
<div id="footer">
please contact us at email.support@github.com
</div>
В цьому випадку ми взяли потрохи з кожної секції, а стрічки <<<<<<<
, =======
та >>>>>>>
видалили повністю.
Після того, як ви розв’язали подібні несумісності в кожному блоці конфліктних файлів, виконайте для них git add
, щоб індексувати та позначити, як розв’язані.
Індексуючи файл, ви позначаєте його для Git таким, що більше не має конфлікту.
Якщо ви хочете використовувати графічний інструмент для розв’язання конфліктів, виконайте команду git mergetool
, яка запустить графічний редактор та проведе вас по всьому процесу:
$ git mergetool
This message is displayed because 'merge.tool' is not configured.
See 'git mergetool --tool-help' or 'git help config' for more details.
'git mergetool' will now attempt to use one of the following tools:
opendiff kdiff3 tkdiff xxdiff meld tortoisemerge gvimdiff diffuse diffmerge ecmerge p4merge araxis bc3 codecompare vimdiff emerge
Merging:
index.html
Normal merge conflict for 'index.html':
{local}: modified file
{remote}: modified file
Hit return to start merge resolution tool (opendiff):
Для того, щоб використовувати інструмент-програму іншу, ніж по-замовчуванню (Git обрав opendiff
, оскільки команду було запущено з Mac), подивіться на список сумісних зверху одразу після “one of the following tools.”
Просто введіть ім’я потрібного інструменту.
Зауваження
|
Про інструменти для розв’язання більш складних конфліктів ми повернемося в Складне злиття. |
Після того, як ви вийшли з програми для зливання, Git спитає вас чи було зливання успішним.
Якщо ви відповісте, що так, Git проіндексує файл для того, щоб позначити файл як безконфліктний
Можете виконати git status
знову, щоб перевірити чи всі конфлікти розв’язані:
$ git status
On branch master
All conflicts fixed but you are still merging.
(use "git commit" to conclude merge)
Changes to be committed:
modified: index.html
Якщо ви задоволені результатом та перевірили, що всі файли, котрі містили несумісності, проіндексовані, можете виконувати git commit
і, таким чином, завершувати злиття.
Повідомлення після коміту виглядає приблизно так:
Merge branch 'iss53'
Conflicts:
index.html
#
# It looks like you may be committing a merge.
# If this is not correct, please remove the file
# .git/MERGE_HEAD
# and try again.
# Please enter the commit message for your changes. Lines starting
# with '#' will be ignored, and an empty message aborts the commit.
# On branch master
# All conflicts fixed but you are still merging.
#
# Changes to be committed:
# modified: index.html
#
Якщо ви вважаєте, що це допоможе іншим зрозуміти коміт злиття у майбутньому, можете змінити його повідомлення — докладно розказати, як ви розвʼязали конфлікт, чому ви зробили саме такі зміни, якщо це й без того не є очевидним.