-
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 Кухонні команди
7.9 Інструменти Git - Rerere
Rerere
Можливості git rerere
є трохи прихованими.
Назва походить від “використовуй записані розвʼязання” (reuse recorded resolution) та, як зрозуміло з назви, дозволяє вам попросити Git запамʼятати, як ви розвʼязали конфлікт шматків (hunk), щоб наступного разу Git міг автоматично розвʼязати такий самий конфлікт для вас.
Є декілька ситуацій, в яких цей функціонал може бути дуже доречним.
Одна з таких ситуацій згадується в документації: коли ви бажаєте переконатись, що довготривала тематична гілка зіллється переважно чисто, проте не бажаєте, щоб купа проміжних комітів злиття засмічували історію.
Якщо rerere
увімкнено, ви можете іноді зливати, розвʼязувати конфлікти, а потім припиняти злиття.
Якщо робити це постійно, то останнє злиття має бути простим, адже rerere
може просто зробити за вас все автоматично.
Таку саму тактику можна використовувати, якщо ви бажаєте тримати гілку перебазованою, щоб не доводилося мати справу з однаковими конфліктами перебазування щоразу, як ви його робите. Або якщо ви бажаєте взяти гілку, яку ви зливали та виправили купу конфліктів, а потім вирішили замість цього зробити перебазування — імовірно вам не доведеться знову виправляти всі ці конфлікти.
Ще однин приклад застосування rerere
: коли ви іноді зливаєте купу незавершених тематичних гілок разом, щоб перевірити результат, як сам проект Git часто робить.
Якщо тести провалились, ви можете скасувати зливання та зробити їх знову без тематичної гілки, що спричинила проблему, без необхідності знову розвʼязувати конфлікти.
Щоб увімкнути функціональність rerere
, треба просто виконати це налаштування конфігурації:
$ git config --global rerere.enabled true
Також його можна ввімкнути, якщо створити директорію .git/rr-cache
в окремому репозиторії, проте налаштування конфігурації ясніше, та вмикає цей функціонал глобально.
Тепер погляньмо на простий приклад, схожий на попередній.
Скажімо, у нас є файл hello.rb
, що виглядає так:
#! /usr/bin/env ruby
def hello
puts 'hello world'
end
В одній гілці ми змінюємо слово “hello” на “holf”, потім в іншій гілці змінюємо “world” на “mundo”, як і раніше.
Коли ми зіллємо ці дві гілки разом, ми отримаємо конфлікт злиття:
$ git merge i18n-world
Auto-merging hello.rb
CONFLICT (content): Merge conflict in hello.rb
Recorded preimage for 'hello.rb'
Automatic merge failed; fix conflicts and then commit the result.
Зверніть тут увагу на новий рядок Recorded preimage for FILE
(записано предвідбиток для ФАЙЛУ).
Решта виглядає так само, як і звичайний конфлікт зливання.
Наразі, rerere
знає декілька речей.
Зазвичай, ви зараз виконали б git status
, щоб побачити всі конфлікти:
$ git status
# On branch master
# Unmerged paths:
# (use "git reset HEAD <file>..." to unstage)
# (use "git add <file>..." to mark resolution)
#
# both modified: hello.rb
#
Однак, git rerere
також скаже вам, що він записав стан до злиття, якщо виконати git rerere status
:
$ git rerere status
hello.rb
А git rerere diff
покаже поточний стан розвʼязання — з чого почалось розвʼязання та як ви його розвʼязали.
$ git rerere diff
--- a/hello.rb
+++ b/hello.rb
@@ -1,11 +1,11 @@
#! /usr/bin/env ruby
def hello
-<<<<<<<
- puts 'hello mundo'
-=======
+<<<<<<< HEAD
puts 'hola world'
->>>>>>>
+=======
+ puts 'hello mundo'
+>>>>>>> i18n-world
end
Також (і це насправді не повʼязано з rerere
), ви можете використати git ls-files -u
, щоб побачити файли конфлікту та попередню, ліву та праву версії:
$ git ls-files -u
100644 39804c942a9c1f2c03dc7c5ebcd7f3e3a6b97519 1 hello.rb
100644 a440db6e8d1fd76ad438a49025a9ad9ce746f581 2 hello.rb
100644 54336ba847c3758ab604876419607e9443848474 3 hello.rb
Тепер ви можете розвʼязати конфлікт щоб було puts 'hola mundo'
та знову виконати команду git rerere diff
, щоб побачити, що запамʼятає rerere:
$ git rerere diff
--- a/hello.rb
+++ b/hello.rb
@@ -1,11 +1,7 @@
#! /usr/bin/env ruby
def hello
-<<<<<<<
- puts 'hello mundo'
-=======
- puts 'hola world'
->>>>>>>
+ puts 'hola mundo'
end
Це нам каже, що коли Git побачить конфлікт шмату (hunk) у файлі hello.rb
, де з одного боку “hello mundo”, а з іншого “hola world”, він розвʼяже конфлікт рядком “hola mundo”.
Тепер ми можемо позначити його розвʼязаним та зберегти у коміті:
$ git add hello.rb
$ git commit
Recorded resolution for 'hello.rb'.
[master 68e16e5] Merge branch 'i18n'
Зверніть увагу на "Recorded resolution for FILE" (Записано розвʼязок для ФАЙЛУ).
Тепер, скасуймо це злиття та замість нього перебазуймо нашу гілку поверху master.
Ми можемо пересунути нашу гілку назад за допомогою git reset
, як ми бачили в Усвідомлення скидання (reset).
$ git reset --hard HEAD^
HEAD is now at ad63f15 i18n the hello
Наше злиття скасовано. Тепер перебазуймо тематичну гілку.
$ git checkout i18n-world
Switched to branch 'i18n-world'
$ git rebase master
First, rewinding head to replay your work on top of it...
Applying: i18n one word
Using index info to reconstruct a base tree...
Falling back to patching base and 3-way merge...
Auto-merging hello.rb
CONFLICT (content): Merge conflict in hello.rb
Resolved 'hello.rb' using previous resolution.
Failed to merge in the changes.
Patch failed at 0001 i18n one word
Тепер, ми отримали саме такий конфлікт зливання, як очікували, проте погляньте на рядок Resolved FILE using previous resolution
(Розвʼязали ФАЙЛ за допомогою попереднього розвʼязку).
Якщо ми відкриємо файл, то побачимо, що він вже розвʼязаний, там більше немає позначок конфлікту.
#! /usr/bin/env ruby
def hello
puts 'hola mundo'
end
Також, git diff
покаже вам, як конфлікт був знову розвʼязаний автоматично:
$ git diff
diff --cc hello.rb
index a440db6,54336ba..0000000
--- a/hello.rb
+++ b/hello.rb
@@@ -1,7 -1,7 +1,7 @@@
#! /usr/bin/env ruby
def hello
- puts 'hola world'
- puts 'hello mundo'
++ puts 'hola mundo'
end
Ви також можете повернути файл до стану конфлікту за допомогою git checkout
:
$ git checkout --conflict=merge hello.rb
$ cat hello.rb
#! /usr/bin/env ruby
def hello
<<<<<<< ours
puts 'hola world'
=======
puts 'hello mundo'
>>>>>>> theirs
end
Ми бачили приклад цього в Складне злиття.
Проте зараз, розвʼяжімо його знову: для цього треба просто виконати git rerere
знов:
$ git rerere
Resolved 'hello.rb' using previous resolution.
$ cat hello.rb
#! /usr/bin/env ruby
def hello
puts 'hola mundo'
end
Ми знову розвʼязали файл автоматично за допомогою збереженого rerere
розвʼязок.
Тепер ви можете проіндексувати файл та продовжити перебазування, щоб завершити його.
$ git add hello.rb
$ git rebase --continue
Applying: i18n one word
Отже, якщо ви робите багато повторних зливань, або бажаєте зберігати тематичну гілку у відповідності з гілкою master без численних зливань, або часто перебазовуєте, то можете увімкнути rerere
, щоб трохи полегшити собі життя.