Git практическое руководство фишерман pdf

Книга в формате pdf! Изображения и текст могут не отображаться!

Настройки текста:


ПРАКТИЧЕСКОЕ

PYKOBODCTBO

Управление и контроль версий
в разработке программного

обеспечения

ФишЕРмдн Л . В.

Практическое руководство
Управление и контроль версий в разработке
программного обеспечения

«Наука и Техника»

Санкт-Петербург

Telegram:

https://t.me/it_boooks

УДКОО4.42

ББКЗ2.973
Фишерман Л. В.

G1т. ПРАКТИЧЕСКОЕ РУКОВОДСТВО. УПРАВЛЕНИЕ И КОНТРОЛЬ ВЕРСИЙ В
РАЗРАБОТКЕ ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ —

— 304 с.,

СПБ.: НАУКА и ТЕХНИКА,

2021.

ил.

ISBN 978-5-94387-547-2

Git

в настоящее время нужен практически всем программистам, которые

занимаются разработкой программного обеспечения.

Git —

это система

управления версиями, с помощью которой вы сможете вести и контроли­

ровать разработку нескольких версий одного приложения, осуществлять
совместную разработку одного приложения несколькими разработчиками

(учитывать изменения, которые делаются на том или ином шаге разработки
тем или иным разработчиком). С помощью системы

Git у

вас будет полная

иерархия всех версий программного кода разрабатываемого приложения.

Данная книга представляет собой подробное практическое руководство по

Git, в

котором описывается

Git и

приводится разбор конкретных ситуаций

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

кой предварительной подготовки не требуется: по ходу изложения даются
все необходимые определения и пояснения. Лучший выбор, чтобы освоить

Git и максимально быстро начать его применять на практике.

Все права защищены . Ни какая часть данной книги не может быть воспроизведена в какой бы то ни было форме без пись­
менного разрешения владельцев авторских прав .

Издательство не несет ответственности за доступность материалов, ссылки на которые вы можете найти в этой книге . На
момент подготовки книги к изданию все ссылки на интернет-ресурсы были действующими .

15BN 978-5-94387-547-2
Контактные телефоны издательства :

(812)4127026
Оф ициальный сайт:

www.nit.com.ru

© Фишерман Л. В.

9 78 — 5- 94387- 547- 2

©

Наука и Техника (оригинал-макет)

Содержание
ГЛАВА

1.

ВВЕДЕНИЕ В

GIT ………………………………… 9

1. 1.

НЕОБХОДИМОСТЬ РЕЗЕРВНОГО КОПИРОВАНИЯ

1.2.

ЭТАПЫ РАЗВИТИЯ

1.3.

ЧТО В ИМЕНИ ТВОЕМ?

ГЛАВА
2.1.

2.

…………………….. 1 О

…………………………………………………………. 11
…………………………………………………….. 12

УСТАНОВКА

GIT ……………………………….. 13

ИСПОЛЬЗОВАНИЕ ДВОИЧНЫХ ДИСТРИБУТИВОВ

LINUX …. …………. 14

DeЬian/Ubuntu …….. ……. .. … ……………… …… …….. … …. .. .. ……. .. .. .. 15

Другие дистрибутивы ….. …… …….. ……. .. .. .. …. ……… …. ……… .. ….. 16

2.2.

ПОЛУЧЕНИЕ ИСХОДНОГО КОДА

2.3.

СБОРКА И УСТАНОВКА

2.4.

УСТАНОВКА

GIT

В

………………………….. .. ………………………. 18

WINDOWS ……………………………………………… 20

Установка пакета
Установка

ГЛАВА

3.

…. .. . …………………………………… 17

Cygwin Git …… … .. … ……. .. .. ….. … …… …… …. …… 21

msysGit ……………… …… ….. .. ….. … …. …… ….. .. ……. ……. 22

НАЧАЛО ИСПОЛЬЗОВАНИЯ

3. 1 .

КОМАНДНАЯ СТРОКА

3.2.

БЫСТРОЕ ВВЕДЕНИЕ В

…………………. 25

GIT …………………………………………………. 26
GIT … …………………………………………….. 29

Создание начального репозитария

.. …. ………. … …. …. …… …. … …. 29

Добавление файлов в ваш репозитарий ………………………………. 30

Неясные сообщения об ошибках ……………. … …….. … …….. … ……. 32
Настройка автора коммита (фиксации)

.. … …….. .. … .. …. … ….. …. .. 32

Вносим другой коммит (фиксацию) … … …. …. .. ….. …. .. … … … … …. .33
Просмотр ваших фиксаций

.. …. ………. .. .. ……. .. …….. … ……….. …. .33

Просмотр разницы между коммитами (фиксациями)

…. … … … …. 35

Удаление и переименование файлов в вашем репозитарии

Копирование вашего репозитария

….. .. 36

…… …… …. .. .. …. .. ……….. ….. … 37

3.3. ФАЙЛЫ КОНФИГУРАЦИИ …………… .. ………………………………….. 38
Настройка псевдонимов
Резюме

….. … …. .. ………… … …… ………. ….. …. ….. .40

….

……. …. …………. …….. .. ……. …. …. ……….. … … .. ……… … ….. .41

… .. . .. . . . . . . . . . . . . . . . .. . —.. —. — —…… —. -……… -… -…. -… -…. -.. —

Git. Практическое руководство

ГЛАВА
4. 1.

4.

БАЗОВЫЕ ПОНЯТИЯ

БАЗОВЫЕ ПОНЯТИЯ

………………………….. ………………… . ……… . . 43

Репозитарии

…….. .. ….. .. ……. … …. … …….. …… .. … .. .. ….. .. .. … … … .. .44

Типы объектов
Индекс

GIT …………………….. 42

Git .. … .. ……… …… ….. .. …….. ……. …….. ……….. … .. …44

……… …….. ….. ………… …… ……. .. …. .. … …. ….. ….. ……… … … 46

Глобально уникальные идентифи каторы

Git отслеживает

контент …. ………. .. .. … …… ….. ……………. ………. … 47

Путь по сравнению с содержанием
Расk-файлы

4.2.

………


ПРАКТИЧЕСКОЕ

PYKOBODCTBO

Управление и контроль версий
в разработке программного

обеспечения

ФишЕРмдн Л . В.

Практическое руководство
Управление и контроль версий в разработке
программного обеспечения

«Наука и Техника»

Санкт-Петербург

Telegram:

https://t.me/it_boooks

УДКОО4.42

ББКЗ2.973
Фишерман Л. В.

G1т. ПРАКТИЧЕСКОЕ РУКОВОДСТВО. УПРАВЛЕНИЕ И КОНТРОЛЬ ВЕРСИЙ В
РАЗРАБОТКЕ ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ —

— 304 с.,

СПБ.: НАУКА и ТЕХНИКА,

2021.

ил.

ISBN 978-5-94387-547-2

Git

в настоящее время нужен практически всем программистам, которые

занимаются разработкой программного обеспечения.

Git —

это система

управления версиями, с помощью которой вы сможете вести и контроли­

ровать разработку нескольких версий одного приложения, осуществлять
совместную разработку одного приложения несколькими разработчиками

(учитывать изменения, которые делаются на том или ином шаге разработки
тем или иным разработчиком). С помощью системы

Git у

вас будет полная

иерархия всех версий программного кода разрабатываемого приложения.

Данная книга представляет собой подробное практическое руководство по

Git, в

котором описывается

Git и

приводится разбор конкретных ситуаций

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

кой предварительной подготовки не требуется: по ходу изложения даются
все необходимые определения и пояснения. Лучший выбор, чтобы освоить

Git и максимально быстро начать его применять на практике.

Все права защищены . Ни какая часть данной книги не может быть воспроизведена в какой бы то ни было форме без пись­
менного разрешения владельцев авторских прав .

Издательство не несет ответственности за доступность материалов, ссылки на которые вы можете найти в этой книге . На
момент подготовки книги к изданию все ссылки на интернет-ресурсы были действующими .

15BN 978-5-94387-547-2
Контактные телефоны издательства :

(812)4127026
Оф ициальный сайт:

www.nit.com.ru

© Фишерман Л. В.

9 78 — 5- 94387- 547- 2

©

Наука и Техника (оригинал-макет)

Содержание
ГЛАВА

1.

ВВЕДЕНИЕ В

GIT ………………………………… 9

1. 1.

НЕОБХОДИМОСТЬ РЕЗЕРВНОГО КОПИРОВАНИЯ

1.2.

ЭТАПЫ РАЗВИТИЯ

1.3.

ЧТО В ИМЕНИ ТВОЕМ?

ГЛАВА
2.1.

2.

…………………….. 1 О

…………………………………………………………. 11
…………………………………………………….. 12

УСТАНОВКА

GIT ……………………………….. 13

ИСПОЛЬЗОВАНИЕ ДВОИЧНЫХ ДИСТРИБУТИВОВ

LINUX …. …………. 14

DeЬian/Ubuntu …….. ……. .. … ……………… …… …….. … …. .. .. ……. .. .. .. 15

Другие дистрибутивы ….. …… …….. ……. .. .. .. …. ……… …. ……… .. ….. 16

2.2.

ПОЛУЧЕНИЕ ИСХОДНОГО КОДА

2.3.

СБОРКА И УСТАНОВКА

2.4.

УСТАНОВКА

GIT

В

………………………….. .. ………………………. 18

WINDOWS ……………………………………………… 20

Установка пакета
Установка

ГЛАВА

3.

…. .. . …………………………………… 17

Cygwin Git …… … .. … ……. .. .. ….. … …… …… …. …… 21

msysGit ……………… …… ….. .. ….. … …. …… ….. .. ……. ……. 22

НАЧАЛО ИСПОЛЬЗОВАНИЯ

3. 1 .

КОМАНДНАЯ СТРОКА

3.2.

БЫСТРОЕ ВВЕДЕНИЕ В

…………………. 25

GIT …………………………………………………. 26
GIT … …………………………………………….. 29

Создание начального репозитария

.. …. ………. … …. …. …… …. … …. 29

Добавление файлов в ваш репозитарий ………………………………. 30

Неясные сообщения об ошибках ……………. … …….. … …….. … ……. 32
Настройка автора коммита (фиксации)

.. … …….. .. … .. …. … ….. …. .. 32

Вносим другой коммит (фиксацию) … … …. …. .. ….. …. .. … … … … …. .33
Просмотр ваших фиксаций

.. …. ………. .. .. ……. .. …….. … ……….. …. .33

Просмотр разницы между коммитами (фиксациями)

…. … … … …. 35

Удаление и переименование файлов в вашем репозитарии

Копирование вашего репозитария

….. .. 36

…… …… …. .. .. …. .. ……….. ….. … 37

3.3. ФАЙЛЫ КОНФИГУРАЦИИ …………… .. ………………………………….. 38
Настройка псевдонимов
Резюме

….. … …. .. ………… … …… ………. ….. …. ….. .40

….

……. …. …………. …….. .. ……. …. …. ……….. … … .. ……… … ….. .41

… .. . .. . . . . . . . . . . . . . . . .. . —.. —. — —…… —. -……… -… -…. -… -…. -.. —

Git. Практическое руководство

ГЛАВА
4. 1.

4.

БАЗОВЫЕ ПОНЯТИЯ

БАЗОВЫЕ ПОНЯТИЯ

………………………….. ………………… . ……… . . 43

Репозитарии

…….. .. ….. .. ……. … …. … …….. …… .. … .. .. ….. .. .. … … … .. .44

Типы объектов
Индекс

GIT …………………….. 42

Git .. … .. ……… …… ….. .. …….. ……. …….. ……….. … .. …44

……… …….. ….. ………… …… ……. .. …. .. … …. ….. ….. ……… … … 46

Глобально уникальные идентифи каторы

Git отслеживает

контент …. ………. .. .. … …… ….. ……………. ………. … 47

Путь по сравнению с содержанием
Расk-файлы

4.2.

……… ………….. … ….. .. … 47

….. .. ……………. .. ……… .. …. … .48

………. …. … …….. .. .. … .. ….. .. …. … .. …. … …. ……. … .. .. … .49

ИЗОБРАЖЕНИЯ ХРАНИЛИЩА ОБЪЕКТОВ

………………………………. 50

4.3. ПОНЯТИЯ GIT В ДЕЙСТВИИ ……………………………………………….. 53
Внутри каталога

.git ….. …. … … ……………… …….. ………….. .. …… … .. 53

Объекты, хэши , блобы ………… .. .. ….. …. … .. .. … … … ……… .. ……….. . 55
Откуда мы знаем , что хэш

SHA1

уникален ? ……… ……. …… …… .. … 55

Файлы и деревья ……………………………………….. …………….. .. … … 56
Примечание относительно использования

Иерархия деревьев

SHA 1 …. .. .. .. ….. .. …. .. . 57

…. ……. .. ………………. …………. .. .. … ….. … …….. 59

Фиксации ….. …. .. .. ……. .. .. …. .. ….. .. ….. .. …. …… …… … … … … .. .. … …. 60
Теги

………………… … ……………………………………… …. ……………… 62

ГЛАВА 5. УПРАВЛЕНИЕ ФАЙЛАМИ. ИНДЕКС …………. 65
5.1.

ВСЕ ОБ ИНДЕКСЕ …………………… . ……………………… .. ……………

67

5.2. КЛАССИФИКАЦИЯ ФАЙЛОВ В GIT ……… . ………………………………. 68
5.3.

ИСПОЛЬЗОВАНИЕ

5.4.

НЕКОТОРЫЕ ЗАМЕЧАНИЯ ОТНОСИТЕЛЬНО ИСПОЛЬЗОВАНИЕ

5.5.

ИСПОЛЬЗОВАНИЕ

GIT RM .••..•…•.••……………………••.••.•••••…..•… 75

5.6.

ИСПОЛЬЗОВАНИЕ

GIT MV …………. . ……………… …………………….. 78

GIT ADD ……………………………………………….. 70

GIT
COMMIT •.•…………………•…….•••.••.••.• •••.•.•.••.•. •..•………••… •• 73

5. 7. ЗАМЕЧАНИЕ ОТНОСИТЕЛЬНО ОТСЛЕЖИВАНИЯ ПЕРЕИМЕНОВАНИЙ. 80
5.8.

ПРОБЛЕМЫ С ОТСЛЕЖИВАНИЕМ ПЕРЕИМЕНОВАНИЯ

……………….. 81

5.9. ФАЙЛ .GITINGNORE ………….•….•..••.••.•..•.••.•.•…..•………..•••••..••.• 82

..

. .. . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Содержание

ГЛАВА б. КОММИТЫ (ФИКСАЦИИ) ……………………..

85

6.1. АТОМАРНЫЕ НАБОРЫ ИЗМЕНЕНИЙ …………………………………….. 87
6.2. ИДЕНТИФИКАЦИЯ ФИКСАЦИЙ …………………………………………… 88
Абсолютные имена фиксации

…. … ……. …. ……. …… …… …. … ……. . 89

Ссылки и символьные ссылки

… … … …… …. …. .. ……….. .. … … .. …… 90

Относительные имена фиксаций .. .. …… … .. …. .. …. .. ….. .. …. .. … … .. 92

6.3. ИСТОРИЯ ФИКСАЦИЙ ……………………………………………………… 95
Просмотр старых фиксаций
Графы фиксации

Использование

…. ….. … ….. …………. ….. .. .. .. …. ………. 95

………… … .. … ……… …………………….. ……… .. …… 98

gitk для

просмотра графа фиксации

… .. ….. …… 102

Диапазоны фиксаций …… .. .. … ……. ….. ……. … ………………………. 103

6.4.

ДОСТИЖИМОСТЬ В ГРАФАХ

……………………………………………. 104

6.5. ПОИСК ФИКСАЦИЙ ………………………………………………………. 108

ГЛАВА

7.

Использование

git

Ьisect

……. ……. ………. ….. ….. .. ……… ……. .. .. .. 108

Использование

git

Ыаmе

.. .. ……. … ….. ….. … … ….. .. ……… …. …. …. 114

Использование

Pickaxe ….. .. ….. …. …. … … … …. .. …………. .. ….. … .. 115

ВЕТКИ В

GIT ………………………………….. 117

7. 1.

ПРИЧИНЫ ИСПОЛЬЗОВАНИЯ ВЕТОК

7.2.

ВЕТКА ИЛИ ТЕГ?

………………………………….. 118

………………………………………………………….. 119

Имена веток … …… … ……… ……………. …… …. ………………………… 120

Правила именования веток

……….. … ……. .. … .. ………. ….. … … …. . 120

7.3.

ИСПОЛЬЗОВАНИЕ ВЕТОК ………………………………………………..

121

7 .4.

СОЗДАНИЕ ВЕТОК .. . ………………………………………………………

123

7.5.

ВЫВОД ИМЕН ВЕТОК ……………………………………………………..

124

7.6.

ПРОСМОТР ВЕТОК

……………………………………………………….. 125

7. 7. ПЕРЕКЛЮЧЕНИЕ ВЕТОК И ВЫГРУЗКА ФАЙЛОВ ……………………… 128
Базовое переключение между ветками

.. .. ………. …. ……. …… …. . 128

Переключение веток при имеющихся незафиксированных
изменениях .. ………… …. .. ….. ………………….. … … ….. …… .. …… …..
Объединение изменений в другую ветку

Создание новой ветки и переключение на нее

129

… … ….. …… ….. ….. ……. 131
.. ……. …… …. .. …. 133

. …

Отсоединение головы ветки .. ……. ………… …. … …. … .. ….. …… .. …

.. . . . -……………. -…….. -… -…. —. —… — — . — …. — . — — … — -·. -…….. —

135

Git.

Практическое руководство

7 .8.

УДАЛЕНИЕ ВЕТОК

ГЛАВА
8. 1.

8.

………………………………………………………… 136

РАЗЛИЧИЯ В

ФОРМЫ КОМАНДЫ

GIT ……………………………. 139

GIT DIFF ……………………………………………. 141

8.2. ПРОСТОЙ ПРИМЕР GIT DIFF ………………………………….. ………… 144
8.3. КОМАНДАGIТDIFFИДИАПАЗОНЫФИКСАЦИЙ ……………………… 148
8.4.

КОМАНДА

GIT DIFF С

ОГРАНИЧЕНИЕМ ПУТИ

Сравнение как

ГЛАВА
9.1.

9.

Subversion (SVN)

и

Git

…………………………. 151
получают разницы

.. …. … . 154

СЛИЯНИЯ ……………………………………..

ПРИМЕРЫ СЛИЯНИЯ

157

……….. . ………………………………………….. 159

Подготовка к слиянию …. … … … … ……. … …. .. … …. ….. ……. … ……..

Объединение двух веток

159

.. ……. .. … …….. … .. .. ….. ……… ……. …. … . 160

Слияние с конфликтом …….. … … …………….. …. ……………… … .. .. . 162

9.2.

РАБОТА С КОНФЛИКТАМИ СЛИЯНИЯ

………………………………….. 167

Обнаружение конфликтных файлов …….. ……….. ………. …. …. …..

168

Исследование конфликтов …….. ……. …. .. .. ….. .. …….. …….. ………

169

git diff с

конфликтами

….. … … …… …. ….. .. …… … .. ……. …… …. ……. 170

git log с конфликтами …….. …….. : ……. … ………. .. ……… …. …… …. . 173
Как

Git отслеживает

конфликты … ….. …………………….. ……. … ….

175

Завершение разрешения конфликта … …. ….. .. …… … … …… ……. . 177

Отмена или перезапуск слияния

9.3.

…. …. … …. … … … … .. ……… ….. … 179

СТРАТЕГИИ СЛИЯНИЯ …………………………………………………….

179

Вырожденные слияния … ….. ……………… .. …………………. .. ……. .. 183
Обычные слияния … … …… … .. .. …… … … ……. …………. …. ….. .. … .. .. 185
Рекурсивные слияния

… … … …. ……………… ……… ……. … … .. .. .. … 185

Слияния осьминога …………. .. …. …….. …………………….. .. ………..

186

Специальные слияния …….. .. … … …. ………… ………….. .. … ….. …. ..

187

9.4. ПРИМЕНЕНИЕ СТРАТЕГИЙ СЛИЯНИЯ ………………………………….. 187
Использование стратегий
Драйверы слияния
Как

Git думает о

ours

и suЬtree

…… .. …. … …. … … … ….. . 189

… …….. .. …. ………….. .. …. ………… … .. …………. 190

слияниях ………………………….. …………… .. … …..

Слияния и объектная модель

191

Git …. .. …. …………… …… ……………. 191

. …………………. . … . …………………………………………… . . .. .

Содержание
Слияние

squash ……. ……… … .. ….. …. .. ……. .. ….. … ………………… .. 192

Почему не выполнять слияние каждого изменения одно за

други м?

…………. …… … …. … ………… …… …………….. … ……………. 193

ГЛАВА 10. ИЗМЕНЕНИЕ КОММИТОВ (ФИКСАЦИЙ) … 195
1 О. 1.

ЗАЧЕМ ПРОИЗВОДИТЬ ИЗМЕНЕНИЯ ИСТОРИИ

10.2.

ИСПОЛЬЗОВАНИЕ КОМАНДЫ

GIT RESEТ .. ………………………….. 199

10.3.

ИСПОЛЬЗОВАНИЕ КОМАНДЫ

GITCHERRY-PICK …………………… 209

10.4.

ИСПОЛЬЗОВАНИЕ КОМАНДЫ

GIT REVERT ………………………….. 211

10.5.

КОМАНДЫ RESEТ,

REVERT

И

……………………. 197

CHECKOUT …………………………….. 212

10.6. ИЗМЕНЕНИЕ ПОСЛЕДНЕЙ ФИКСАЦИИ …………………. . ………….. 214
10.7. ПЕРЕБАЗИРОВАНИЕ ФИКСАЦИЙ …………………………………….. 217
Использование команды
Сравнение

ГЛАВА

11. STASH

rebase

И

и

git rebase -i .. ……………… … … … ……….. 220

merge …….. … .. ……. … … …….. ….. ….. … …….. . 225

REFLOG …………………………… 233

11 . 1 . STASH ………………….. .. ………………………………………………. 234
11.2. REFLOG ………………………………. , …………………………………. 246

ГЛАВА
12.1.

12.

УДАЛЕННЫЕ РЕПОЗИТАРИИ

…………….. 253

ПОНЯТИЯ РЕПОЗИТАРИЯ .. ……………………………………………..

Чистый репозитарий и репозитарий разработки
Клоны репозитариев
Удаленные

…. .. …….. .. …… …. .. … … …. ………. ………. …… 257

……. …………. ……. ……… .. … ……….. ……… .. … …….. ….. 258

Ветки отслеживания

12.2.

256

…. …… ………… 256

…. …………. .. ………. … … …….. …. .. ….. ………. 260

ССЫЛКИ НА ДРУГИЕ РЕПОЗИТАРИИ

… . ……………………………… 261

Ссылки на удаленные репозитарии

…. ………….. …… ……………… 262

Refspec … .. .. ………… ………….. .. .. … ……. .. …. ……………………… …. 264
12.3.

ПРИМЕРЫ ИСПОЛЬЗОВАНИЯ УДАЛЕННЫХ РЕПОЗИТАРИЕВ
Создание авторитетного репозитария

Создание вашей собственной удаленной

,

_

Разработка в вашем репозитарии
Передача ваших изменений

… ….. 267

…….. ……. …. … ….. .. …….. 268
origin ……………. …… .. 270

…. …. ………… .. …… ….. .. .. …… . 273

. . …

…….. .. …… .. .. .. .. .. ………. .. …… …….. . 274

— — — — — — —.. — -. —- .. — . —. —- . — — . — . —. — …. — ….. — . —.. —

Git.

Практическое руководство
Добавление нового разработчика

…… …. …… .. ……. …. .. .. …….. … 275

Получение обновлени й репози тария ……………. ……… …………… 278

12.4.

УДАЛЕННАЯ КОНФИГУРАЦИЯ ………………………………………….
Использование команды
Использование

285

git remote .. …… .. .. …… .. .. .. …. …. ………. 285

git config …. …. .. … … .. … …. .. …… ……….. .. …. ….. … 287

Редактирование файла конфигурации вручную … .. … .. …….. …. .. 288
Несколько удаленных репозитариев

12.5.

РАБОТА С ВЕТКАМИ ОТСЛЕЖИВАНИЯ

……………………………….. 289

Создание веток отслеживания

……………………………… ….. … ….. 289

Впереди и сзади

12.6. ДОБАВЛЕНИЕ
12. 7.

…………………. .. …………. … 288

ЧИСТЫЕ

.. … ….. .. … ….. ……. ……… … … ……. …… ……….. .. .. 293

И УДАЛЕНИЕ УДАЛЕННЫХ ВЕТОК

(BARE)

РЕПОЗИТАРИИ И КОМАНДА

………… ………… 295

GIT PUSH ……………. 297

— — — —- ——- ——- — — —— — — —— ————— —— —- — —— —-

.

Глава

1.

Введение в

Git

Git.

Практическое руководство

1.1.

Необходимость

резервного копирования
Ни один осторожный и творческий человек не начнет проект в наше время

без четкой стратегии резервного копирования. Данные эфемерны и могут
быть легко потеряны, например, в результате ошибочного изменения или
отказа диска. Очень разумно поддерживать оперативный архив всей своей

работы .
Для проектов , содержащих текст и код, стратегия резервного копирования

обычно включает управление версиями. Каждый разработчик в день может

создать несколько версий кода, а представьте, что над проектом работает це­
лая команда. Учитывая его основную роль , управление версиями является

наиболее эффективным, когда оно адаптировано в соответствии с привыч­

ками разработчика и целями команды проекта.
Утилита, которая управляет и отслеживает разные версии программно­

го обеспечения, обычно называется системой контроля версий

( version/
revision control system, VCS), менеджером исходного кода (source code
manager, SCM) и еще несколько вариантов , построенных путем перестанов­

ки слов « версия >>, « код1> , « управление 1>, и . Хотя авто-

— ————- — —— — —— —— ——— ——— —- — ———— — ——

_,

Глава

1.

Введение в

Git

ры и пользователи той или иной утилиты могут доказывать, что их утилита

лучшая, назначение каждой системы то же: разработка и обслуживание

репозитария контента, предоставление доступа к более старым редакциям

кода по дате, запись всех изменений в журнал. В этой книге мы будем ис­
пользовать термин система контроля версий

(VCS, version control system)

для всех утилит подобного рода.
В данной книге рассматривается утилита

Git — мощный и гибкий инстру­
Git был создан Линусом Торвальдсом для под­
держки разработки ядра Linux, но с тех пор он оказался полезен огромному
мент управления версиями.
числу других проектов.

1.2.

Этапы развития

Первая версия

Git

появилась в апреле

2005

года, а именно

7

апреля

( со­

общения были переведены на русский язык):

Author: Linus Torvalds
Date : Thu Apr 7 15:13:13 2005 — 0700
Первая версия «git», менеджера данных из ада
Немного позже была выполнена первая фиксация (коммит) ядра

Linux:

commit lda177e4c3f41524e886b7flb8a0clfc7321cac2
Author: Linus Torvalds
Date : Sat Apr 1 6 15:20:36 2005 — 0700
Linux- 2 . 6 . 12-rc2
Начальная сборка репозитария git. Я не волнуюсь относител ьн о
полной

истории,

создать

за хотим .

об ъем,

когда

у

Давайте

даже

отдельный

Тем

временем

который

нас

при

нет

сделал

хорошей

разорвем

том,

что

«исторический»

это
бы

3.2

она
архив

Гб

ранние

у

нас

Git

есть.
позже ,

диско в ого
дни

Git

инфраструктуры для

Мы

можем

если

мы

пространства

излишне

сложными,

нег о .

его!

Да, одна фиксация (коммит) представляла собой объем всего ядра

Linux.

Она состояла из:

17291 files changed ,

6718755 inserti ons( +),

О

deletions(-)

•.-.-.. —..————————————————————————811

Git.

Практическое руководство

Да, вы все правильно поняли:

6.7

миллионов строк кода!

Это было всего три минуты спустя, когда первый патч с использованием

Git
20
Linux (Linux Kernel Mailing List).

был применен к ядру. Убедившись, что он работает, Линус объявил о нем

апреля

2005 года в списке рассылки ядра

Приблизительно два месяца спустя с использованием
версия

Git

была выпущена

2.6.12 ядра Linux.

1.3.

Что в имени твоем?

Сам Линус рационализирует имя

«Git~, утверждая, что «Я — эгоцентричный
Linux, теперь
Git,>. Ведь Linux — это гибрид Linus и Minix. А в случае с Git Линус исполь­
зовал британский термин ttallltlon d the
Cygwin enmnnert as wel •• а1 ..Ьaequn updaes. The
Р91 thi!lt folow wll gLide )’OU throo.ф lhe i>ttalation.
Ple- note thi!lt we oriy i>ttal • ь..е aet d packages Ьу
defd. C)vwi, providet • t.ge ruml>erd packllplnl8’lg • wide vn,ty d PL’J)Otes .

You aw, llw• 111 thil progr,811 i!lt lt’f-i>thetш…to
ildd, «»»°ve· ar Ul)!rode pack- as песеоау .

Setup verslon 2.905 (Ы

Ыt)

Cop)’!l!;i.!000-2020
№>, ·11cygw1n

Рис.

2. 1.

coml

Установка

Cygwin

После выбора пакетов для установки нажмите

Next

несколько раз, пока

установка

Shell
меню

Cygwin не будет завершена. После этого запустите Cygwin Bash
Cygwin Tenninal (в зависимости от версии Cygwin) из вашего
Пуск, которая должна содержать программную группу Cygwin (рис.

или

2.3) .

.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . .. . . . . . . . . . . . .

Практическое руководство

Git.

о

IPendnQ

Е

v: s…,;,I

О к,.,р

1~
eu,.,.

Pock..,

—0.
ь,.,2

1.0.6-3

1.0.8-1

ca,certl’icite1

2.22-1

240-1
201,0218-1

2.111-1

«wk

4.2.1-1

«»‘

1.22.З.-1

317-1
5 10-1
1.22.4—1

по
~

.,_

6.5-2
530-1

67-1

2. 4.СБ- 1

2.4.48-2
2.33.1-2
1.0.8-1
2.33.1-2
1020-1

,252-2
106-3

ll>Ьludl

1Ы>l2_1


lid,kl
ll>gccl

7 .3.0-З

-10

112-1
6.1.2-1

IЬconv

114-З

1Ьconv2

1.14-3
523-1

….. s

~
..

1Ьр11«10

IЬ.-мrtcoltl

1Ьн11 О

.=.J'»»
.=.J «
..=.] ..

:j::
..=.] :-

113-1

6.2.0-2
116-2
116-2

.=.J»»

5.2.4·1

.=.]

IЬ•dc++o

7 30-З

lbl.!r!1_6
l>Widl

4.13·1

414-1

2.25.2-2

2.33.1·2

.•

••j

Рис.

~::
-=1 :-

.

~=
~=-=1:
~

.=.]

Te,d

Установка

LЬ,

LI>,
LЬ,

LЬ, , IW,
LЬ,
LЬ,

LЬ,
LЬ, _ IW,

u,,

Jk ~IЬf«~
104< llod

Cygwin

В качестве альтернативы вы можете собрать вашу собственную копию

Git
Windows, если ваша конфигурация Cygwin содержит
компилятора вроде gcc и make следуя тем же инструкциям, что и

из исходного кода в
утил иты
в

Linux.

Установка
Пакет

msysGit

msysGit

очень просто установить в

Windows,

поскольку этот па­

кет содержит все свои зависимости. В нем даже есть команды

(SSH)

Secure Shell

для создания ключей, генерирующихся для управления доступом к

репозитариям. Также

msysGit интегрируется с оболочкой Windows (Прово­

дником).

. ………………………………………………………………………..

Глава

Рис.

Первым делом загрузите

2.3.

Оболочка

последнюю

https://gitforwindows.org/ Файл,
ся примерно так Git-2.28.0-64.exe.

2.

Установка

Git

Cygwin

версию

инсталлятора по адресу

который вам нужно получить, называет­

После загрузки инсталлятора, запустите его. В процессе установки инстал ­

лятор спросит вас, как обрабатывать окончания строк

— в Windows-cтилe
Windows, выберите
использует Unix, выбе­

или Uniх-стиле. Если вся ваша команда работает в
Windows-cтиль, если же ваша команда в основном
рите Uniх-стиль.

Нажмите

Next несколько
Windows.

раз. Лучший способ запустить

msysGit —

через

Проводник

Дополнительно также будет установлен ярлык
позволяющая вводить команды

Git)

Git Bash (командная строка,

в меню Пуск в программную группу

Git. Поскольку большинство из примеров в этой книге используют команд­
ную строку, этот ярлык вам очень пригодится.

Все примеры в этой книге работают одинаково, что в

Linux, что

в

Windows,

но есть один нюанс:

msysGit для Windows использует старые имена команд
Git, как будет описано в разделе « Командная строка Git~ главы 3. В msysGit
нужно вводить git-add для git add .

. — — —- — —— ————— ——- ——- — ——— ———————— —

Глава

3.

Начало использования

·~
.1

.

2

r- —

(t-L,

:-·••- )
,

-‘-{к

…..

r’-(0

Git.

Git

Практическое руководство

управляет изменениями.

Git —

одна из систем управления версиями.

Множество принципов, например, понятие фиксации, журнала изменений,

репозитария, являются одинаковыми для всех инструментов подобного
рода. Но

Git

предлагает много новинок. Некоторые понятия и методы дру­

гих систем управления версиями могут работать по-другому в

Git

или не

работать вообще. Независимо от наличия вашего опыта работы с подобны­
ми системами, данная книга учит вас работать с

Git.

Давайте начнем!

3.1.

Командная строка

Git

Git очень просто использовать. Просто введите git без всяких
Git выведет свои параметры и наибол ее общи е подкоманды.

аргументов.

$ g it

g it [— vers i o n ] [— exec — pa t h [= GIT_E XEC_PATH]]
[- pl — pagin a t e l — no — p a ger] [ — bare ] [ — git — dir =GIT DIR]

.

E ! I — —···-················-··························-·· ····-·- ······· ·-···-··· ·····- ·

Глава

[—work-tree=GIT_WORK_TREE]

[—help]

Начало использования

3.

СОММАND

Далее приведены наиболее часто используемые команды

[ARGS]

git:

add Добавляет содержимое файла в индекс
bisect Выполняет бинарный поиск ошибки по истории фиксаций
branch Выводит, создает или удаляет ветки
checkout Проверяет и переключает на ветку
clone Клонирует репозиторий в новый каталог
commit Записывает изменения в каталог (фиксация)
diff Показывает изменения между фиксациями, рабочими
деревьями

и

т.д.

fetch Загружает объекты и ссылки из другого репозитария
grep Выводит строки, соответствующие шаблону
init Создает пустой репозитарий git или переинициализирует
существующий

log Показывает журналы фиксации
merge Объединяет две или больше истории
mv Перемещает или переименовывает файл ,
с имволическую

ссылку

pull

изменения

Получает

объ единяет

push

их

Загружает

с

из

локальным
изменения

удаленного
вашего

каталог

или

репозитария

репозитарием
из

разработки

или

и

локальной

локального

ветк ой

репозитория

в

у даленный

rebase Строит ровную линию фиксаций
reset Сбрасывает текущий HEAD в указанное состояние
rm Удаляет файлы из рабочего дерева и из индекса
show Показывает различные типы объектов
status Показывает состояние раб о чего дерева
tag Создает , выводит, удаляет или проверяет тег объекта,
подписанного с GPG
Чтобы вывести полный список подкоманд

git,

введите:

git help —all
Как видно из подсказки использования, имеется множество полезных оп­
ций для

git.

Большинство опций, показанных как

[ARGS],

применяются к

определенным подкомандам.

Например, опция

—version

применяется к команде

git

и производит вывод

номера версии:

·- —······ · ·········· ·· ······ ···· ·······················-·························-

it.

Практическое руководство

$ git —version
git version 2 . 29.0 . windows . l

А опция

$

—amend, наоборот,

относится к подкоманде

commit:

git commit —amend

В некоторых случаях придется указывать обе формы опция, например:

$

git —git-dir=project.g it repack -d

Получить справку по каждой подкоманде

git можно

следующими способа­

ми:

git help subcommand, git —help
Раньше у

Git

suЬcommand или

git

suЬcommand

— -help

был набор простых, отличных, автономных команд, разрабо­

танных согласно философии

«Unix toolkit:

небольшие и независимые ин­

струменты . Каждая команда начиналась со строки

git

и содержала дефис,

после которого следовало название выполнимого действия, например ,

commit и git-log.

Однако на данный момент считается, что должна быть одна

единственная исполнимая программа

git,

а выполняемые действия должны

передаваться в качестве параметров, например,
отметить, что формы команд

git commit и git log.
git commit и git-commit идентичны.

Примечание. Онлайн-документация по Git
www.kernel.org/pub/software/scm/git/docs/

Команды

git

$

Нужно

доступна по адресу

http://

понимают команды. Например, сле ­

дующие две команды

$

git-

git commit эквиваленты :

git commit -m » Fixed а typ o .»
git commit — — message= » Fixed а typo . «

В короткой форме используется один дефис, а длинная форма использует

два. Некоторые опции существуют т_олько в одной форме.
Наконец, вы можете разделить параметры из списка аргументов, используя

.> .

Настройка автора коммита (фиксации)

Перед коммитом (фиксацией) вам нужно установить некоторые параметры
конфигурации и переменные окружения. Как минимум,

Git должен знать
e-mail. Вы можете указывать эти данные при каждой коман­
де фиксации (git commit), как было показано ранее, но это очень неудобно.
ваше имя и ваш

Вместо этого лучше всего сохранить данную информацию в файле конфи­

гурации, используя команду

git config:

$ gi t config user . name » Фе дя Колобков «
$ git config user . email kolobok@lobok.com

…. . ….

·—· ·— …….. -········—·— ···- …. … ···· ···· ··· ….. ….. … …. . .

Глава

Вы также можете сообщить

Git свое

имя и свой

3.

Начало использования

e-mail, установив

перемен­

ные окружения GIТ_AUTHOR_NAME и GIТ_AUTHOR_EMAIL. Если
эти переменные окружения установлены , они перезапишут все параметры,

установленные в файле конфигурации.

Вносим другой коммит (фиксацию)

Чтобы продемонстрировать еще несколько функций

Git, давайте внесем не­

которые изменения и создадим сложную историю изменений внутри репо ­
зитария .

Откройте

index.html,

конвертируйте его в

HTML,

сохраните изменения и

выполните фиксацию изменений:

~/ puЫic

$

cd

#

редактируем

html
index . html

$ cat index . html

Мой

сайт

жив!

git commit index . html

$

Когда откроется редактор, введите описание фиксации, например,
+
Этот вывод должен выглядеть знакомым. Он напоминает вывод команды

Первая версия, 9da581d910c9c4ac93557ca4859e767f5caf5169, является
более ранней версией содержимого, а версия с именем ec232cddfЬ94e0dfd5b

diff.

5855af8ded7f5eb5c90d6 является более новой. Таким образом,
( +) предшествует каждой строке нового содержимого.

знак «плюс>,)

Вы испугались, глядя на эти шестнадцатеричные идентификаторы? Не

волнуйтесь,

Git

предлагает более лаконичные способы идентифицировать

фиксации без необходимости указания таких сложных чисел .

·——— ————————————————- —————————

Git.

Практическое руководство

Удаление и переименование файлов в вашем
репозитарии

Удаление файла из репозитарии аналогично добавлению файла, но вместо

команды

git add используется команда git nn.

талоге веб-сайта есть файл

poem.html,

Представим, что в нашем ка­

который больше не нужен.

cd ~/ puЬlic_html
1s
index.html p o em.html
$
$

$ git rm poem . html
rm ‘poem . html’
$ git commit -m «Удаляем поэму»
Created c ommit 364а708: Remove а
О files changed, О insertions(+),
delete mode 100644 poem.html

р о ет
О

deleti o ns(-)

Как и добавление, удаление состоит из двух этапов. Сначала
файл из репозитария, а затем

рии. Опция

git commit фиксирует

git rm удаляет

изменения в репозита­

-m позволяет указать описание фиксации,

например, ~Удаляем

поэму>>. Вы можете опустить эту опцию, чтобы задать сообщение в вашем
любимом текстовом редакторе.
Для переименования файла можно использовать комбинацию

add или же, что намного быстрее,

git rm

и

git

использовать команду git mv:

mv f o o.html bar.html
git rm f o o.html
rm ‘foo .html’
$ git add bar . html
$
$

В данном случае мы сначала переименовываем файл

foo.html в bar.html и
foo.html, как из репозитария , так и с файловой системы, после
чего добавляем файл bar.html в репозитарий .
удаляем файл

Эту же операцию можно выполнить с помощью одной команды:

$

git mv f o o.html bar.html

. … …………. ….. . ·······-······ ············ ……………………………. .

Глава

3.

Начало использования

После всего этого нам нужно фиксировать изменения:

$ git commit -m «Переимен о вание foo в bar»
Created commit 8805821 : Moved foo to bar
1 files changed, О insertions(+) , О deletions(-)
rename foo.html => bar.html (100 %)

Git обрабатывает операции перемещения файла иначе, чем другие системы,
используя механизм, основанный на базе подобия содержания между д:ву­
мя версиями файлов. Особенности механизма описаны в главе

5.

Копирование вашего репозитария
Ранее мы создали наш начальный репозитарий в каталоге

— / pu Ьlic_ html.

Теперь мы можем создать полную копию (или клон) этого репозитария ко­

мандой

git clone.

Сейчас мы создадим копию нашего репозитария в нашем домашнем катало­

ге, она будет называться

$
$

cd ~
git clone

my_ website:

puЫic_html

Хотя эти два репозитария

Git

my_website
теперь содержат те же объекты, файлы и ка­

талоги, есть некоторые тонкие различия. Исследовать эти различия можно
командами:

$

$

1s — lsa puЫic_html my website
diff — r puЫic_html my_website

На локальной файловой системе, подобно этой, использование
создаст копию репозитария подобно командам ер — а или

rsync.

git clone

Однако

Git

поддерживает богатый набор любых других источников, в том числе сете­

вые репозитарии. Эти формы источников и их использование будут объ­
яснены в главе

12.

Как только вы клонируете репозитарий, вы сможете изменять, делать но­
вые фиксации, исследовать журналы и историю и т.д. Это полностью новый
репозитарий со своей полной историей .

········ ··· ·········· ······························ · · · ··· · · · ·· ··· ··· ······ ········- —

Git.

Практическое руководство

3.3.

Файлы конфигурации

Конфигурационные файлы

Git — это

простые текстовые файлы в стиле

ini-

файлов. В них записываются различные установки, используемые многими

Git-командами . Некоторые установки представляю собой сугубо личные

предпочтения (например,

color.pager),

другие жизненно важны для пра­

вильного функционирования репозитария

( core.repositoryforrnatversion),
gc.auto).

а

остальные управляют поведением команд (например,

Подобно многим другим утилитам

Git поддерживает иерархию конфигура­

ционных файлов. В порядке уменьшения приоритета приведены его конфи­
гурационные файлы:

• .git/config —

специфичные для репозитария параметры конфигурации ,

которыми управляет опция

—file.

У этих настроек наивысший приори­

тет.

• -/.gitconfig- специфичные для пользователя параметры конфигурации,
которыми управляет опция —global.
• /etc/gitconfig- системные параметры конфигурации, изменить которые
можно опцией —systern, если у вас есть надлежащие права доступа Unix
(нужно право на запись этого файла). Данные настройки обладают наи­
меньшим приоритетом.

В зависимости от вашей инсталляции, системные настройки могут быть

где-то еще, возможно, в

/ usr/ local/ etc/ config,

или могут полностью отсут­

ствовать .

Например , для установки имени и

e-mail

пользователя, произведшего

фиксацию, нужно указать значения параметров

шем файле

$HOME/ gitconfig.

user.name

и

user.email в ва­
git config

Для этого используется команда

—global:
$
$

git config —glob a l user.name » Ф ед я Колоб к о в»
git config —global u s er.ema il «ko l obo k@l ob o k.com»

Можно установить специфичные для репозитария имя пользователя и

адрес электронной почты, которые переопределят глобальные установки,
для этого просто опустите флаг

—global:

— — ——————————————————————————— -·

Глава

$

$

3.

Начало использования

git config user.name » Федя Колобков «
git config user.email «kolobok@special — project.example.org»

Используйте

git config -1

для вывода всех переменных, найденных во всем

наборе файлов конфигурации:

#

Создаем

пустой

репозитарий

$ mkdir / tmp / new
$ cd /tmp/new
$ git init

#

Устанавливаем

некоторые

переменные

git config — — global user.name » Федя Колобков «
$ git config —global user.email » kol o bok@lobok . com «
$ gi t config user. email «kolobok@special-proj ect. example . org «
$

$ git config -1
user.name=Фeдя

Колобков

user.email=kolobok@lobok.com
core . repositoryformatversion=O
core . filemo~e=true
core . bare=false
core . logallrefupdates=true
user . email=kolobok@special-project.example . org
Поскольку файлы конфигурации

— это обычные текстовые файлы, вы може­
cat и отредактировать в любимом

те просмотреть их содержимое командой
текст ово м редакторе:

#

Посмотрим

на

параметры репозитария

cat . git / config
[core]
repos i toryformatversion
О
filemode = true
bare = false
logallrefupdates = true
[user]
email = kolobok@special-project.example.org
$

Или, если вы используете ОС от

Microsoft,

у вас будут некоторые измене­

ния. Скорее всего, ваш конфигурационный файл будет выглядеть примерно
так:

. ——— — — ——— — — — ————- — — — —. — — ————- -. —— — —

Git.

Практическое руководство

[core]
repositoryformatversion
filemode = true
bare = true
l o gallrefupdates
true
symlinks = false
ignorecase = true
hideDotFiles = dotGitOnly
Большинство из этих изменений

О

— из-за разницы в характеристиках файло­

вой системы. Отключены символические ссылки, включено игнорирование
регистра символов , другие настройки для скрытых файлов .

Используйте опцию

$

—unset для удаления

настройки:

git config —unset —global user.email

Для одной и той же цели существуют несколько параметров конфигурации

и переменных окружения. Например, редактор, который будет вызван при
создании сообщения журнала фиксации, можно задать с помощью:

Переменной окружения GIТ_E D IТOR

Опции конфигурации

Переменной окружения

Переменной окружения E D IТO R

Команды

core.editor
VISUAL

vi

Есть несколько сотен параметров конфигурации . По мере чтения книги я

буду обращать ваше внимание на самые важные из них. На странице руко­
водства

(man)

по команде

git config вы

найдете более подробный (и все же

не полный) список параметров конфигурации.

Настройка псевдонимов
Новичкам пригодится совет по настройке псевдонимов командной строки.
Часто команды

Git довольно

сложны, поэтому для самых часто используе­

мых команд вы можете создать псевдонимы:

— —— . — —— . ——— . -. — — — — — — . ——- — . — —— —— .. — — — . — . — -… -.

Глава

3.

Начало использования

$ git config —global alias .show — graph

‘l og — graph —abb rev — commit —p retty=oneline’
В этом примере я создал псевдоним

show-graph

и сделал его доступным в

любом созданном мной репозитарии . Теперь, когда я использую команду git

show-graph будет

выполнена длинная команда

git log со

всеми заданными

опциями.

Резюме
Конечно, у вас осталось много вопросов без ответа даже после прочтения
этой главы. Например, как

Git хранит каждую версию файла? Что на самом
деле представляет фиксация? Что такое ответвление? Что означает master?
Хорошие вопросы. Следующая глава определяет некоторую терминологию
и знакомит вас с определенными понятиями

Git .

.. . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . .. . . .. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Глава

4.

Базовые понятия

·1

.

.1

2

·J’,

.

3

— —:,
. ._

,,..,

,,.-…,,,……,

-·—· ·- :,.__; »;~
..

1

— О :::с;-·-

~

.._./ t -..__, —-

-,,~_

r

Git

Глава

4.

Базовые понятия

Git

Базовые понятия

4.1.

В предыдущей главе было рассмотрено типичное приложение

Git.

Скорее

всего, после ее прочтения у вас появилось гораздо больше вопросов, чем
было до того. Какие данные
значение каталога

.git?

Git хранит для каждой фиксации? Каково на­
ID фиксации напоминает мусор? Нужно ли

Почему

мне обращать внимание на него?
Если вы использовали другую

VCS,

например,

SVN

или

CVS,

команды,

представленные во второй главе, наверняка покажутся вам знакомыми. На
самом деле,

Git

служит для той же цели и предоставляет все операции, ко­

торые вы ожидаете увидеть в современной
нятия

Git отличаются,

VCS. Однако, Git некоторые по­

о чем мы и поговорим.

В этой главе мы выясним, чем отличается

Git от других VCS, исследуя клю­

чевые компоненты его архитектуры и некоторые важные понятия. В этой

главе мы сфокусируемся на основах взаимодействия с одним репозитари­

ем, а глава

12

объясняет, как работать с несколькими соединенными репо­

зитариями.

…… . -… -.. . —. . ……… -….. — .. . -.. . — -.. -… . -…. — .. . — .. . — .. . -… —

. …..

it.

Практическое руководство

Репозитарии
Репозитарий

Git — просто база данных, содержащая всю информацию, необ­
ходимую для управления версиями и историей проекта. В Git, как и в боль­
шинстве других систем управления версиями, репозитарий хранит полную

копию всего проекта на протяжении всей его жизни. Однако, в отличие от

большинства других

VCS, репозитарий Git

не только предоставляет пол­

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

Git

обслуживает ряд значений конфигурации. Вы

уже видели некоторые из них (имя пользователя и его

e-mail)

в предыду­

щей главе. В отличие от данных файла и других метаданных репозитария ,

параметры конфигурации не переходят из одного репозитария в другой при
клонировании. Вместо этого

Git

исследует конфигурацию и информацию

об установке на основе пользователя, сайта, репозитария.
В репозитарии

Git управляет двумя

основными структурами данных

— хра­

нилищем объектов и индексом . Все эти данные репозитария хранятся в кор­

не вашего рабочего каталога в скрытом подкаталоге с именем

.git.

Хранилище объектов разработано для эффективного копирования при опе­
рации клонирования как часть механизма, полностью поддерживающего

распределенный

VCS.

Индекс

— это

переходная информация, персональная

для репозитария . Индекс может быть создан или изменен по требованию в
случае необходимости .

В следующих двух разделах подробно рассмотрены хранилище объектов и
индекс.

Типы объектов
Сердце репозитария

Git

Git — это хранилище объектов.

Оно содержит ваши ис­

ходные файлы и все сообщения журналов, информацию об авторе, даты и
другую информацию , необходимые для сборки любой

версии или ветки

проекта .

В хранилище объектов
англ.

BLOB,

….

Вinагу

Git помещает объекты четырех типов: блобы ( от
Large Object), деревья, фиксации и теги .

——- —— — —— .. -………………………… — …… -.. -…… …… .

Глава

4.

Базовые понятия

Git

Блобы
Блобы

— каждая версия файла представлена как BLOB. BLOB — это аббре­
Large Object~, то есть большой двоичный объект. Этот

виатура для файлы считаются частью инфраструктуры или

конфигурации

Git.

Конечно, в

Git есть

набор команд по управлению этими

скрытыми файлами, но вы будете редко их использовать.
Изначально каталог

.git/ objects

(каталог для всех объектов

Git)

пуст, за ис­

ключением нескольких заполнителей:

$ find

.git / objects
.git / objects
. git / objects / pack
. git / objects / info

Теперь давайте осторожно создадим простой объект:

$

echo » hello world» > hello.txt

$ git add hello . txt
Если вы введете

«hello world1>

точно так же (без изменений в регистре сим­

волов или интервале между ними), ваш каталог объектов будет выглядеть
примерно так:

find .git / objects
.git / objects
.git / objects / pack

$

.git / objects / Зb
.git / objects / 3Ь/18e512dЬa79e4c8300dd08aeb37f8e728b8dad

. git / objects / info

—-

——. — -.. —-. ——-. —. — —. —.. —- —.. -.. · — —— —. —.. —- . — . —… —·.

Глава

4.

Базовые понятия

Git

Все это выглядит довольно таинственным. Но на самом деле все просто и в
следующем разделе вы поймете почему.

Объекты, хэши, блобы
Когда Git создает объект для hello.txt, он не беспокоится об имени файла
hello.txt. Его интересует только то, что в файле: последовательность из 12
байтов — строка «hello world~ и символ новой строки. Git выполняет не­
сколько операций на этом блобе, вычисляет его хеш SHA1 и помещает в
хранилище объектов как файл , в качестве имени файла используется вы­
численное значение хэша .

Откуда мы знаем, что хэш

SHA 1 уникален?

Есть чрезвычайно

небольшой шанс , что два различных блоба приводят к
тому же хэшу

SHA1.

Когда это происходит, эту ситуацию называют колли­

зией. Однако , коллизия

SHA1

так маловероятна, что практически никогда

не происходит.

SHA1 —

«криптографически безопасный хэш » . До недавнего времени не

было никакого известного способа (кроме слепой удачи) специально вы­
звать коллизию . Но ведь коллизия могла произойти непроизвольно? Да­
вайте посмотрим .

Учитывая

SHA1

160 бит,

у вас есть

2160 или 1048 (1

с

48

нулями после) возможных

хэшей. Это число просто огромно. Даже если бы вы наняли триллион

человек, чтобы произвести трилл ион новых уникальных блобов в секунду в

течение триллиона лет, у вас было бы приблизительно
Если бы вы прохэшировали

1043 блоба.

280 случайных блобов, вы бы могли найти кол­

лизию. Не верите нам? Пойдите почитайте Брюса Шнайера.

Хэш в этом случае
тов хэша

ЗЫ8e512dba79e4c8300dd08aeb37f8e728b8dad.

160

би­

20 байтам , а при отображении на экране в
— 40 байтов. Итак, наш контент сохранен как .git/
objects/Зb / 18e512dba79e4c8300dd 08aeb37f8e 728b8dad.
SHA1

соответствуют

шестнадцатеричном виде

Git

вставляет

/

после первых двух разрядов, чтобы повысить эффектив­

ность файловой системы. Производительность некоторых файловых си­

,

стем заметно падает, если поместить в один каталог слишком много файлов.

А если превратит первый

SHA1 байт в каталог, то это самый простой способ

… ……….. ……. … ………….. .. .. ……… ………………………… .

Git.

Практическое руководство

создать фиксированное разделение пространства имен для всех возможных
объектов с равным распределением.

Чтобы показать, что

Git

файла (это все еще строка

действительно ничего не сделал с содержанием

«hello world1> ), вы можете использовать хэш фай ­

ла, чтобы получить доступ к содержимому в любой момент:
$ git cat-file
hello wo rld

З Ы 8 e512 db a 79 e 4c8300 dd 08 aeb 37 f 8 e 7 28b 8 dad

Примечание.

Git

также знает, что

40

символов немного рискованно,

чтобы их вводить вручную , поэтому он предоставил команду для поис­
ка объектов по префиксу хэwа:

$ git rev-parse ЗЫ 8e512d
ЗЬ18e512dba79e4c8300dd08aeb37f8e728b8dad

Файлы и деревья
Теперь, когда блоб

«hello world,> безопасно помещен в хранилище объектов,
что произошло с его именем файла? Git был бы не очень полезен, если он не
мог бы найти файлы по имени.
Как было упомянуто выше,

объектов

— деревья .

Git отслеживает

Когда вы используете

пути файлов через другой вид

git add, Git сздает объект для со­

держания каждого добавленного вами файла, но он не создает объект для
вашего дерева сразу же. Вместо этого он обновляет индекс . Индекс хранит­

ся в

.git/ index и используется для отслеживания пути файла и соответству­
git add, git
rm или git mv, Git обновляет индекс, устанавливая новую информацию бло ­
ющих блобов. Каждый раз, когда вы выполняете команды вроде
ба и пути файла.
Создать объект дерева из вашего текущего индекса можно с помощью низ­
коуровневой команды

git write-tree.

Для просмотра содержимого индекса введите следующую команду

мент ее ввода индекс содержал только один файл

( на

мо­

— hello.txt):

$ git ls — files -s

..

1 00 644

ЗЫ8e51 2 db a 79 e 4 c 8300 d d08 aeb 37 f 8 e 728b8 da d

О

h ell o . txt

. .. . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . — .. — .. — …. -… — … —. — — ………… — . — .

Глава

4.

Базовые понятия

Git

Здесь мы видим, что файл hello.txt соответствует блобу ЗЫ8е5 …. Далее, да­
вайте получим состояние индекса и сохраним его как объект дерева:

git write — tree
68aba62e560c0ebc3396e8ae9335232cd93a3f60
$ find . git/objects
.git /ob jects
.git /objects / 68
.git / objects/68/aba62e560c0ebc3396e8ae9335232cd93a3 f60
. git/objects / pack
. git/objects/Зb
$

.git / ob jects / 3Ь/18e512dba79e4c8300dd08aeb37f8e728b8 dad

.git / objects / info
Теперь у нас есть два объекта: объект
объект, объект дерева, с

ID

«hello world»

с

ID

ЗЫ8е5 и новый

68аЬа6. Как видите, имя объекта соответствует

каталогу и файлу в каталоге

.git/ objects.

Но как выглядит само дерево? Поскольку дерево

— это тоже объект, подобно

блобу, вы можете использовать ту же команду для его просмотра:

$ git cat-file -р 68аЬаб
100644 ЫоЬ 3Ьl8e512dba79e4c8300dd08aeb37f8e728b8dad hello.
txt

Содержимое объекта просто интерпретировать . Первое число

— 100644 —

представляет атрибуты файла в восьмеричной системе, если вы работали
с

Unix, то вы с ними знакомы. Далее
— имя файла, связанное с блобом.

идет имя (ЗЫ8е5) объекта, а

Примечание относительно использования

hello.txt

SHA 1

Перед более подробным рассмотрением содержимого объекта дерева, да­
вайте посмотрим на очень важную функцию SНА1-хэшей:

git write-tree
68aba62e560c0ebc3396e8ae9335232cd93a3f60
$ git write-tree
68aba62e560c0ebc3396e8ae9335232cd93a3f60
$ git write-tree
$

,

……… . …………………………………………… . …….. . .. . …. .. . . .

Git.

Практическое руководство

68aba62e560c0ebc3396e8ae93 3 5232cd93a 3 f 6 0
Каждый раз, когда В ы вычисляете другой объект дерева для того же индек­
са, хэш

SHA1

остается неизменным.

Git не должен воссоздать новый объект

дерева. Если вы вводите эти команды на своем компьютере, то вы должны
увидеть те же хэши, что и приведенные в этой книге .

Хэш-функция

— истинная функция в

математическом смысле: для заданно­

го ввода она всегда производит один и тот же вывод.

Это чрезвычайно важно. Например, если вы создаете то же самое содержа­

ние как другой разработчик, независимо от того, где или когда или как вы

оба работаете, идентичный хэш

— доказательство полной идентичности со­

держимого.

Но задержитесь на секунду. Разве

SHA1

хэши не являются уникальными?

Что произошло с триллионами людей с триллионами блобов в секунду, ко ­
торые никогда не произведут одну единственную коллизию? Это частый
источник недоразумений среди новых пользователей

Git.

Внимательно

продолжайте читать далее, поскольку если вы сможете понять эту разницу,
тогда все остальное в этой главе

Идентичные хэши

SHA1

— просто .

в этом случае не считаются коллизией. Коллизия

это если два разных объекта производят один и тот же хэш . Здесь же мы соз ­
дали два отдельных экземпляра одного и того же содержимого, поэтому хэш

одинаковый (у одного и того же контента всегда будет одинаковый хэш) .

Git зависит от другого последствия хеш — функции SHA1: не имеет значения,
68aba62e560c0ebc3396e8ae9335232cd93
аЗfбО. Если оно есть у вас , вы можете быть полностью уверены, что это — тот
как вы получили дерево, названное

же древовидный объект, который , скажем , есть у другого читателя этой кни­
ги . Блоб, возможно, создал дерево , комбинируя фиксации А и В от Дженни

и фиксации С от Сергея, тогда как вы получили фиксацию А от Сью и об­
новление от Лакшми, которое комбинирует фиксации В и С. Результат — тот

же, и это существенно упрощает распределенную разработку.

Если вас попросили найти объект

68aba62e560c0ebc3396e8ae9335232cd93a
SHA1 — криптогра­

ЗfбО и вы можете найти именно этот объект, поскольку

фический хэш и вы можете быть уверены, что нашли именно те данные, по

которым был создан хэш.
Также истинно: если вы нашли объект с определенным хэшем в вашем хра­

..

нилище объектов, вы можете быть уверены , что у вас нет копии этого объек­

та. Хэш таким образом является надежной меткой или именем для объекта .

. . . .. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . .. . . . . . . . . . .

Глава

Но

Git

4.

Базовые понятия

Git

также полагается на что-то более важное, чем просто заключение.

Рассмотрим самую последнюю фиксацию ( или связанный с ней объект де­
рева). Поскольку она содержит, как часть ее контента, хэш ее родительский

фиксаций и ее дерево содержит хэш всех его поддеревьев и блобов. А это
означает, что хэш исходной фиксации однозначно определяет состояние це­

лой структуры данных, которая основана на той фиксации.

Наконец, импликации нашего требования в предыдущем абзаце приводят
к мощному использованию хеш-функции: она предоставляет эффективный

способ сравнения двух объектов, даже очень больших и сложных структур
данных без передачи этих объектов полностью.

Иерархия деревьев

Хорошо иметь информацию относительно одного файла, как было показано
в предыдущем разделе, но проекты обычно более сложны и содержат глубо­
ко вложенные каталоги, которые со временем перестраиваются и переме­

щаются. Давайте посмотрим, как

Git

обработает создание нового каталога,

в который мы поместим полную копию файла

hello.txt:

pwd
/ tmp / hello
$ mkdir suЬdir
$ ер hello.txt suЬdir /
$ git add suЬdir / hello.txt
$ git write-tree
492413269336d21fac079d4a4672e55d5d2147ac
$ git cat-file -р 4924132693
100644 ЫоЬ 3Ы8e512dЬa79e4c8300dd08aeb37f8e728b8dad hello.
txt
040000 tree 68aba62e560c0ebc3396e8ae9335232cd93a3f60 suЬdir
$

В новом корневом дереве теперь есть два элемента: исходный файл

и новый подкаталог

subdir,

который выводится как

Что же тут необычного? Посмотрите на имя объекта
друг

hello.txt

tree, а не как ЫоЬ.
subdir.

Это наш старый

— 68aba62e560c0ebc3396e8ae9335232cd93a3f60!

.. . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . .. . . . . . .. . . . .. . . . .. . . . . . . . . . . . . . . . . .. . .. .

Git.

Практическое руководство

Новое дерево для

subdir

содержит только один файл ,

содержит старый контент
глазах

строку

«hello world~.

hello.txt

и этот файл

Поэтому дерево

subdir

в

Git выглядит так же, как и корневой каталог.

Теперь давайте посмотрим на каталог

.git/objects

и посмотрим , на что по­

влияло это новое изменение:

$ find

. git/objects
.git /objects
. git/objects/49
. git/objects/49/2413269336d21fac079d4a4672e55d5d2147ac
. git/objects/68
.git/objects / 68 / aba62e560c0ebc3396e8ae9335232cd93a3f60
. git/objects/pack
. gi t/ obj ec ts /ЗЬ
. git/objects/3Ь/18e512dba79e4c8300dd08aeb37f8e728b8dad

.git /objects/ inf o
У нас все еще есть три уникальных объекта: блоб со строкой

«hello world,>;
дерево, содержащее hello.txt, в котором есть текст «hello world~ плюс новая
строка; второе дерево, которое содержит другую ссылку на hello.txt в первом
дереве.

Фиксации
Следующий объект для обсуждения
добавлен с помощью

writer-tree, вы

git add

— фиксации.

Теперь, когда

и был произведен объект дерева

hello.txt был
командой git

можете создать объект фиксации, используя следующие ко­

манды:

$ echo -n «Comrnit а file that says hellon»
1 git comrnit-tree 492413269336d21fac079d4a4672e55d5d2147ac
3ede4622cc241bcb09683af36360e7413b9ddfбc

Результат будет примерно таким:

$ git cat-file -р Зеdе462

tree 492413269336d21fac079d4a4672e55d5d2147ac
author Федя Колобков 1220233277 — 0500
committer Федя Колобков 1220233277 -0500

18—… -… —.·—.—……… -.—….-.. —…. -…—…. -.—.—… —.. —·. —.. ‘

Глава

Commit

а

4.

Базовые понятия

Gi

file that says hello

Если вы выполняете примеры из этой книге на своем компьютере, вы, веро­

ятно, обнаружили, что у объекта фиксации, сгенерированного вами, будет
другое имя, которое отличается от приведенного в книге. Если вы до сих

пор понимали все написанное, причина должна быть очевидной: это не та
фиксация. Ведь фиксация содержит ваше имя и время создания фиксации,

а эти данные в вашем случае будут отличаться. С другой стороны, у вашей
фиксации есть то же дерево, что и в примерах.

Это то, почему объекты фиксации отделяются от их объектов дерева: раз­
ные фиксации часто относятся к одному и тому же дереву. Когда это проис­

ходит,

Git достаточно умен, чтобы передать только новый объект фиксации,

который обычно крошечный, вместо копирования всего дерева и всех блоб ­
объектов, которые, наверняка, гораздо больше.
В реальной жизни вы можете (и должны) вызвать команды

git write-tree и
git commit. Вам не
нужно помнить все команды, чтобы быть счастливым пользователем Git.

git commit-tree, и

потом просто использовать команду

Основной объект фиксации довольно прост и содержит следующее:

Имя объекта дерева, который фактически идентифицирует связанные
файлы.

Имя человека, создавшего новую версию

(author) и время создания этой

версии.

Имя человека, который поместил новую версию

(commiter)

в репозита­

рий и время фиксации.

Описание версии (сообщение о фиксации) .

По умолчанию

author и commiter- это один и тот же человек.

Но существуют

ситуации, когда это разные люди.

Примечание. Вы можете использовать команду

git show —pretty=fuller

для просмотра дополнительной информации о заданной фиксации.

Объекты фиксации также хранятся в виде структуры графа, хотя эта струк­
тура полностью отличается от структур , которые используются объектами

дерева. Когда вы производите новую фиксацию, вы можете указать одну

························· ·· ········· ······································ · · · · · · · · — E I

Git.

Практическое руководство

или больше родительских фиксаций. Подробно о фиксациях мы поговорим
в главе

6.

Теги
Наконец, мы добрались до последнего объекта, которым управляет

Git — тег.
Git реализован тег только одного вида, на самом деле существует два
вида тегов — легковесный и аннотированный.
Хотя в

Легковесный тег

— это просто ссылка на объект фиксации и обычно он част­

ный для репозитария. Эти теги не создают постоянный объект в хранилище
объектов. Аннотированный тег более существенный и создает объект, со­
держащий сообщение, предоставленное вами и может содержать цифровую
подпись, созданную с помощью GРG-ключа согласно

Git

RFC4880.

обрабатывает обрабатывает как легковесные , так и аннотированные

теги, но по умолчанию большинство тегов

Git работают только с аннотиро­

ванными тегами , поскольку считают их или, проще говоря, > ready
$ echo somthing else >> notyet
$ git add ready notyet
$ git commit -m «Setup»
[master (root-commit) 71774al] Setup
2 files changed, 2 insertions(+), О deletions(-)
create mode 100644 notyet
create mode 100644 ready
# Изменяем файл «ready» и добавляем командой «git add»

его

в индекс

……………………….. .. ……………… .. .. … ……………. ……….. .

Git.

Практическое руководство

$ git add ready

#
#

Изменяем

файл

#

Добавляем новый

редактируем

«notyet»
«notyet»
файл

в

подкаталог,

но

не

добавляем его

в

репозитарий

$ mkdir subdir
$ echo Nope >> subdir / new

Используем

git status,

чтобы просмотреть изменения, требующие фик­

сации:

$ git status

# On branch master
# Changes to Ье committed :
# (use 11 gi t reset HEAD .. .

11

to unstage)

#
# modified: ready

#
# Changed but not updated:
11
git add … 11 to update what will

# (use

Ье

committed)

#
# modified: notyet

#
# Untracked files:
11
gi t add …
committed)

# (use

11

to include in what will

Ье

#
# subdir /
Здесь индекс подготовлен для фиксации только одного файла

с именем

ready, поскольку только этот файл был подготовлен (добавлен).
Однако, если вы запустите команду

git commit -all, Git

рекурсивно обой­

дет весь репозитарий, организует все известные, измененные файлы. В

этом случае, когда ваш редактор представит шаблон сообщения фиксации,

он должен указать, что измененный и известный файл

notyet

тоже будет

фиксироваться:

# Please enter the commit message for your changes .
# (Comment lines starting with ‘#’ will not Ье included)
# On branch master
# Changes to Ье committed :
# (use 11 git reset HEAD … 11 to unstage)

#

. . ……………………….. …. .. … …… …… .. … ……. … …… ….. … ..

Глава

5.

Управление файлами. Индекс

# modified: notyet
# modified: ready

#
# Untracked files:
# (use «git add . . . » to include in what will
committed)

Ье

#
# subdir /
Наконец, поскольку каталог с именем
ни один из файлов , даже опция

subdir/ новый и в нем не находится
—all не заставит его фиксироваться:

Created commit db7de5f: Some —all thing.
2 files changed, 2 insertions(+), О deletions(-)

Git рекурсивно обойдет репозитарий в поисках измененных и файлов . Пол­
ностью новый каталог subdir/ и всего его файлы не станут частью фиксации.
Написания сообщений журнала фиксации

Если в командной строке вы явно не указываете сообщение журнала,

Git

запустит редактор и предложит вам написать его. Будет запущен установ­

ленный в вашей конфигурации редактор. Как установить редактор, было
показано в главе

3.

Если вы выйдете из редактора без сохранения,

Git

будет использовать пу­

стое сообщение журнала. Если вы уже сохранили сообщение, но еще не
вышли из редактора, вы можете удалить сообщение и опять сохранить

да

— тог­

Git тоже сохранит пустое сообщение фиксации.

5.5.
Команда

Использование

git rm, как и ожидается,

обратна для

git add.

git rm
Она удаляет файл из

репозитария и рабочего каталога. Однако удаление файла может быть более

проблематичным (если что-то пойдет не так), чем добавление файла. По­
этому

Git относится

к удалению файла с большей осторожностью .

·———————————————————————————- —

Git.

Практическое руководство

Git

может удалить файл только из индекса или одновременно из индекса и

рабочего каталога.

Git не

может удалить файл только из рабочего каталога,

для этого используется команда операционной системы

nn.

Удаление файла из каталога и из индекса не удаляет историю файла из ре­

позитария. Любая версия файла до момента удаления хранится в хранили ­
ще объектов и не будет оттуда удалена.
Давайте представим, что у нас есть некоторый файл, который мы еще не

добавили в репозитарий (не выполнили команду
удалить его командой

git add),

и мы пытаемся

git nn:

$ echo «Random stuff» > oops

#
#

Не можем удалить
Нужно

файл,

использовать

не добавленный в

команду

репозитарий

«rm oops»

$ git rm oops
fatal : pathspec ‘ oops’ did not match any files
Теперь
команду

давайте

добавим

файл

командой

qit add ,

а

затем

выполним

qet status :

# Добавляем файл
$ git add oops
$ git status
# On branch master

#
# Initial commit

#
# Changes to Ье committed:
# (use «git rm —cached … » to unstage)

#
# new file: .gitignore
# new file: data
# new file : oops

#
Чтобы конвертировать файл из подготовленного в неподготовленный, ис­

пользуйте команду

git rm —cached:

$ qit ls-files —staqe
100644 0487f44090ad950f6195527lcf0a2d6c6a83ad9a
. gitignore
100644 e476983f39f6e4f453f0fe4a859410f63b58b500

…..

О
О

data

_,

—————— ———— —————- — —- ———- . —. — —. — — —

Глава

5.

Управление файлами. Индекс

100644 fcd87b055f 2 61557434fa9956e6ce29433a5cdlc
$ git rm —cached oops
rm ‘ oops ‘
$ git ls-files —stage
100644 0487f44090ad950f61955271cf0a2d6c6a83ad9a
.gitignore
100644 e476983f39f6e4f453f0fe4a859410f63b58b500
Обратите внимание:

git rm —cached

О

oops

О
О

data

удаляет файл только из индекса, но

оставляет его в рабочем каталоге, в то время как команда

git rm

удаляет

файл, как из индекса, так и с рабочего каталога.

Примечание. Использование команды

git rm —cached делает файл не­

отслеживаемым, в то время как его копия остается в рабочем ката­
логе. Это довольно опасно, так как вы можете забыть о нем, и файл

больше никогда не будет отслеживаемым. Будьте осторожны!

Если вы хотите удалить файл, как только он был зафиксирован, просто от­
правьте запрос через команду

git rm :

$ git comrnit -m «Add some files»
Created initial commit 5Ь22108: Add some files
2 files changed , 3 insertions(+) , О deletions(-)
create mode 100644 .gitignore
create mode 100644 data
$ git rm data
rm ‘ data ‘
$ git status
# On branch master
# Changes to Ье committed :
# (use » git reset HEAD … » to unstage)

#
# deleted : data

#
Перед удалением файла

Git

проверяет, соответствует ли версия файла в

рабочем каталоге последней версии в текущем ответвлении (в версии, ко­
торую команды

Git

называют

HEAD).

Эта проверка устраняет случайную

потерю любых изменений, которые, возможно, были сделаны в файле .

.——— — . —- — . — . — ——.. ———- — . — . —- — —— —- —. ————

it.

Практическое руководство

Примечание. Используйте команду

git nn -f для

принудительного уда­

ления вашего файла. В этом случае файл будет удален , даже если он
был изменен с момента последней фиксации.

Если вам нужно сохранить файл, который вы случайно удалили, просто до­

бавьте его снова:
$ git add data

fatal: pathspec ‘ data’ did n o t match an y files
Ошибочка вышла!
тесь,

VCS

Git

ведь удалил и рабочую копию тоже! Н о не волнуй­

содержит отличный механизм восстановления старых версий

файлов:

$ git checkout НЕАD — data
$ cat data
Н о вые
Еще

данные

немн о го

новых

данных

$ git status
# On branch master
nothing to commit (wo rking directory clean)

5.6.

Использование

git mv

Предположим, что вам нужно удалить или переименовать файл. В ы можете

использовать комбинацию команд

git rm

(для удаления старого файла) и

(для добавления нового файла) . Или же вы можете использовать не­

git add

посредственно команду

файл с именем

stuff и

git mv. Представим,

что в нашем репозитарии есть

вы хотите переименовать его в

newstuff. Следующие

две последовательности действий являются эквивалентными:

$ mv stuff newstuff
$ git rm stuff

$ git add newstuff

..
или

$ git mv stuff newstuff

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . .. . . . . . . . . . . . . . . . .. . . .. . . . . . . . . . .

Глава

В обоих случаях

newstuff,

Git

удалит путь

stuff

Файл

Управление файлами. Индекс

из индекса, добавит новый путь

сохраняя оригинальное содержимое

реассоциирует это содержимое с путем

5.

stuff в
newstuff.

хранилище объектов и

data мы уже восстановили, теперь давайте его переименуем в mydata:

$ git mv data mydata
$ git status

# On branch master
# Changes to Ье committed:
# (use «git reset HEAD . .. » to unstage)
#
# renamed : data — > mydata

#
$ git coппnit -m » Переместил данные в хранилище»
Created commit ec7d888: ПеренесТИJI данные в хранилище
1 files changed , О insertions(+) , О deletions(-)
rename data => mydata (100 %)
Если вы проверите историю файла, вы можете быть немного удивлены, ког­
да увидите, что

Git, очевидно, специально потерял историю исходного фай ­

ла и помнит, только, что данные были переименованы:

$ git log mydata
commit ec7d888b6492370a8ef43f56162a2a4686aea3b4
Author : Федя Колобков
Date : Sun Nov 2 19 : 01:20 2020 -0600
Moved data to mydata

Git

все еще помнит всю историю, но отображает только то, что касается

определенного имени файла, указанного в команде. Опция

Git отследить журнал

—follow

просит

и найти всю историю, связанную с контентом:

$ git log —follow mydata
commit ec7d888b6492370a8ef43f56162a2a4686aea3b4
Author: Федя Колобков
Date : Sun Nov 2 19:01:20 2020 -0600

Moved data to mydata
commit 5b22108820b6638a86bf57145a136f3a7ab71818

‘—— —· ··-···

……………. — — …………. ………. -· ··-·- — …. …….

. ..

Git.

Практическое руководство

Author :

Федя Колобков

Date : Sun Nov 2 18 : 38 : 28 2020 -0600
Add some files
Одна из классических проблем многих

VCS

заключается в том, что после

переименования файла невозможно отследить его историю. В

Git

эта про­

блема решена.

5. 7.

Замечание

относительно отслеживания

переименований
Давайте немного подробнее рассмотрим отслеживание переименований
файла.

SVN,

как пример традиционного управления версиями, производит боль ­

шую работу по отслеживанию во время переименования/перемещения
файла, поскольку она отслеживает только разницу между файлами. Если
вы перемещаете файл, то это, по сути, то же, что и удаление всех строк из

старого файла, и их добавление в новый файл. Но передавать все содержа­
ние файла каждый раз, когда вы делаете простое переименование, очень не­

эффективно. Подумайте о том, что будет, если нужно переименовать целый
подкаталог с тысячами файлов.

Чтобы облегчить эту ситуацию,

SVN явно отслеживает каждое переимено­
вание. Если вы хотите переименовать hello.txt в subdir/ hello.txt, вы должны
использовать команду svn rnv вместо команды svn rm и svd add. Иначе SVN
никак не поймет, что это переименование и ему придется пойти по неэф­

фективному пути удаления/добавления, что и было описано выше.
Затем, учитывая эту исключительную функцию отслеживания переиме ­

нования,

SVN нуждается

в специальном протоколе, чтобы сказать его кли­

ентам: ~переместите файл
клиент

hello.txt в subdir/ hello.txt~. Кроме того, каждый
SVN должен убедиться , что выполнил эту работу правильно .

— — — -··· ·························· ········· ····· ·· ······· ·····························

Глава

Git, с другой стороны,
стить или скопировать

5.

Управление файлами. Индекс

не отслеживает переименование. Вы можете переме­

hello.txt куда угодно, но это

влияет только на объек­

ты дерева. Помните, что объекты дерева хранят отношения между содержи­
мым, тогда как само содержимое хранится в блобах. Посмотрев на разницу

между двумя деревьями, становится очевидным, что блоб с именем ЗЬ18е5
переместился в новое места.

В этой ситуации, как и во многих других, система хранения

на хэше, упрощает много вещей по сравнению с другой

5.8.

Git,
RCS.

основанная

Проблемы с

отслеживанием
переименования
Отслеживание переименования файла порождает постоянные дебаты среди
разработчиков

VCS.

Простое переименование

— объект

разногласия. Аргументы становятся еще

более весомыми, когда изменяется и имя, и содержимое файла. Тогда сце­
нарий переговоров переходит от практического к философскому. Что это:
переименование или новый файл (раз у него другое содержимое и другое

имя)? Насколько новый файл подобен старому? Если вы применяете чей­
то патч, который удаляет файл и воссоздает подобный в другом месте, как
это обрабатывать? Что произойдет, если файл переименован двумя различ­
ными способами на двух разных ветках? Какая тактика менее подвержена
ошибкам: используемая в

Git или в SVN?

В реальной жизни, похоже, что система отслеживания переименований, ис­

пользуемая в

Git,

очень хороша, поскольку есть много способов переиме­

новать файл и человек может просто забыть уведомить

SVN

об этом. Но

помните, что нет идеальной системы для обработки переименований, к со­
жалению

.

·- -······· ········· ················ ····· ······ ·································-· ·-

Git.

Практическое руководство

5.9.

Файл

.gitingnore

Ранее в этой главе было показано, как использовать файл

main.o. Чтобы
файл .gitignore,

.gitignore для иг­

норирования файла

проигнорировать любой файл, просто

добавьте его имя в

который находится в этом же катало ­

ге. Вы также можете игнорировать файлы где угодно, добавив его в файл

.gitignore, который находится в корневом каталоге вашего репозитария.
Но

Git

предоставляет более богатый механизм . Файл

.gitignore

может со­

держать список шаблонов имен файлов , указывающий, какие файлы нужно
игнорировать . Ф ормат

.gitignore следующий:

Пустые строки игнорируются, как и строки, начинающиеся с решетки

( #). Такие строки можно использовать для комментариев, однако символ
# не представляет комментар ий, если он не является первым в строке.

Обычные имена файлов соответствуют файлу в любом каталоге сука­
занным именем.

Имя каталога отмечается с помощью слеша

(/).

Это правило соответ­

ствует любому каталогу или любому подкаталогу, но не соответствует
файлу или символической ссылке.

Шаблон может содержать маски оболочки, такие как звездочка(*). Звез­
дочка может соответствовать единственному имени файла или каталога.

Также звездочка может быть частью шаблона, включающего наклонные

черты для обозначения имен каталогов, например, debug/32Ьit/* .о.

Восклицательный знак(!) инвертирует смысл шаблона оставшейся ча­
сти строки. Дополнительно, любой файл , исключенный предшеству­

ющим образцом, но соответствующий этому правилу инверсии, будет
включен . У инверсии более высокий приоритет.

Кроме того ,

Git

позволяет вам создавать файл

.gitignore

в любом каталоге

вашего репозитария. Каждый такой файл влияет на свой каталог и все под­
каталоги. Правила

.gitignore

каскадные: вы можете переопределить прави­

ла в каталоге более высокого уровня, включив инвертированный шаблон ( с
использованием

! в начале правила)

в одном из подкаталогов.

Приоритет игнорирования следующий:

Шаблоны, определенные в командной строке

. ………………… .. … … ………. ……….. .. ……….. … ……………..

Глава

Шаблоны, прочитанные из файла

5.

Управление файлами. Индекс

.gitignore,

находящего в том же ката­

логе

Шаблоны в родительских каталогах. Шаблоны, находящиеся в текущем
каталоге, будут перезаписывать шаблоны родительского каталога, сле­

довательно, шаблоны более близкого родителя перезапишут шаблоны
родителя более высокого уровня


Шаблоны из файла
Шаблоны

из

.git/ info/ exclude

файла,

указанного

переменной

конфигурации

core.

excludefile.
Пocкoлькy.gitignore обрабатывается как обычный файл в вашем репози­
тарии, он копируется во время операций клонирования и применяется ко
всем копиям вашего репозитария.

Если образец исключения, так или иначе определенный для одного вашего
репозитария, не должен применяться к какому-нибудь клону этого репози­

тария, то шаблоны должны находиться в файле

.git/ info/ exclude, поскольку

он не копируется во время операций клонирования. Формат его шаблонов
полностью совпадает с форматом файла

.gitignore.

Рассмотрим другой сценарий. Нам нужно исключить файлы

* .о , сгенериро­

ванные компилятором из исходного кода. Для игнорирования этих файлов

поместите шаблон * .о в файл

.gitignore самого верхнего уровня.

Но что если

в определенном каталоге у вас есть определенный . о файл, который нужно

отследить? Тогда у вас может быть примерно эта конфигурация:

$
$

cd my_package
cat .gitignore

* . о

cd my_pa ckage / vendor files
cat .giti gnore
!driver.o

$
$

Данная конфигурация игнорирует все .о файлы в репозитарии, но
отслеживать одно исключение

— файл driver.o в

Git будет
подкаталоге vendor_files .

·—————·——————·····-··—···—···-··-·-···-··-·············-···C!I

Глава

6.

Коммиты (фиксации)

Git.

В

Практическое руководство

Git

коммит (или фиксация) используется для записи изменений в репо­

зитарий.

На первый взгляд кажется, что фиксация

другой

VCS.

Но на самом деле фиксация

Git не отличается от фиксации в
Git работает своим собственным ,

уникальным образом.
Когда происходит фиксация ,

Git

записывает снимок индекса и помеща­

ет этот снимок в хранилище объектов (подготовка индекса для фиксации

была рассмотрена в главе

5).

Данный снимок не содержит копию каждого

файла и каталога в индексе, поскольку бы такая стратегия потребовала бы
огромных затрат дискового пространства. Вместо этого

Git

сравнивает те­

кущее состояние индекса с предыдущим и получает список измененных/

добавленных/удаленных файлов и каталогов.

Git

создает новые блобы для

каждого измененного файла и новые деревья для каждого измененного ка­

талога. Если же файл/каталог не изменился, используются уже имеющиеся

блоб/дерево.
Снимки фиксации объединяются в цепочку, в которой каждый новый сни­
мок указывает на своего предшественника. Со временем последовательно­

сти изменений могут быть представлены как серия фиксаций.

Вам может показаться очень (в плане системных ресурсов) срав­

нивать индекс с некоторым предшествующим состоянием. Но все же про-

. — —— — — . — — —… -… -.. -……. — …… … .. . — — — . — -· —… -.. . —. . .. -·-,

Глава

6.

цесс удивительно быстр, потому что у каждого объекта

Коммиты (фиксации)

Git есть

SНА1-хэш.

Если у двух объектов, даже у двух поддеревьев, один и тот же SНА1-хэш,
значит, объекты идентичны.

Git может избежать ряда рекурсивных сравне­

ний, сокращая поддеревья, у которых то же самое содержимое.
Есть взаимно-однозначное соответствие между рядом изменений в репози­

тарии и фиксацией. Фиксация

единственный способ представления из­

менений в репозитарии, и любое изменение в репозитарии должно быть
представлено фиксацией. Этот мандат обеспечивает отслеживаемость. Ни
при каком обстоятельстве данные репозитария не должны изменяться без
записи изменения! Просто вообразите хаос, если содержимое в главном ре­
позитарии было изменено и при этом небыло бы никакой записи о том , как
это произошло, кто внес изменения или почему.

Хотя фиксации чаще всего производятся явно, то есть разработчиком,
может самостоятельно произвести фиксацию. В главе

Git
9 мы поговорим о та­

ких неявных фиксациях при слиянии репозитариев.
Когда именно фиксировать изменения

значительной степени ваше дело

и зависит от ваших предпочтений или стиля разработки. В целом вы долж ­
ны выполнить фиксацию в четко определенные моменты времени, когда

ваша разработка достигает определенного этапа, например, когда было вы­
полнено тестирование, когда все идут домой после рабочего дня и еще по
огромному числу других причин .

Git

нормально относится к частым фиксациям и обеспечивает богатый на­

бор команд для управления ними. Позже вы увидите, как несколько фикса­

ций, каждая с небольшими, но четко определенными изменениями , могут
привести к лучшей организации изменений и более простому манипулиро­
ванию наборами патча.

6.1.

Атомарные наборы

изменений
Каждая фиксация

Git представляет единственный,

атомарный набор изме­

нений относительно предыдущего состояния. Независимо от числа катало­

гов, файлов, строк или байтов , которые изменяются фиксацией, или при­
меняются все изменения, или ни одно

.

·————————————————————————————

Git.

Практическое руководство

С точки зрения базовой объектной модели атомарность просто целесоо­
бразна: снимок фиксации представляет общий набор измененных файлов
и каталогов. Он должен представлять одно состояние дерева или другое, а

набор изменений между этими двумя снимками состояний представляет
полное преобразование дерево-дерево (разницы между фиксациями описа­
ны в главе

8).

Рассмотрим поток операций по перемещению функции из одного файла в

другой . Если вы выполняете удаление одной фиксацией, а добавление — дру­
гой фиксации, то останется небольшой «семантический разрыв ~ в истории
вашего репозитария, вовремя которого пропала функция. Две фиксации в

обратном порядке тоже проблематичны. В любом случае перед первой фик­
сацией и после второй ваш код семантически непротиворечивый, но после
первой фиксации код является дефектным.

Данную проблему можно решить с помощью атомарной фиксации, которая
одновременно удаляет и добавляет функцию
Однако атомарная фиксация одновременно удаляет и добавляет функцию
без всякого семантического разрыва в истории репозитария. О том, как луч­
ше организовать ваши фиксации, будет написано в главе

Git

10.

все равно , почему изменяются файлы. То есть содержание изменений

не имеет значения. Как разработчик, вы можете переместить функцию из

одного файла в другой и ожидать, что эта операция будет обработана как
одно унитарное перемещение. Но, альтернативно, вы можете фиксировать

удаление и чуть позже

— добавление .

При этом

Git

будет все равно, ведь он

не имеет никакого отношения к семантике того, что находится в файлах.
Атомарность позволяет вам структурировать свои фиксации и в конечном

счете вы можете быть уверенными, что

Git

не оставил ваш репозитарий в

некотором переходном состоянии между одним снимком фиксации и дру­
гим.

6.2.

Идентификация

фиксаций
Программируете ли вы самостоятельно или в составе команды очень важно

идентифицировать отдельные фиксации. Например, для создания ветвле•

. ….. ….. .. ………. ….. …. …. …. … …… …….. …….. .. … …………..

Глава

6.

Коммиты (фиксации)

ния вы должны выбрать фиксацию, с которой можно начать; для сравне ­
ния двух вариантов кода нужно указать две фиксации; для редактирования

истории фиксации нужно предоставить набор фиксаций. В

Git

вы можете

обратиться к каждой фиксации по явной или неявной ссылки.
Вы уже видели явные ссылки и несколько неявных ссылок. Уникальный,
40-разрядный шестнадцатеричный SНА1-идентификатор

ка, а

HEAD,

— это явная ссыл­

которая всегда указывает на наиболее последнюю фиксацию,

это пример неявной ссылки. Однако , ни одна из ссылок не является удобно.
К счастью,

Git обеспечивает

много разных механизмов именования фикса­

ций, каждый из которых более или менее полезен в той или иной ситуации.
Например, при обсуждении определенной фиксации с коллегой, работа­
ющим над теми же данными, но в распределенной в среде, лучше исполь­

зовать имя фиксации, которое гарантировано будет одинаковым в обоих
репозитариях. С другой стороны, при работе со своим локальным репозита­
рием проще использовать относительное имя.

Абсолютные имена фиксации
Самое строгое имя фиксации

— ее

идентификатор хэша.

ID

хэша

— это

абсо­

лютное имя, которое может относиться только к одной фиксации. Не имеет
значение, где в репозитарии находится эта фиксация,

ID

хэша всегда уни­

кально и идентифицирует одну и ту же фиксацию .

Каждый идентификатор фиксации глобалыю уникален , не только для одно­
го репозитария , а для всех репозитариев . Например, если разработчик пи­
шет вам и ссылается на определенный

ID фиксации в его репозитарии и при
ID, это значит,

этом в своем репозитарии вы находите фиксацию с таким же

что у вас обоих есть одинаковая фиксация с одинаковым содержимым.
Поскольку 40-разрядное шестнадцатеричное SНА1-число утомительно и

подвержено ошибкам,

Git

позволяет вам сокращать это число до уникаль­

ного префикса в пределах базы данных объектов репозитария. Рассмотрим
пример из собственного репозитария

Git:

$ git log -1 —pretty=oneline HEAD

lfbb58b4153e90eda08c2b022ee32d90729582e6 Merge git : // repo .
or . cz/git -gui

·——- ————————————————————————- —-

Git.

Практическое руководство

$ git log -1 —pr etty=oneline lfЬb
error : sho rt SHAl lfbb is amЬiguous.
fatal: amЬigu o us argument ‘lfbb’ : unknown revision or path
not in the working tree.

Use ‘—‘ to separate paths from revisi ons
$ g i t log -1 —pretty=onel i ne lfЬb58
lfbb58b4153e90eda0 8c2b022e e 32d90729582eб

Merge git : // repo.

or . cz / git-gui
Несмотря на то, что имя тега не является глобально уникальным именем, в

данном случае оно абсолютно указывает на уникальную фиксацию и не из­
меняется в течение долгого времени (если вы явно не измените его).

Ссылки и символьные ссылки

Ссылка

— это SНА1-хэш, который относится к объекту в хранилище объ­
Git. Хотя ссылка может ссылаться на любой объект Git, она обычно
ссылается на объект фиксации. Символическая ссылка — это имя, косвенно
указывающее на объект Git. По сути, это тоже ссылка.
ектов

Локальные имена ветки, удаленные имена ветки и имена тегов

все это

ссылки .

У каждой символической ссылки есть явное, полное имя, которое начинает­

ся с

.git/ refs/ репозитария . Обычно представле ­
refs/: refs/ heads/ refs — локальные ответвления,
refs/ remotes/ ref ваши удаленные ответвления и refs/ tags/ ref — ваши теги
(ответвления подробно описаны в главах 7 и 12).
refs/

и хранится в каталоге

но три пространства имен в

Например, локальное ответвление с именем

dev

является короткой фор­

мой refs/ heads/ dev. Удаленные ветки находятся в пространстве имен refs/
remotes/, поэтому имя origin/ master на самом деле соответствует имени
refs/ remotes/ origin/ master. А тег v2.6.23 является коротким именем для
refs/ tags/ v2.6.23.
Вы можете использовать, как полное, так и короткое имена, но если у вас

есть и ветвление и тег с одинаковыми именами , учтите, что
совпадение с указанным именем в следующем порядке
для

git rev-parse):
,

.

Git будет искать
( см. страницу man

—— ············—······—··················-·········————- —— ———·

Глава б. Коммиты (фиксации)

.git / ref
.git / refs / ref
.git/refs/tags/ref
.git / refs / heads / ref
.git / refs / rernotes / ref
.git / refs / rernotes / ref / HEAD
Первое правило обычно только для нескольких ссылок, описанных поз­
же:

HEAD, ORIG_HEAD, FETCH_HEAD, CHERRY PICK_HEAD
MERGE HEAD.

и

Примечание. Технически, имя каталога

Git (.git) можно изменить. По­
Git использует переменную окружения $GIT_DIR
каталога .git.

этому документация
вместо имени

Рассмотрим несколько специальных символьных ссылок, которые

Git

ис­

пользует для разных целей.

HEAD
Ссылка

HEAD всегда указывает на самую последнюю фиксацию в текущей
HEAD обновляется так, чтобы она снова

ветке. Когда вы изменяете ветки,

указывала на самую последнюю фиксацию , но уже в новой ветке.

ORIG HEAD
Некоторые операции , например, слияние и сброс, записывают предыдущую
версию

HEAD

в

ORIG_HEAD.

Вы можете использовать

ORIG_HEAD для

восстановления предыдущего состояния или сравнения.

FETCH HEAD
При использовании удаленных репозитариев команда

ет ~головы ~ всех веток, выбранных в файле

HEAD —

git fetch

записыва­

.git/ FETCH_HEAD. FETCH_

это короткое имя последней выбранной ветки и оно допустимо

сразу после операции выборки. Подробно об этой ссылке мы поговорим в
главе

12 .

.. . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . .. . —- . -.. —· — .. — .. —

. . . …

Git.

Практическое руководство

MERGE HEAD
Указывает на верхушку ветки, с которой только что сделано слияние . П о­
нятно, что данная ссылка имеет смысл только после процесса слияния .

Все эти символические ссылки управляются командой

Примечание.

Xoni

git symbolic-ref.

вы можете создать собственную ветку с этими спе­

циальными именами ссылок (например,

HEAD),

это не очень хорошая

идея .

Существуют и другие специальные имена ссылок. Два таких имени, каретка

С) и тильда

(-),

используются чаще всего и будут описаны в следующем

разделе.

Относительные имена фиксаций

Git также предоставляет механизмы для идентификации фиксации относи­
тельно другой ссылки.

Вы же видели

некоторые из этих имен , например, masterл, где masterл всегда

относится к предпоследней фиксации на ветке
вы можете использовать masterлл ,

master-2

master.

Есть и другие формы:

и даже более сложную форму

вроде master-1oл2-2 л 2.

За исключением первой корневой фиксации, каждая фиксация получена,

по крайней мере, из одной более ранней фиксации и, возможно, многих
других предков , которые называются родительскими фиксациями. Если у
фиксации есть несколько родител ьских фиксаций, значит, она

результат

работы слияния. Ведь в результате будет одна родительская фиксация для
каждой ветки.

Символ каретки используется для выбора родительской фиксации. Пред­

ставим , что у нас есть фиксация С, тогда с л 1
сация, с л2

— это первая родительская фик­

— вторая , сл з — третья и т.д. , см. рис. 6.1.

— — — —- — ——————— — —————— —- — — — — —- — ——- —.

Глава

Рис.

6 . 1.

6.

Коммиты (фиксации)

Несколько родительских имен

Тильда используется для возврата назад и выбора предшествующего по ­
коления: С-1

первый родитель, С-2

— первый

прародитель, С-2

— первый

прапрародитель. Вы можете заметить, что для ссылки на первого родителя

используется, как ссылка с л 1, так и С-1. Обе ссылки верны, что и показано
на рис.

6.2.

Рис.

6.2.

Несколько родительских имен

. . . ..

.-…… ———— . —.. -. -… -…. -.. —… -…. -.. — -… — —.. -.. —…. — . — —

Git.

Практическое руководство

Git

позволяет использовать сокращения и комбинации имен ссылок. На­

пример, е л и с-

— ЭТО то же самое, что и

сл 1 и С-1 соответственно. слл

— это

то же самое, что и сл 1 л 1, что означает ~первый родитель первого родителя

фиксации С» и то же самое, что и С-2.
Используя команды:

git show-branch

— -more=ЗS

и ограничив вывод

последними строками, вы можете изучить историю

графа и исследовать сложную структуру слияния ветвления:

$ git rev- parse master
lfbb58b4153e90eda08c2b022ee32d90729582e6

I tail -10
[master ~ lSJ Merge branch ‘maint’
— [master ~ З л 2 л ] Merge branch ‘maint — 1 . 5.4’ into maint
+* [mаstеr~З л 2 л 2 л ] wt-status.h: declare global variaЫes as
extern
[master ~ З л 2 ~ 2] Merge branch ‘maint-1.5.4’ into maint
[master ~ lб] Merge branch ‘lt / core — optim’
+* [master ~ lб л 2] Optimize symlink / directory detection
+* [master ~17] rev-parse —verify: do not output anything
on error
+* [master ~18] rev-parse : fix using «—default» with
«—verify»
+* [master~19] rev-parse : add test script for » — — verify»
+* [master ~20] Add svn-compatiЫe «Ьlame» output format to
git-svn
$ git show-branch —more=ЗS

$ git rev- parse

mаstеr ~ з л 2л2 л

32efcd91c6505ae28f87c0e9a3e2b3c0115017d8
Между

master-15

и

master-16

имело место слияние, которое представ­

ляло несколько других слияний, а также простую фиксацию с именем

mаstеr-зл 2 л 2 л. Это, оказывается, фиксация

32efcd91c6505ae28f87c0e9a3e2

b3c0115017d8.
Команда

git rev-parse — окончательное решение при переводе любой формы
— тега, относительной, сокращенной или абсолютной — в актуаль­

фиксации

….

ный, абсолютный идентификатор в пределах базы данных объектов.


.

— -. —- . — — .. —. . —.. — .. —-. . . — .. —.. —.. — -. — —- ·— . — .. —-. -. —. —.. — . —

Глава

6.3.

6.

Коммиты (фиксации)

История фиксаций
Просмотр старых фиксаций

Основной командой для просмотра истории фиксаций является

git log.

У

нее довольно много опций, параметров, средств форматирования, селекто­

ров и прочих возможностей. Но не беспокойтесь! Вам совсем не обязатель­
но знать все ее параметры.

Если команда git log вызвана без параметров, она работает как git log

HEAD,

то есть выводит сообщение журнала, связанное с каждой фиксацией в ва­
шей истории, которая доступна из

ются с фиксации

HEAD.

Показанные изменения начина­

HEAD и будут выведены~ обратном хронологическом по­
Git придерживается

рядке. Но вспомните, что при перемещении по истории

графика фиксации, а не времени .

Если вы введете команду

git log

, вывод начнется с указанной

фиксации. Следующая форма команды полезна для просмотра истории вет ­
ки:

$ git log master

commi t lfbb58b4153e90eda08c2b022ee32d90729582e6
Merge: 58949ЬЬ . . . 76ЬЬ40с .. .
Author: Junio С Harnano
Date : Thu Мау 15 01 :31 : 15 2020 — 0700
Merge git : // repo . or.cz/git — gui

* git : // repo. or . cz/git -gui:
git-gui: Delete branches with ‘git branch -D’ to clear
config
git-gui : Setup branch . rernote,rnerge for shorthand git-pull
git-gui: Update Gerrnan translation
git-gui: Don’t use ‘$$cr rnaster ‘ with aspell earlier than
0.60
git-gui: Report less precise objec t estirnates f o r
database cornpression

….

.—- — ————- —— —- — — ————— . —.. -.. — — -. —— — —— — —

Git.

Практическое руководство

commi t 58949bЫ8a1610d109e64e997c41696e0dfe97c3
Au thor : Chris Fr e y
Da te : Wed Мау 14 19 : 22 : 18 2020 — 0400
Doc umentation / g it-p r u ne . txt : document u n p acked logic
Clarifies the gi t-p r une ma npage , documen ti n g t h at it on l y
pru nes unpacked objects .
Si g n ed- off- by : Chris Frey
Si gned — off- by : Junio С Hamano
commit c7ea453618e41e05a0 6 f05e3ab63d555d0ddd7d9

Журналы авторитетные, но откат назад через всю историю фиксации ваше­
го репозитария , вероятно, не очень практичен. Как правило , ограниченная

история более информативна. Один из методов

— ограничить историю опре­

деленным диапазоном фиксаций, используя диапазон от …до. Пример:

$ git log — -pretty=short
master~ lO

—aЬbrev-commit

master~12 ..

commit бd9878с …
Au t hor : Jeff Ki n g
clone : bs d s h e l l p orta bility fix
commit 30684d f …
Au t hor : Jeff King
t5000 : t a r po rtabil i ty fix
Здесь gi t

1О-ой

low показывает фиксации между master-12 и master-1 О или между
master. Подробно диапазоны фиксаций

и 11 — ой фиксациями в ветке

описаны в разделе , в то время как «фиксация

включена~ .

6.4.

Достижимость в графах

В теории графов узел Х является достижимым из узла А, если вы може­
те начать с узла А, filel
Файл

file 1 был

модифицирован в рабочем каталоге, но не был помещен в

индекс. Это еще не ситуация, изображенная на рис.

8.1,

но вы можете уже

произвести сравнение. Вы должны ожидать вывод, если вы сравниваете ра­

бочий каталог с индексом или с существующими Н ЕАD- версиями . Однако
между индексом и

HEAD не должно быть никаких различий, поскольку ни ­

чего еще не помещено в индекс.

1111————.—..-.—.. -…. -… -… -…—… -.-..-… -·……….. -.. -………-_,

Глава

#

рабочий

катал о г

vs

8.

Различия в

Git

индек с

$ git diff

diff —git a / filel Ь/filel
index 257cc56 . . d90bda0 100644
— a / filel
+++ Ь/filel
@@ — 1 +1 @@
— foo
+quux
#

рабочий

катал о г

v s HEAD

$ git diff НЕАD

diff —git a / filel Ь/ filel
index 257сс56 . . d90bda0 100644
— a / filel
+++ Ь/filel
@@

-1 +1 @@

-foo
+quux
#
$

индекс VS HEAD
git diff —cached

$

Теперь нужно подготовить файл

file1

(поместить его в индекс). Давайте сде­

лаем это:

$ git add filel
$ git status
# On branch master

# Changes t o Ье committed:
# (use «git reset HEAD .. . » t o unstage)

#
# modified: filel
Здесь дублируется ситуация, описанная рисунком

8.1.

Поскольку

file1

те ­

перь добавлен в индекс, рабочий каталоги и индекс синхронизированы и
между ними не будет разницы. Однако теперь есть разюща между НЕА D­
версией (то есть репозитарием) и версией, которая находится в рабочем ка­
талоге и индексе

.

.—— ———————— ——- ——— — ———————————-

Git.

Практическое руководство

#

рабочий каталог

$

git diff

vs

индекс

каталог vs HEAD
g it diff HEAD
diff —git a / filel Ь/filel
index 257сс56 .. d90bda0 100644
— a/filel
+++ Ь/filel
@@ -1 +1 @@
-foo
+quux

#

рабочий

$

индекс

vs HEAD
git diff —cached
diff —git a / filel Ь/filel
index 257cc56 .. d90bda0 100644
— a/filel
+++ Ь/filel
@@ -1 +1 @@
-f oo
+quux
#

$

Если вы теперь запустите

git commit, новая фиксация поместит изменения,
(git diff—cached), в репозитарий. Команда
git diff —cached является синонимом команды git diff —staged.
показанные последней командой

Теперь давайте посмотрим, что произойдет, если вы отредактировали файл

file1

перед фиксацией? Давайте посмотрим!

$ echo «baz» > filel

vs индекс
git diff
diff —git a / filel Ь/filel
index d90bda0 .. 7601807 100644
— a/filel
+++ Ь/filel
@@ -1 +1 @@
-quux
+baz
#

рабочий каталог

$

#

рабочий каталог

g it diff HEAD
diff —git a / filel

vs HEAD

$

Ь/filel

……………………………………………………………………..

Глава

8.

Различия в

Git

index 257сс56 .. 7601807 100644
— a / filel
+++ Ь/filel
@@ -1 +1 @@
-foo
+baz
vs HEAD
git diff — cached
diff —git a / filel Ь/filel
index 257сс56 .. d90bda 0 100644
— a / filel
++·+ Ь/filel
@@ -1 +1 @@
-foo
+quux
#

индекс

$

Все три diff-операции показывают теперь какую-то из форм различия. Так

какая же версия будет фиксирована? Запомните,

git commit работает

с со­

держимым индекса, то есть будет зафиксирована версия файла со словом

«quux~.
$ git commit -m «quux

uЬer

alles»

[master] : crea ted f8aelec : «quux uber alles»
1 files changed , 1 insertions(+ ), 1 deletions(-)
Теперь в хранилище объектов есть две фиксации. Давайте испробуем об­

щую форму команды

git diff и

# предыдущая НЕАD-версия
$ git difi НЕАDЛ НЕАD

сравним обе эти две фиксации:

против

тек ущей

diff — git a/file l Ь/filel
index 257сс56 .. d90bda0 100644
— a / filel
+++ Ь/ filel
@@ -1 +1 @@
-foo
+quux
Эта разница подтверждает, что предыдущая фиксация изменила
ка

.

·-······· ··· · ·· ·· ··· ········ ··········· ······· ·· ···· ············ ·· ·· ··· ······· ·· ·· t l i l

Git.

Практическое руководство

Неужели сейчас все синхронизировано? Нет! Ведь копия файла в рабочем
каталоге содержит строку

«bazi,,.

$ git diff
diff — git a/filel Ь/filel
index d90bda0 .. 7601807 100644
— a/filel
+++ Ь/filel
@@

-1 +1 @@

-quux
+baz

8.3.

Команда

git diff и

диапазоны фиксаций
Существуют еще две дополнительных формы команды

ют отдельного объяснения, особенно на фоне команды

git diff и
git log.

они требу­

Команда git diff поддерживает синтаксис двух точек для представления раз­
ницы между двумя фиксациями. Следующие две команды являются экви­
валентными:

$
$

git diff master bug /p r-1
git diff master .. bug / pr-1

же синтаксис в команде

К сожалению, синтаксис двух точек в

git diff означает нечто другое, чем тот
git log, с которой вы познакомились в главе 6.

Стоит сравнить git diff и

git log, поскольку эти команды по-разному обраба­

тывают диапазоны фиксаций. Вот что нужно иметь в виду :

Git diff не беспокоится

об истории файлов, которые она сравнивает, так­

же она ничего не хочет знать о ветках.

Git log

строка» производит поиск последних

50

Git, оп­
master

фи ксаций в ветке

для изменени й, содержащий указанную строку.

$ git diff -S»octopus» master~SO
d i ff — git a / Documentation / RelNo tes — 1 . 5.5 . 3 . txt
Docume ntat i on / RelNotes — 1 . 5.5 . 3 . txt
new file mode 100644
index 0000000 .. f22f98b
— / dev / null
+++ Ь/Documentati on/RelNotes-1 . 5 . 5.3.txt
@@ — 0 , 0 +1 , 12 @@
+GIT vl . 5 . 5 . 3 Release Notes
+==========================

Ы

+
+Fixes since vl . 5.5.2

+—————— -+
+ * «g it send- email — — compose» did not notice that non — asci i
c ontents
+ needed some MIME magic .
+
+ * «git fast — export» did n ot export oc topus merges correctly .

,
+

+Also comes with va ri ous d ocumentati o n updates .

……………………………………………………………………… . .

Git.

Практическое руководство

Использование опции

-S уже было рассмотрено в главе 6, поэтому вы долж­

ны быть уже знакомы с ней.

Сравнение как

Subversion (SVN)

и

Git получают

разницы

Большинство систем, таких как

CVS или SVN, отслеживает серию версий и

хранит просто изменения между каждой парой файлов. Этот метод позво­
ляет сохранить дисковое пространство и сократить издержки. Внутренне
такие системы проводят много времени, думая о вещах как «серии измене­

ний между А и В». Когда вы обновляете свои файлы центрального репо­
зитария, например,

SVN

помнит, что при предыдущим обновлении файла

репозитарий был в версии

r1095, а сейчас репозитарий находится в версии
r1123. Таким образом, сервер должен отправить вам разницу между r1095 и
ri 123. Как только ваш SVN-клиент получит эти разницы, он может вклю­
чить их в вашу рабочую копию и воспроизвести r1123 ( с помощью этого
трюка SVN избегает отправки вам всего содержания всех файлов при каж­
дом отправлении).

Чтобы сохранить дисковое пространство,

SVN также хранит свой собствен­

ный репозитарий как серию изменений на сервере . Когда вы просите пока­

зать разницу между

r1095 и r1123, он ищет отдельные различия для каждой

версии между теми двумя версиями, объединяет их в одну большую раз­
ность и отправляет вам результат. Но
Как вы видели, в

Git

Git работает иначе.

каждая фиксация содержит дерево, которое является

списком всех файлов и каталогов, затронутых этой фиксацией. Каждое де­
рево независимо от всех других деревьев. Пользователи

о различиях и патчах, поскольку они все еще очень

Git все еще говорят
полезны . Все же, в Git

разница и патч

— производные, а не фундаментальные данные. Если вы по­
.git, то не увидите ни одной разницы, а если заглянуть в
SVN, то он состоит преимущественно из различий.

смотрите в каталог

репозитарий

Git,

как и

SVN,

способен получить полный набор различий между двумя

произвольными состояниями . Но

между версиями

r1095

и

r1123,

SVN

нужно смотреть на каждую версию

в то время как

Git

не заботится о промежу­

точных шагах .

. . … ……….. ……………………………………………….. .. …. ….. ..

Глава

У каждой ревизии есть свое собственное дерево, но

Git

8.

Различия в

Git

не требует его для

создания разницы , поскольку он может оперировать со снимками полного

состояния каждой из этих двух версий. Эта простая разница в системах хра­

нения

— одна из

наиболее важных причин того, что

Git быстрее,

чем другие

RCS .

•.———————————————————————————-ID

Глава

9.

Слияния

.1

7.
.

2

.»‘—1

~

Git.

Практическое руководство

Git — это

распределенная система управления версиями

(Distributed VCS).

Она позволяет разным разработчикам, например , когда один находится в
Японии, а другой в

— Нью-Джерси, независимо вносить изменения в проект.

В любое время эти два разработчика могут комбинировать свои изменения
без наличия центрального репозитария. В этой главе вы узнаете, как объ­
единить две или больше линий разработки.
Слияние объединяет две или более веток истории фиксаций. Чаще всего

слияние объединяет всего две ветки, хотя

большего числа веток
В

Git

Git

поддерживает объединение

(3, 4 и даже больше).

слияние должно происходит в пределах одного репозитария

все

ветки, которые нужно объединить, должны находиться в одном и том же
репозитарии. Как эти ветки попали в репозитарий

дите в главе

— не важно (как вы уви­
12, в Git есть механизм, позволяющий ссылаться на удаленные

репозитарии и помещать удаленные ветки в ваш текущий рабочий репози­
тарий) .

Когда изменения в одной ветке не конфликтуют с изменениями, найден­
ными во второй ветке,

Git

вычисляет результат слияния и создает новую

фиксацию, которая представляет новое, унифицированное состояние. Но
когда ветки конфликтуют,

Git

отмечает такие конкурирующие изменения

I D —-··················· ········ · ··· ···················· · ·· ············ · ···········

Глава

как «необъединенные~

9.

Слияния

(unmerged), а разработчик уже сам принимает реше­

ние, какое из изменений нужно принять .

9.1.

Примеры слияния

Чтобы объединить ветку
переключиться на ветку

branch с
branch, а

веткой

other_branch,

вам нужно сначала

затем выполнить слияние новой ветки в

текущую:

$ git checkou t b ran ch
$ g i t merge o the r_b ran c h

Теперь давайте рассмотрим пример слияний, один без конфликтов и один с
существенными перекрытиями . Для упрощения примеров в этой главе мы

будем использовать методы , представленные в главе

7.

Подготовка к слиянию
Прежде, чем начать слияние, нужно произвести генеральную уборку в ва­

шем рабочем каталоге. Во время обычного слияния

Git

создает новые вер­

сии файлов и помещает их в ваш рабочий каталог, когда слияние будет
завершено .

Git

также использует индекс для хранения временных и про­

межуточных версий файлов во время операции слияния.

Если вы изменили файлы в вашем рабочем каталоге или вы модифицирова­

ли индекс посредством git add или git rrn, тогда у вашего репозитария «гряз­
ный,> рабочий каталог или индекс . Если вы начнете объединение в таком
« грязном,> состоянии,

Git не сможет правильно скомбинировать изменения

из других веток.

Примечание. Не всегда нужно начинать с «чистого» каталога .

Git

вы­

полнить слияние , например, если измененные ( « грязные» ) файлы в

рабочем каталоге и затрагиваемые слиянием файлы не пересекаются.
Однако все же рекомендуется взять за правило начинать каждое сли ­

яние с чистого рабочего каталога и индекса, что в будущем позволит
избежать многих проблем .

… . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Git.

Практическое руководство

Объединение двух веток
Давайте рассмотрим простейший сценарий. Мы настроим репозитарий, со­

держащий один файл, затем создадим две ветки, а затем

выполним объ­

единение этих двух веток.

$ git init

Initialized empty Git repository in / tmp/conflict/.git/
$ git config user.email «kolobok@lobok . com»
$ git config user.name « Федя Колобков »
$ cat > file

Line 1 stuff
Line 2 stuff
Line 3 stuff
ло

$ git add file
$ git coппnit -m «Initial 3 line file»

Created initial commit 8f4d2d5 : Initial 3 line file
1 files changed, 3 insertions(+), О deletions(-)
create mode 100644 file
Давайте создадим другую фиксацию на ветке

rnaster:

$ cat > other file
Here is stuff on another file !
ло

$ git add other_file
$ git coппnit -m «Another file»

Created commit 76ld917 : Another file
1 files changed , 1 insertions(+) , О deletions( — )
create mode 100644 other file
Итак, у нас есть репозитарий, в котором создана одна ветка с двумя фикса­
циями , каждая фиксация представляет новый файл. Далее, давайте пере­
ключимся на новую ветку и модифицируем пер вый файл:

$ git checkout

-Ь alternate masterл
Switched to а new branch «alternate»
$ git show-branch
* [alternate] Initial 3 line file
! [master] Another file

ID———————————————————————————.

Глава

9.

Слияния

+ [master] Another file
*+ [alternate] Initial 3 line file
Здесь видно, что ветка alternate изначально создана из фиксации masterл , то
есть из предпоследней фиксации в ветке.

Внесите простые изменения в файл, чтобы у вас было что объединять, и за­
тем фиксируйте эти изменения. Помните, что лучше начать слияние с «чи ­

стого~ рабочего каталога.

$ cat >> file
Line 4 alternate stuff
л о

$ git conпnit -а -m «Add alternate’s line 4 »
Created cornmit Ь384721: Add alternate ‘ s line 4
1 files changed, 1 insertions(+) , О deletions( — )
Теперь у нас есть две ветки и каждая из них содержит определенную работу
разработчика. Второй файл был сначала добавлен в ветку

был модифицирован в ветке

alternate.

master, а затем он

Поскольку изменения не относятся

к одной и той же части общего файла, слияние должно пройти гладко и без
происшествий.
Операция

git merge

чувствительна к контексту. Ваша текущая ветка всег­

да является целевой веткой, а другая ветка

( или ветки) будет объединена
с текущей веткой. В этом случае ветка alternate должна быть объединена с
веткой master, поэтому сначала нужно переключиться на ветку master:
$ git checkout master
Switched to branch «master»

$ git status
# Мы на ветке master
nothing to commit (working directory clean)

#

Теперь

мы

готовы

к

слиянию!

$ git merge alternate

Merge made Ьу recursive .
file 1 1 +
1 files changed, 1 insertions(+),

О

deletions(-)

·-····· ··· ··· ·· ·········· ················ · ········· · · ··· ······· ········ ···· ······· -1111

Git.

Практическое руководство

Чтобы просмотреть , что же произошло , вы можете использовать утилиту

просмотра графа фиксации, которая является частью

git log:

$ git l og —graph —pre tt y =o n e li ne —ab brev — commit

* ld5l b93 … Merge bra nc h ‘ al ter nat e’
1
1

*
1/

*
1

Ь38 4 7 21

. .. Add a l ternate’ s l ine 4
76 l d9 1 7 .. . An o ther file

* 8 f4d 2d 5 … Initi a l 3 line file
Концепция графов фиксации была описана ранее в главе

6, поэтому в общих

чертах выведенный граф вам должен быть понятен. В отличие от графов ,
представленных в главе

6, на этом графе наиболее последние фиксации на­
ID начальной фиксации — 8f4d2d5. Каждая ветка
содержит одну фиксации (761d917 и Ь384721), вторая ветка начинается на
фиксации 8f4d2d5, затем обе ветки объединяются в одно целое снова — на
фиксации 1d51b93.
ходятся сверху, а не справа.

Примечание. Использование утилиты
натива rрафическим утилитам вроде
ляемая

Технически

Git

git log —graph,

git log —graph — отличная альтер­
gitk. Визуализация, предостав­

отлично подходит для медленных терминалов.

производит каждое слияние симметрично для создания

одной комбинированной фиксации, которая добавляется в вашу текущую
ветку. Другая ветка никак не изменяется слиянием . Поскольку фиксация

слияния добавляется только в вашу текущую ветку, вы можете сказать > file

Line 5 stuff
Line 6 stuff
л о

$ git commit

-m «Add line 5 and

б»

Created commit 4d8b599: Add line 5 and 6
1 files changed, 2 insertions(+), • О deletions(-)
Теперь на ветке

altemate модифицируем тот же файл, но немного иначе:

$ git checkout alternate

Switched branch «alternate»
$ git show-branch

* [alternate] Add alternate’s line 4
! [rnaster] Add line 5 and 6
+ [rnaster] Add line 5 and 6
*+ [alternate] Add alternate ‘ s line 4
#

Редактируем файл

$ cat >> file

Line 5 alternate stuff
Line 6 alternate stuff
л о

$ cat file

Line
Line
Line
Line
Line
Line

1
2
3
4
5
6

stuff
stuff
stuff
alternate stuff
alternate stuff
alternate stuff

….

.— — ————— — —— — — —— — — ———— — ——————— — — —

Git.

Практическое руководство

$ git diff
diff —git a / file Ь/file
index a29c52b .. 802acf8 100644
— a / file
+++ Ь/file
@@ -2,3 +2,5 @@ Line 1 stuff
Line 2 stuff
Line 3 stuff
Line 4 alternate stuff
+Line 5 alternate stuff
+Line 6 alternate stuff

$ git commit -а -m «Add alternate line 5 and б «
Created commit еЗОбеld: Add alternate line 5 and 6
l files changed , 2 insertions(+), О deletions( -)
Теперь давайте просмотрим сценарий. Текущая ветка истории выглядит
так :

$ git show-branch
* [alternate] Add alternate line 5 and 6
[master] Add line 5 and 6

* [alternate] Add alternate line 5 and 6
+ [master] Add line 5 and 6
*+ [alternate л ] Add alternate’s line 4
Чтобы продолжить, переключитесь на ветку

master

и попытайтесь осуще­

ствить слияние:

$ git checkout master
Switched t o branch «master»
$ git merge alternate
Auto-merged file
CONFLICT (content) : Merge conflict in file
Automatic merge failed ; fix conflicts and then comm it the
result.
Когда произошел конфликт слияния, вы должны внимательно исследовать

причину конфликта командой

•·

кроется в содержимом файла

git diff. В

нашем случае причина конфликта

file:

………….. ········ …………………… .. -………………………… .

Глава

9.

Слияния

$ qit diff
diff —се file
index 4d77ddl, 802acf8 .. 0 00 0000
a / file
+++ Ь/file
@@@ -2,5 -2,5 +2,10 @@@ Line 1 stuf
Line 2 stuff
Line 3 stuff
Line 4 alternate stuff
++ > alternate:file
Команда

git diff

показывает разницы между файлом

каталоге и индексе. В стиле обычной команды
представлен между

>>.
Дополнительные знаки плюс и минус используются в комбинированном

формате

diff

для обозначения изменений из разных источников относи­

тельно финальной версии .

Предыдущий вывод показывает, что конфликт покрывает строки

5

и

6,

именно эти строки отличаются в версиях файла из двух разных веток. Те­
перь давайте попытаемся разрешить конфликт. Когда вы разрешаете кон­

фликт слияния, вы вольны выбрать любое решение на свое усмотрение. Вы

можете выбрать один из вариантов файла, вы можете смешать оба варианта
или даже создать что-то полностью новое и отличающееся от представлен­

ных вариантов. Хотя последняя возможность довольно странная, но она
тоже доступна.

В этом случае я выбираю строку из каждой ветки в качестве моей разрешен­
ной версии. Отредактированная версия файла теперь выглядит так:

$ cat file

Line
Line
Line
Line

1 stuff
2 stuff
3 stuff
4 alternate stuff

•.——·—.—-.—…—…-.—….-…-…-..—..—….-.—…-….——..-.. —IID

Git.

Практическое руководство

Line 5 stuff
Line 6 alternate stuff
Если вы довольны разрешением конфликта, введите команду

git add

для

добавления файла в индекс и подготовить его для фиксации слияния:

$

git add file

После разрешения конфликтов и подготовки окончательной версии каж­

дого файла в индексе с использованием
слияние с использованием команды

git add, вам нужно зафиксировать
git commit. Git откроет ваш любимый

редактор с шаблоном сообщения, который будет выглядеть примерно так:

Merge branch ‘ alternate’
Conflicts:
file
#
# It looks like you may Ье committing а MERGE.
# If this is not correct, please remove the file
# .git / MERGE_HEAD
# and try again .
#
#
#
#
#
#

Please enter the commit message f o r your changes.
(Comment lines starting with ‘ # ‘ will not Ье included)
On branch master
Changes to Ье committed :
(use «git reset HEAD . .. » to unstage)

#
# modified: file
#
Как обычно, строки, которые начинаются решеткой(#), являются коммен ­
тариями и предназначены исключительно для вашей информации.

Когда вы выйдете из редактора,

Git

сообщит об успешном создании новой

фиксации слияния:

$ git commit

#

Редактирование

сообщения

фиксации

слия н ия

• ··· ················· ·· ·· ·· ··· ···························· ········ ······ ········· ··

Глава

9.

Слияния

Created commit 7015896: Merge branch ‘alternate’
$ git show-branch
! [alternate] Add alternate line 5 and 6
* [master] Merge branch ‘ alternate’

— [master] Merge branch ‘alternate’
+* [alternate] Add alternate line 5 and 6
Просмотреть результат фиксации слияния можно так:

$ git log

9.2.

Работа с конфликтами

слияния
Как показано в предыдущем примере, при наличии конфликтов слияние не

может быть выполнено автоматически .
Давайте рассмотрим другой сценарий с конфликтом для изучения утилит,

предоставляемых

hello со

строкой

Git для разрешения конфликтов. Пусть у нас будет файл
«hello~, потом мы создадим две разных ветки с двумя раз ­

ными вариантами этого файла.

$ git init
Initialized empty Git repository in / tmp / conflict/.git/
$ echo hello > hello
$ git add hello
$ qit commit -m «Initial hello file »
Created ini tial commi t Ь8725ас: Ini tial hello file
1 files changed , 1 insertions(+), О deletions(-)
create mode 100644 hello
$ git checkout

Switched to

а

-Ь alt
new branch «alt»

$ echo world >> hello
$ echo ‘Уау ! ‘ >> hello

, _—————.——————————————————————ll!il

Git.

Практическое руководство

$ qit coппnit -а -m «One world»
Created comrnit d03e77f : One world
1 files changed , 2 insertions(+), О deletions(-)
$ qit checkout master
$ echo worlds >> hello
$ echo ‘Уау ! ‘ >> hello
$ qit commit -а -m «All worlds »
Created •comrnit eddcb7d : All wo rlds
1 files changed, 2 insertions(+), О deleti o ns(-)
Одна ветка содержит

>,

в дру­

В ам нужно просто в ы­

брать одну из фраз, удалить маркеры конфликта и выполнить команды

add

и

git commit. Но давайте

рассмотрим некоторые другие функции

git
Git ,

помогающие нам в решении конфликтов.

Примечание.

>>>>>>>>)

Маркеры

слияния

(> master file
$ git add master_file
$ git comrnit

.. . . . . . — … -… -.. — ……………. — .. . — . — … — . — -…….. …… .. … —

. . …

Git.

Практическое руководство

Created initial commit е719Ыf: Add master file to master
branch.
1 files c hanged , 1 insertions(+) , О deletions(-)
create mode 100644 master file
$ echo «more foo» >> master fil.e
$ git commit master_fil.e
Created commit 0fбla54 : Add more foo .
1 files changed , 1 inserti on s(+) , О deletions(-)
$ git show-branch —more=S

[master] Add more foo .
[master л] Add master_file to master branch.
Предположим теперь, что вторая фиксация неправильная, и в ы хотите вер ­

нуться обратно. Это классическое применение команды
НЕ АD л . Вспомните , в главе

6

git reset —mixed

мы говорили о том, что ссылка Н ЕА Dл ука­

зывает на родителя текущей фиксации

H EAD

ветки

master

и представляет

состояние, предшествующее неправильной фиксации.

# По умолчанию используется
$ git reset НЕАDл
master_file: locally modified

параметр

— — mixed

$ git show-branch —more=S

[ma ste r] Add master file to master branch .
$ cat master_file
foo
more foo
После

git reset

НЕАD л

Git

восстановил содержимое

master_file и всего ра­
«Add more foo~.

бочего каталога в состояние, которое было до фиксации
Поскольку опция

—mixed

сбрасывает индекс, вам нужно заново подгото­

вить любые изменения , которые вы хотите видеть в новой фиксации. Воз ­

можно, вам нужно повтор но отредактировать

master_file

и другие файл ы ,

а также выполнить какие-либо другие изменения перед созданием новой
фиксации.

$ echo «even rnore foo» >> master_fil.e
$ git comrnit master_file
Created commit 04289da : Updated foo .

ED—-· …………………………. —…………………………….. ·········

Глава

1 files c hanged, 2 insertions(+),

О

1О.

Изменение коммитов (фиксаций)

deletions(-)

$ git show-branch —more=S

[rnaster] Updated f oo .
[rnaster л ] Add rnaster_file t o rnaster branch.
Теперь на ветке

master

создано всего две фиксации, а не три. Если вам не

нужно изменять индекс, тогда вы можете использовать опцию

$
$

git reset —s oft
git cornrnit

—soft:

НЕАD л

Предположим, однако, что вы хотите полностью устранить вторую фикса­

цию и при этом вам все равно , что будет с ее содержимым. В этом случае
используйте опцию

—hard:

$ git reset —hard

HEAD is now at

НЕАDл

е719Ыf

Add rnaster file to rnaster branch.

$ git show-branch —more=S

[rnaste r] Add rnaster_file to rnaster branch .
Данная команда немедленно переводит ветку

master

в предыдущее состо­

яние, при этом изменяются как индекс, так и рабочий каталог в состояние
фиксации НЕАDл. Состояние файла

master_file

в вашем рабочем каталоге

будет снова модифицировано, и вы получите исходный файл:
$ cat rnaster file
Foo

Хотя все примеры в той или иной форме используют

применить

git apply

HEAD,

вы можете

к любой фиксации в репозитарии. Например , чтобы

устранить несколько фиксаций на вашей текущей ветке, вы можете исполь­

зовать команду

git reset —hard HEAD-3

или даже

git reset —hard master-3.

Будьте осторожны. Хотя вы можете указать имена ветки, это не то же самое,
что и переключение ветки. В случае с

git reset вы должны всегда оставаться

на одной и той же ветке. Вы можете изменить свой рабочий каталог, чтобы
ваш рабочий каталог был похож на

HEAD другой ветки, но вы все еще оста­

етесь на исходной ветке .


· -· ········· · ·····································································
-&I

Git.

Практическое руководство

Чтобы проиллюстрировать использование git reset на других ветках, давай­

те добавим вторую ветку с названием

# Мы д о лжны быть на master ,
$ git checkout master
Already оп «master»

но

dev и добавим в

л у чше

нее новый файл.

у бедиться

в

эт о м

т о чно

git checkout -Ь dev
echo bar >> dev file
git add dev_file
git commit
Created commit 7ecdc78 : Add dev file to dev branch
1 files changed, 1 insertions(+), О deletions(-)
create mode 100644 dev file
$
$
$
$

Вернемся на ветку

master,

здесь только один файл:

$ git checkout master
Switched to branch «master»
$ git rev-parse НЕАD
e719Ыfe81035c 0 bb5eldaaaбcd8lc7350b73976

$ git rev-parse master
e719Ыfe81035c0bb5eldaaaбcd8lc7350b73976

$ 1s
master file
Использования опции

#

Изменяем

HEAD,

—soft изменит только ссылку HEAD:

чтобы

она

указывала

на

фиксацию

dev

$ git reset —soft dev
$ git rev-parse НЕАD

7ecdc78lc3eb9fbb9969b2fdl8a7bd2 324d0 8c2f
$ 1s
master file

$ git show-branch

[ de v ] Add de v _ file to dev branch

* [master] Add dev file to dev branch


&1- ———————————- — ———- — — ————— ———— —·

Глава

1О.

Изменение коммитов (фиксаций)

+* [dev ] Add de v file to dev branch
Конечно, кажется, как будто ветка

master

и ветка

dev находятся в одной
master, что хорошо —

и той же фиксации. И вы все еще находитесь на ветке

но выполнение этой операции оставляет вещи в специфическом состоянии.

Что бы произошло , если бы вы теперь сделали фиксацию?
ет на фиксацию , в которой есть файл
ветке

dev_file,

HEAD указыва­

но этот файл не находl-‘тся в

master.

$ echo « Funny» >> new
$ git add new
$ git commit — m «Which commit parent? »
Created commit f48bb36 : Which commit parent?
2 files changed , 1 insert i ons(+ ) , 1 deletions(-)
delete mode 100644 dev file
create mo de 100 6 44 new
$ git show-branch

! [dev] Add dev file to dev bran ch
* [master] Which commit parent?
* [master] Which commit parent?
+* [dev] Add dev_file to dev branch

Git корректно добавил новый файл new и, очевидно, решил, что dev_file от­
Git удалил dev_file? Git прав, dev_file

сутствует в этой фиксации. Но почему

не является частью этой фиксации, но ошибочно говорить, что он был уда­
лен, поскольку его никогда там и не было . Итак, почему
этот файл?

Git

Git выбрал удалить
HEAD тогда,

использует фиксацию , на которую указывает

когда была сделана новая фиксация. Давайте посмотрим, как это было :
$ git cat-file -р НЕАD

tree 948ed823483a0504756c2da81d2e6d8d3cd95059
parent 7ecdc781c3eb9fbb9969Ыfd18a7bd2324d08c2f
auth o r Федя Колобков 12 2963 14 9 4 -0 600
commit ter Федя Колобков 1229631494 — 0600
Какой из родителей совершает ошибку?

Родитель этой фиксации

— 7ecdc7, который является вершиной ветки dev,
master. Но эта фиксация была сделана на ветке master! Путани­
ца не должна стать неожиданностью , потому что основная HEAD была из а не ветки

·——- ·-·· .. ………………… …… ….. ···- ···—· · ······- …… .. …. …… . . .

Git.

Практическое руководство

менена, чтобы указать на голову ветки

dev. В этой точке вы можете пр ийти

к заключению , что последняя фиксация полностью поддельная и должна

быть удалена. И это хорошо. Такому запутанному состоянию не место в
репозитарии.

Как показал ранний пример , вся эта ситуация подходит команды
предыдущей версии

HEAD ветки master:

# Сначала нужно убедиться ,
$ git checkout master

#
#

git reset

НЕА D л . Но перед выполнением этой команды нужно добраться до

—hard

что мы находимся

на

ветке

master

ПЛОХОЙ ПРИМЕР!
Сброс

обратно

на

$ git reset — -hard

предшес тв ующее

сос т оян ие

master

НЕАD л

Так в чем же проблема? Ведь вы просто увидели, что родитель
указывает на

dev, а

HEAD

не на предшествующую фиксацию на исходной ветки

master.
#

Да,

НЕАDл

указывает

$ git rev-parse

на

HEAD

ветки

dev .

НЕАDл

7ecdc78lc3eb9fbb9969b2fdl8a7bd2324d08c2f
Есть несколько способов определения фиксации , к которой будет сброшена
ветка

master.

$ git log

commit f48bb36016e9709ccdd54488a0aael487863b937
Author : Федя Колобков
Date : Thu De c 18 14:18 : 14 2020 — 0600
Which commit parent?
commit 7ecdc78lc3eb9 f bb9969b2fdl8a7bd2324d08c2f
Author : Федя Колобко в
Date : Thu Dec 18 13 : 05 : 08 2020 — 0600
Add dev file to dev branch
commit e719Ыfe81035c0bb5eldaaa6cd8lc7350b73976
Author: Фе дя Колобков

ва

———————————————————————————.

Глава

1О.

Изменение коммитов (фиксаций)

Date: Thu Dec 18 11:44:45 2020 -06 00
Add master file to master branch.
Последняя фиксация (е719Ыf) является корректной.
Другой метод использует команду

git reflog, которая выводит историю из­

менений ссылок в вашем репозитарии:

$ git reflog

f48bb36 …
7ecdc78 …
е719Ыf …
7ecdc78 …
е719Ыf …
е719Ыf …
е719Ыf …
04289da …
е719Ыf …
72с001с …
е719Ыf …
0fбla54 …

HEAD@{0}: commit: Which commit parent?
HEAD@{l} : dev : updating HEAD
HEAD@{2}: checkout : moving from dev to master
НЕАD@{З} : commit: Add dev file to dev branch
HEAD@{4} : checkout : moving from master to dev
HEAD@{S}: checkout : moving from master to master
НЕАD@{б}: НЕАDл: updating HEAD
HEAD@{7}: commit: Updated foo.
HEAD@{8}: НЕАDл: updating HEAD
HEAD@{9}: commit: Add more foo.
HEAD@{l0}: НЕАD л : updating HEAD
HEAD@{ll}: commit : Add more foo.

Просмотрите этот список. Третья строка свидетельствует о переключении с

ветки

dev на ветку master. В то время основной HEAD была фиксация с ID

е719Ыf. Если еще вам понадобится использовать е719Ыf, вы можете или
указать ее идентификатор или же использовать имя

$ git rev-parse

HEAD@{2}.

НЕАD@{2}

e719Ыfe81035c0bb5eldaaa6cd8lc7350b73976

$ git reset —hard HEAD@{2}
HEAD is now at е719Ыf Add master file to master branch .
$ git show-branch

! [dev] Add dev_file to dev branch
* [master] Add master file to master branch.
+ [dev] Add dev file to dev branch
+* [master] Add master file to master branch .

·- — ——— — — — —— — — — — —— —- —— ——- —- — —— —- — ________

,..

Git.

Практическое руководство

Как только что было показано,

reflog

можно часто использоваться для на­

хождения предыдущей информации состояния для ссылок, таких как име­
на веток.

Аналогично, неправильно пытаться изменять ветки, используя команду

git

reset —hard:
$ git reset —hard dev
HEAD is now at 7ecdc78 Add dev file to dev branch
$ 1s
dev file mast e r file
Кажется, что это сработало. В этом случае, рабочий каталог даже был за­
полнен правильными файлами из ветки
тает! Ветка

dev. Но
master все еще осталась текущей:

на самом деле это не рабо­

$ git branch

de v

* master
Так же, как в предыдущем примере, фиксация в этой точке перепутала бы
граф. Поэтому самое правильное действие в данном случае

определить

корректное состояние и выполнить сброс к нему:

$ git reset —hard е719Ыf
Или, возможно, даже:

$ git reset —s o ft

е719Ыf

При использовании опции

—soft

рабочий каталог не будет изменен , что оз­

начает, что ваш рабочий каталог теперь представляет содержимое

( файлы
dev. Кроме того, поскольку
HEAD теперь правильно указывает на голову ветки master, фиксация в этой

и каталоги), присутствующие на вершине ветки

точке приведет к допустимому графу с новым основным состоянием, иден­

тичным вершине ветки

dev.

Может, это не совсем то, что вы хотели, но такой вариант тоже возможен .

ВI-

———————————————————————————.

Глава

10.3.
gi t

Изменение коммитов (фиксаций)

Использование

команды
Команда

1О.

git cherry-pick
фик с ация применяет изменения, представ ­

c h e rr y — p ick

ленные фиксацией на текущей ветке. Она представит новую , отдельную

фиксацию. Строго говоря, использование команды

git cherry-pick не

изме­

няет существующую историю в репозитарии; вместо этого , она добавляет
фиксацию в историю.

Как с другими операциями

Git,

которые представляют изменения через

процесс применения разности, вы, возможно, должны будете разрешить
конфликты, чтобы полностью применить изменения от данной фиксации .
Команда

git cherry-pick

обычно используется, чтобы представить опреде ­

ленные фиксации из одной ветки в репозитарии в другую ветку.

На рис.

10.4

у ветки

dev

есть нормальная разработка, тогда как

держит фиксации для обслуживания выпуска

rel_2.3

со ­

2.3.

dev

rel_2.3

Рис.

10.4. До команды git cherry-pick

В течение нормальной разработки была исправлена ошибка фиксацией

Если та же ошибка была также и в релизе
можно перенести фиксацию

$
$

gi t c he c kout r el 2 . 3
g i t che r ry — pick dev~2 #

На рис .

10.5 фиксация F’

2.3, то
ветку rel_2.3:

фи к с ац ия

с помощью

F.
git cherry-pick

F

подобна фиксации

F, но это полностью новая фик­

сация и, возможно, она должна быть скорректирована для разрешения кон-

•.—.——-.————————-.———.-.-..—.—..———.—.——.-&1

Git.

Практическое руководство

dev

rel_2.3
Рис.

1О. 5.

после команды

фликтов. Обратите внимание: фиксация

F’

git cherry-pick
применена после фиксации

Z

— последней фиксации ветки rel_2.3.
Другое применение

git cherry-pick — восстановление серии фиксаций путем

выбора пакета от одной ветки и перенос его в новую ветку.

Предположим , что у нас есть серия фиксаций в вашей ветке
показано на рис.

10.6, и вы хотите перенести их в ветку master,

my_dev,

как

но немного в

другом порядке.

master

my_dev
Рис.

1О. 6.

Перед переносом фиксаций командой

Чтобы применить их на ветке

master в

порядке У,

W,

Х,

git cherry-pick

Z,

используйте сле­

дующие команды:

$ git checkout master
$

git cherry- p i ck

my_devл

#

У

$ git c herr y -pi ck my_dev ~ З

# W

$ git ch erry-pick my_dev~2
$ git c herry-pick my_dev # Z

#

Х

После этого ваша история фиксаций будет похожа на рис.

10.7.

• · ········· ···· ··· ··· ································ ··· ······················ ·····

Глава

1О.

Изменение коммитов (фиксаций)

master

my_dev
Рис.

1О. 7.

после переноса фиксаций командой

git cherry-pick

В подобных ситуациях, где порядок фиксаций претерпевает довольно боль­
шие изменения, скорее всего , вам придется разрешать конфликты. Наличие
конфликтов полностью зависит от отношений между фиксациями. Если

фиксации будут тесно связаны , у вас будут конфликты, которые придется

разрешать. Если они будут не очень зависимым, конфликтов будет меньше.
Изначально, команда git
за один раз.

cherry-pick могла выбирать только одну фиксацию
Однако, в более поздних версиях Git данная команда может вы­

бирать диапазон фиксаций . Например, следующая команда:

#
$

на ветке master
git cherr y-pick X .. Z

применит новые фиксации Х’, У’,

10.4.

на ветке

master.

Использование

команды
Командаgit

Z’

revert

git revert

фик с ацияподобнакомандеgit

cherry-pick

фик­

сация с одним важным отличием: она применяет инверсию заданной фик­

сации . Другими словами , данная команда отменяет фиксацию, используя
хэш этой фиксации.

Подобно команде

git cherry-pick, команда git revert не изменяет существую ­

щую историю в репозитарии. Вместо этого она добавляет в историю новую
фиксацию .

.. . . . . . —………… …. .. .. .. …. ….. … … …… … .. .. … .. …….. ….. .. .. .

Git.

Практическое руководство

master
Рис.

1О. 8.

Ветка до команды

Обычное применение для команды
ной фиксации. На рис.
ды

git revert.

git revert — это

10.8 показана

git revert

D просто запустите

master ~ З

Результат показан на рис.

#

~отмена~,, эффекта задан­

история ветки до применения коман ­

По некоторым причинам, фиксацию

Для отмены фиксации

$

git revert

фик с ация

D нужно отметить.

команду

git revert:

О

10.9, где фиксация D’ — это отмена фиксации D.

master
Рис.

1О. 9.

Ветка после команды

git revert

10.5. Команды reset, revert
и checkout
Эти три команды, а именно

reset, revert

и

checkout,

могут быть немного не­

понятными, поскольку все они могут выполнять подобные операции.
Однако есть правила и рекомендации, когда каждая из этих команд должна
использоваться, а когда

— нет.

Если вы хотите переключиться на другую ветку, используйте команду

checkout.

Ваша текущая ветка и ссылка

HEAD

git

будут изменены, чтобы со­

ответствовать вершине заданной ветки.

Команда

git reset

не изменяет вашу ветку. Однако, если вы предоставите

имя ветки, она изменит состояние вашего текущего рабочего каталога так,

IJEt———————————————————————————·

Глава

1О.

Изменение коммитов (фиксаций)

что он будет выглядеть, как будто бы загружена указанная ветка. Другими
словами,

git reset предназначен для сброса ссылки HEAD текущей ветки .

Поскольку

git reset —hard разработан для восстановления к известному со­
git checkout, которая просто переключает

стоянию , чего не делает команда

ветку. Таким образом, если у вас есть незаконченная фиксация слияния, и

вы попытались восстановиться при помощи команды

git checkout

вместо

git reset —hard, ваша следующая фиксация будет

ошибочной.
Путаница с git checkout происходит из-за его дополнительной возможности

извлечения файла их хранилища объектов и его помещения в ваш рабочий
каталог с возможной заменой версии, находящейся в вашем рабочем ката­
логе. Иногда версия того файла соответствует текущей версии

гда

HEAD,

ино­

— это более ранняя версия.

#

Выгружаем файл file. с из индекса
git checkout — path/to / file.c
# Выгружаем файл file.c из версии v2.3
$ git checkout v2.3 — some / file.c

$

Git называет это

«проверкой пути~.

В первом случае при получении текущей версии из хранилища объектов,

кажется, что это форма операции ),

то есть изменения в

вашем локальном рабочем каталоге будут потеряны, потому что файл будет
сброшен к его текущей, НЕАD-версии .
Во втором случае более ранняя версия файла извлекается из хранилища

объектов и помещается в ваш рабочий каталог. Это похоже на команду «от­
мены~,,

( «revert>> ).

Такая двойственность запутывает пользователей.

В обоих случаях неправильно думать о данной операции как о git reset или
revert. В обоих случаях файл «извлекается~.> из определенной фиксации:
HEAD или v2.3 соответственно. Команда git revert работает с фиксациями,
а не с файлами!

Если другой разработчик клонировал ваш репозитарий или получил неко­
торые из ваших фиксаций, есть импликации для изменения истории фикса­
ции. В этом случае вы не должны использовать команды, которые изменя­

ют историю в вашем репозитарии. Лучше использовать команду

не используйте команды

git reset

или

git commit —amend

git revert,

(будет описана в

следующем разделе) .

•.———————————————————————————fJEI

it.

Практическое руководство

10.6.

Изменение последней

фиксации
Самый простой способ изменить последнюю фиксацию вашей текущей

ветки

— это

команда

git commit —amend. Как правило,

исправление

(amend)

подразумевает, что у фиксации есть существенно то же содержимое, но не­

который аспект требует корректировки или удаления. Фактический объ­
ект фиксации, который введен в хранилище объектов, будет, конечно, от­
личаться.

Типичное использование

git commit —amend — исправление

опечаток сразу

после фиксации. Это не единственное применение этой команды, эта ко­

манда может исправить любой файл ( файлы) и, действительно, может доба­
вить или удалить файл как часть новой фиксации. Как и в случае с обычной
командой

git command, команда git command —amend запустит сеанс редак­

тора, в котором вы можете изменить сообщение о фиксации.
Например, предположим, что вы работаете над речью и сделали следующую
последнюю фиксацию:

$ git show
cornmit 0ba161a94e03aЫe2b27c2e65e4cbef476d0 4f5d
Author: Федя Колобков
Date : Thu Jun 26 15:14 : 03 2020 -0500

Initial speech
diff —git a /s peech . txt Ь/speech . txt
new file mode 100644
index 0000000 .. 310bcf9
— / dev/nul l
+++ Ь/speech .txt
@@ — 0 , 0 +1,5 @@
+Three score and seven years ago
+our fathers brought f or th on this continent,
+а new nation, conceived in Liberty,
+and dedicated to the proposition
+that all men are created equal.

. . . . …. … .. …. …. …………………… ….. . …….. . . ……… . …………..

Глава

1О .

Изменение коммитов (фиксаций)

В данный момент фиксация сохранена в хранилище объектов

Git,

но в тек­

сте есть небольшие ошибки. Чтобы исправить их, вам можно просто отре­
дактировать файл снова и сделать вторую фиксацию. История будет при­
мерно такой:

$ qit show-branch — — more=S
[master] Fix timeline typo
[masterл]
Initial speech
Однако, если вы хотите хранить чистую историю в вашем репозитарии, вы
можете непосредственно отредактировать эту фиксацию и заменить ее.

Чтобы сделать это, исправьте файл в вашем рабочем каталоге. Исправьте
опечатки и добавьте/удалите файл, если необходимо. Как и с обычной фик­
сацией для обновления индекса используйте команды
сле чего выполните команду

#

исправьте

опечатки

в

git add и git nn. По­

git commit —amend:

speech.txt

$ qit diff

diff —git a / speech . txt Ь/speech.txt
index 310bcf9 .. 7328a76 100644
— a / speech.txt
+++ Ь/speech.txt
@@ — 1,5 +1,5 @@
-Three score and seven years ago
+Four score and seven years ago
our fathers brought forth on this continent ,
а new nation, conceived in Liberty,
and dedicated to the prop o sition
-that all men are created equal.
+that all men and women are created equal .
$ qit add speech . txt
$ qit commit — -amend
# При необходимости измените
# («Initial speech»)
# Мы его немного изменили
При использовании

сообщение

фиксации

—amend любой сможет увидеть, что исходная фиксация

была изменена:

$ qit show-branch —more=S

,. ……………………………………………………………………..fJII

Git.

Практическое руководство

[master] Initial speech that sounds familiar.
$ git show
commit 47d849c61919f05dalacf983746f205d2cdb0 0 55
Author : Федя Колобков
Date: Thu Jun 26 15 : 14:03 2020 -0500

Initial speech that sounds familiar.
diff —git a / speech . txt Ь/speech.txt
new file mode 100644
index 0000000 . . 7328а76
— /dev/nu ll
+++ Ь/speech . txt
@@ -0 , 0 +1 , 5 @@
+Four score and seven years ago
+our fathers brought forth on this continent,
+а new nation , conceived in Liberty ,
+and dedicated to the proposition
+that all men and women are created equal .
Эта команда может редактировать метаинформацию фиксации. Например,

указав опции

—author, вы можете изменить автора фиксации:

$ g i t commit —amend —author » ВоЬ Miller < kЬob@example . com> «

# … just close the editor …
$ g i t log
commit 0e2a14f933a3aaff9edd848a862e783d986f149f
Author: ВоЬ Miller
Date: Thu Jun 26 15:14:03 2020 -05 00

Initial speech that sounds familiar.
Посмотрим на граф фиксаций, на рис.

команды

git commit —amend,

а на

10.1 О изображен граф до выполнения
10.11 — после.

HEAD
Рис.

10. 10.

Граф фиксации до выполнения команды

—amend

git commit

·································· ················································

Глава

1О.

Изменение коммитов (фиксаций)

HEAD
Рис.

1О. 11.

Граф фиксации после выполнения команды

git commit

—amend
Здесь экземпляр фиксации С остался практически тем же самым, но был
HEAD была изменена и те­

изменен, чтобы получить фиксацию С’. Ссылка

перь она указывает не на фиксацию С, а на фиксацию С’.

10.7.Перебазирование
фиксаций
Команда

git rebase

используется для изменения последовательности фик ­

саций. Эта команда требует, как минимум, одного имени другой ветки, в ко­

торую будут перемещены ваши фиксации. По умолчанию перебазируются
фиксации из текущей ветки, которых еще нет в целевой ветке.

Типичное использование команды

git rebase — сохранить серию фиксаций из
master.

указанной ветки на последнюю фиксацию ветки

На рис.

topic
ветка

10.1 2 показано ,

что было разработано две ветки. Изначально ветка

произошла от ветки

master (с фиксации В ) . Тем временем
master тоже не стояла на месте и дошла до фиксации Е.

основная

master

topic

Рис.

1О. 12.

Перед выполнением команды

git rebase

·——————————————————————————— —IJII

Git.

Практическое руководство

Предположим, что вы хотите перенести фиксации из ветки

master.

topic в ветку
master, то

Они будут присоединены к последней фиксации ветки

есть к фиксации Е, а не к В . Поскольку ветка

topic

должна быть текущей,

сначала на нее нужно переключиться:

$
$

git checkout topic
git rebase master

Или же использовать эту команду:

$

git rebase master topic

После завершения операции перебазирования новый граф будет таким, как
показано на рис.

10.13.

master

topic
Рис.

Использование

10.13.

git rebase

nослекомандь,gitrеЬаsе

в ситуациях, подобной показанной на рис.

часто называется портированием. В этом примере, ветка
рована в ветку

Команда

10.12
topic была порти­

master.

git rebase

может также использоваться для полной транспланта­

ции линии разработки из одной ветки в другую, для этого используется оп­
ция

—onto.

Например, предположим, что вы разработали новую функцию в ветке

Q. Ветка feature основана на ветке maint, что по­
10.14. Чтобы трансплантировать фиксации Р и Q из ветки
feature в ветку master (не maint!), используйте команду:
feature

с фиксациями Р и

казано на рис.

$

git rebase —onto master

maint л

featur e

IJIJ-……………………………………………………………………… .

Глава

1О.

Изменение коммитов (фиксаций)

master

maint

feature
Рис.

1О. 14.

перед трансплантацией командой

Результат приведен на рис.

git rebase

10.15.

При трансплантации могут произойти конфликты, которые придется раз ­

решить вручную. Имейте это в виду при использовании команды
Если конфликт будет найден, операция
ботку

— пока

rebase

git rebase.

временно прекратит обра­

вы не разрешите конфликт. О том, как разрешать конфликты,

было сказано в главе

9.

feature
master

maint
Рис.

1О. 15.

после трансплантации командой

git rebase

Когда вы разрешите все конфликты и обновите индекс, операцию
можно продолжить командой

rebase
git rebase —continue. Данная команда продол­

жит выполнение перебазирования фиксаций до следующего конфликта,
если таковой будет найден .

.. . . . . . . ·- ………………… -…. -…………. -… -… -………… -… -… —

Git.

Практическое руководство

Если во время исследования конфликта вы решите, что определенная фик­

сация не является необходимой, используйте команду

git rebase —skip

для

перехода к следующей фиксации. Это не очень корректно и может приве­

сти к еще большим конфликтам, поэтому лучше все-таки попытаться раз­
решить конфликт.

Использование команды

git rebase -i

Предположим , что вы начали писать хайку и уже написали две полные
строки:

$ git init

Initialized empty Git reposit ory in .git /
$ git config user . email » kolobok@lobok . com»
$ cat haiku
Talk about colour
No jealous behaviour here
$ git add haiku
$ git commit -m «Start ту haiku»
Created initial commit a75f74e: Start my haiku
1 files changed , 2 insertions(+) , О deletions(-)
create mode 100644 haiku
Но потом вы решили использовать Американский вариант написания слова

.. color1>

вместо Британского. Вы сделали фиксацию, чтобы исправить это:

$ git diff
diff — git a / haiku Ь/haiku
index 088Ьеа0 .. 958aff0 100644
— a /haiku
+++ Ь/haiku
@@ — 1 , 2 +1,2 @@
-Talk about colour
+Talk about color
No jealous behaviour here

..

$ git commit -а -m «Use color instead of colour»
Created commit Зd0f83b : Use color instead of colour
1 files changed, 1 insertions ( +) , 1 deletions (-)

. . . . . . . . . . .. . . . . . . . . . .. . . . . .. . . . . . . . . . . . . . . . . . . . . . . . .. . . . .. . . . . . . . . . . . . . . . . . . . . . . .

Глава

1О.

Изменение коммитов (фиксаций)

Затем вы придумали последнюю строчку и зафиксировали ее:

$ git diff
diff — -git a / haiku Ь/haiku
index 958aff0 . . cdeddf9 100644
— — a/haiku
+++ Ь/haiku
@@ — 1,2 +1,3 @@
Talk about color
No jealous behaviour here
+I favour red wine
$ git commit -а -m «Finish my colour haiku»
Created commit 799dba3: Finish my colour haiku
1 files changed , 1 in sertions(+) , О deletions(-)
Однако, вы снова написали Британский вариант вместо Американского и
хотите испр авить его:

$ git diff
diff —git a / haiku Ь/haiku
index cdeddf9 . . 064clb5 100644
— — — a/haiku
+++ Ь/haiku
@@ -1 , 3 +1 , 3 @@
Talk about color
-No jealous behaviour here
— I favour red wine
+No jealous behavior here
+I favor red wine
$ git commit -а -m «Use American spellings»
Created commit Ь61Ь041: Use American spellings
1 files changed , 2 insertions(+) , 2 deletions( — )
В этой точке ваша история фиксаций будет следующей:

$ git show-branch —more=4
[master] Use American spellings
[masterл] Finish my colour haiku
[master~2] Use color instead of colour
[master ~3 ] Start my haiku

,

……………………………………………………………………… .

Git.

Практическое руководство

После просмотра последовательности фиксаций вы решаете изменить ее
так:

[master] Use American spellings
[master л] Use color instead of colour
[master~2] Finish my colour haiku
[master~З] Start my haiku
Затем в вашу голову приходит мысль объединить две похожие фиксации

те, которые исправляют написание разных слов. Поэтому вы объединяете
фиксации

master и

masterл в одну:

[master] Use Ameri c an spellings
[master л] Finish my colour haiku
[master~2] Start my haiku
Изменение порядка, редактирование, перемещение и слияние нескольких

фиксаций в одну
где опция

-i

(или

— все это можно сделать с помощью команды git rebase -i,
—interactive) означает «интерактивность».

Эта команда позволяет вам изменить фиксации и поместить их или в исход­
ную, или в другую ветку. Типичное использование

— изменение фиксаций

в

той же ветке. При запуске команды нужно указать имя фиксации, с которой
вы хотите начать вносить изменения:

$ git rebase — i

master~З

Затем будет открыт редактор, файл в котором будет выглядеть примерно
так:

pick 3d0f83b Use color instead of co l our
pick 799dba3 Finish my colour haiku
pick ЬбlЬ041 Use American spellings
# Rebase a75f74e .. ЬбlЬ041 o nt o a75f74e
#
# Commands:
# pick = use commit
# edit = use commit , but st op for amending
# squash = use commit , but meld into previous commit

#
# If yo u remove

а

line here

ТНАТ

СОММIТ

WILL

ВЕ

LOST.

—·· ···········-··-·· ·························-············ ········ ········ ·····’

Глава

1О.

Изменение коммитов (фиксаций)

# However, if you remove everything, the rebase will
aborted .

Ье

#
Первые три строки перечисляют фиксации в доступном для редактирова­

ния диапазоне фиксаций, который вы указали в командной строке. Фикса­
ции приводятся в порядке от самой старой до самой новой, а перед каждой

из них есть команда

pick.

Если вы сейчас выйдете из редактора, каждая из

этих фиксаций будет выбрана (в указанном порядке) и применена к целе­
вой ветке. Строки, отмеченные знаком

#,

являются комментариями и игно ­

рируются программой.

Сейчас вы можете переупорядочить фиксации, объединить их вместе, из­
менить фиксации или удалить навсегда. Представим, что вы хотите про­

сто переупорядочить фиксации. Для этого нужно просто переупорядочить
строки в вашем редакторе, а потом выйти из него:

pick 799dba3 Finish my colour haiku
pick ЗdОfВЗЬ Use color instead of colour
pick ЬбlЬ041 Use American spellings
Вспомните, что первая фиксация для перебазировки

— это фиксация и ~ U se American … >> .
$ git rebase -i master~З

# переупорядочим первые две фиксации и выйдем из редактора
Successfully rebased and updated refs/heads / master.
$ git show- branch —more=4
[master] Use American spellings
[master л ] Use color instead of colour
[master ~2 ] Finish my colour haiku
[master~ЗJ Start my haiku
И так, мы переупорядочили историю . Следующий шаг

— объединить ( опе­
squash) две фиксацию в одну. Снова выполните команду git rebase -i
master-3. На этот раз конвертируйте список фиксаций из:
рация

pick d83f7ed Finish my colour haiku
pick lf7342b Use color instead of colour

.-… — — — —- — — — —- — —— ——— — —— ———— ——— ——-

Git.

Практическое руководство

pick 1915dae Use American spellings
в:

pick d83f7ed Finish my colour haiku
pick lf7342b Use color instead of colour
squash 1915dae Use American spellings
Третья фиксация будет помещена непосредственно в предшествующую
фиксацию, а новый шаблон сообщения журнала фиксации будет сформи­

рован из комбинации фиксаций, объединенных вместе.
В этом примере два сообщения журнала фиксации будут объединены вме­
сте и представлены как одно в редакторе:

# This is

а

comЬination

of two commits .

# The first commits message is:
Use col o r instead of colour
# This is the 2nd commit message:
Use American spellings
Эти сообщения будут отредактированы так:

Use American spellings
Снова, все строки, отмеченные # игнорируются.

Теперь посмотрим результаты перебазирования последовательности:

$ git rebase -i rnaster~З
# squash and rewrite the comrnit log message
Created comrnit cf27784: Use American spellings
1 files changed , 3 insertions(+), 3 deletions(-)
Successfully rebased and updated refs / heads / master.
$ git show-branch —more=4
[master] Use American spellings
[master л ] Finish my colour haiku
[master~2] Start my haiku
Хотя мы переупорядочили и объединили фиксации за два шага, эти опера­

ции можно было бы выполнить за одно действие.

. …………………………………………….. …………………………

Глава

Сравнение

1О .

rebase

Изменение коммитов (фиксаций)

и

merge

В дополнение к обычному изменению истории , у операции перебазирова­
ния есть особенности, о которых вы должны знать.
Перебазирование последовательности фиксацию на вершину ветку подоб­
но объединению двух веток.

Вы можете задать себе вопрос: что лучше использовать
В главе

12

— rebase или merge?

этот вопрос станет особенно остро, особенно, когда в игру всту­

пают множество разработчиков, репозитариев и веток.
В процессе перебазирования последовательности фиксаций

сгенери­

Git

рует полностью новые последовательности фиксаций. У них будут новые
SНА 1 -идентификаторы фиксации, основанные на новом начальном состо­
янии и представляющие другие разницы, даже при том, что они включают

изменения, которые достигают того же окончательного состояния .

Когда сталкиваешься с ситуацией, изображенной на рис .

вать ее в ситуацию, изображенную на рис.

10.13,

10.12, перебазиро­

не составляет проблемы,

поскольку никакая друга фиксация не основана на перебазируемой ветке .
Однако, даже в вашем собственном репозитарии у вас могут быть допол­
нительные ветки, основанные на той, которую вы хотите перебазировать .
Рассмотрим граф, изображенный на рис.

10.16.

master

dev

dev2
Рис.

10. 16.

перед мноrоветковым перебазированием

.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .

Git.

Практическое руководство

Вы можете подумать, что выполнение команды:
$

git rebase master dev

Приведет к графу, изображенному на рис .

10.17. Но

это не так. Первая под­

сказка, что этого не п р оизошло, следует из вывода команды.

$ git rebase master dev

First , rewinding head to replay your work on top of it .. .
Applying : Х
Applying: У
Applying : Z

master

dev

dev2

Рис.

Это говорит о том, что

Git

1О. 17.

применит только фиксации Х, У и

не сказано о фиксациях Р и
ный на рис.

Требуемый граф

Z. Но

ничего

Q, вместо этого вы получите граф, изображен ­

10.18.

dev

master

..

dev2
Рис.

1О. 18.

То, что получилось

. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . . . . .. . . .. . . . . . . . . . . . . . .. . . . . . .

Глава

Фиксации Х’, У’ и

1О.

Изменение коммитов (фиксаций)

Z’ — новые версии старых фиксаций, произошедших от В .

Старые фиксации Х и У все еще существуют в графе, поскольку они все

еще достижимы от ветки

dev2. Однако, исходная фиксация Z была удалена,

поскольку она больше не достижима. Имя ветки, которая указывала на нее,
было перемещено в новую версию той фиксации.

Теперь , похоже, что в истории ветки есть дублирующиеся сообщения:

$ git show-branch

* [dev] Z
!

*
*
*

[dev 2] Q
[master ] D
[dev] Z
[de vл ]

У

[dev~2] Х
* + [master ] D

* +

[master л ]

+

[dev 2]

+
+
+

[de v2л ]

с

Q
Р

[dev 2 ~2 ] У
[dev 2~3 ] Х
*++ [master ~2 ]

В

Но помните, это различные фиксации, которые делают по существу то же

изменение . Если вы объедините ветку с одной из новых фиксаций в дру­
гую ветку, у которой есть одна из старых фиксаций,

Git

никак не узнает,

что вы применяете одно и то же изменение дважды . В результате появятся

двойные записи в

git log, вероятнее всего, будет конфликт слияния и общий

хаос. В ы должны придумать, как избавиться от этой ситуации .
Если получившийся граф то, что вы хотите сделать, то вы это сделали . Но,

скорее всего, это не то , что вы хотите. Чтобы достигнуть графа, изображен­
ного на рис.

цию У ветки

10.1 7, вам
dev:

$ git rebase

devл

нужно перебазировать ветку

dev2

на новую фикса­

dev2

First , rewinding head t o replay you r wo rk on t op o f it . . .
Applying : Р
Appl y ing : Q
$ git show-branch
! [dev] Z

.. . .. . . . . .. . . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . .. . .. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . .

Git.

Практическое руководство

* [dev2] Q
[rnaster]
*
*
+
+*
+*
+*+

D

[dev2] Q
[de v2л ]

р

[dev] z
[dev2~2] у
[dev2~3] х
[rnaster] D

Наконец -то мы достигли графа, показанного на рис.

Другая запутывающая ситуация

10.17.

это перебазирование ветки, у которой

есть слияние на ней. Например , предположим , что у вас есть структура ве­

ток, подобная изображенной на рис.

10.19.

dev

master
Рис.

1О. 19.

Перед слиянием средствами

git rebase

Если вы хотите переместить всю структуру ветки

dev

до фиксации Х и присоединить к фиксации

(не В), чтобы получить

структуру, изображенную на рис.

10.20, вам

D

из фиксации

N вниз

нужно использовать команду

git rebase master dev.
Снова, однако, эта команда приводит к некоторым удивительным резуль­
татам:

$ q i t rebase master dev
First, rewinding head to repla y your work on top of it …
Applying: Х
Applying: У

_,

——— ——— — —— — ——— ————- ———. —- —— — — ———

Глава

1О.

Изменение коммитов (фиксаций)

dev

master
Рис.

10.20.

Ожидаемая структура дерева фиксаций

Applying: Z
Applying: Р
Applying: N
Кажется, все правильно. Но нужно разобраться, так это или нет.

git sho w-branch

$

*

[dev]

!

*
*
*
*
*

N

[master] D
[dev]

N

[dev л ]

Р

[dev ~2 ]

Z

[dev~З]

У

[ dev~4]

Х

*+ [master] D
Все фиксации теперь выстроились в одну длинную строку. Что же произо­
шло здесь?

Git должен переместить часть

графа, достижимого от

поэтому он найдет фиксации в диапазоне
фиксации,

Git

dev к базе слияния В,
master.. dev. Чтобы вывести все те

осуществляет топологическую сортировку той части графа

для произведения линеаризированной последовательности всех фиксаций
в диапазоне. Как только та последовательность была определена,
меняет фиксации по одной, начиная с фиксации

D,

Git

при­

как показано на рис.

10.21 .

•.-……………………………………………………………………..&1

Git.

Практическое руководство

master

dev
Рис.

10.21. Дерево фиксаций после линеризации

Снова, если вы хотели именно этого или вас не заботит форма графа, тогда

все готово. Но обычно в таких случаях хочется получить именно требуемую
структуру графа, поэтому нужно использовать опцию

#

Эта

опция

появилась

в

версии

—preserve-merges.

1. 6.1

$ git rebase —preserve -merges master dev

Successfully rebased and updated refs / heads/dev .
Просмотреть структуру результирующего графа можно командой:

$ git show-graph

* 06lf9fd .. . N
* f669404 … Merge branch ‘ dev2 ‘ into dev
1
1 * c386cfc .. . z
* 1 38аЬ25е …
1/
р

*
*
*
*
*
*

b93ad42 … у
65be7fl .. . х
е3Ь9е22 … D
f2b96c4 … с
8619681 … в
d6fbal8 .. . А

Это уже похоже на структуру, изображенную на рис.
Ответ на вопрос, что лучше использовать

10.20.

перебазирование или слияние,

зависит от того, какой репозитарий вы используете

— ваш

собственный или

распределенный. Также выбор стратегии зависит от вашего стиля разработ­
ки и вашего окончательного намерения.

Если операция перебазирования

— это

не ваш выбор, но вам все еще нужно

получить изменения ветки, тогда вам поможет слияние.

Важно помнить следующее:

E!I-····…….. ·················· …………………………………………..,

Глава

1О.

Изменение коммитов (фиксаций)

Перебазирование перезаписывает фиксации как новые фиксации .

Старые фиксации, которые больше не будут доступны , будут потеряны .

Если у вас есть ветка, которая содержит пред-перебазированную фикса­
цию , вам нужно перебазировать ее снова.

Если есть пользователь пред-перебазированной фиксации в другом ре­
позитарии, у него все еще есть копия той фиксации , даже если она была
перемещена в ваш репозитарий. Пользователю нужно согласовать свою
историю фиксаций .

•.——————-.———————.————..———————-.—1!11

Глава

Stash

.1

.

и

2

•R········•········—·—-· · ·—~
·
1

r

11.

reflog

it.

Практическое руководство

11.1. Stash
Вы когда-нибудь чувствовали себя уставшим в процессе разработки, когда
накапливаются постоянные прерывания, требования об исправлениях оши­

бок и запросы от коллег, создающие помехи реальной работы? Тогда меха­
низм

stash создан именно для вас!

Stash —

это механизм , позволяющий « захватить ~ ваш рабочий процесс ,

позволяя вам сохранить ее и вернуться к ней позже, когда вам будет удобно.
По сути, у вас есть механизм фиксации , но

stash —

это более продвинутый

механизм, позволяющий захватить состояние вашего индекса и рабочего
каталога одной простой командой. Он оставляет чистым и непротиворечи­
вым ваш репозитарий, а также готовым к альтернативному направлению

разработки. В результате вы можете возобновить работу именно с того ме­
ста, где закончили.

Давайте посмотрим, как

stash

работает с каноническим вариантом исполь­

зования: с так называемым . Однако, когда необходимо разрешение

конфликтов,

Git

не будет отбрасывать состояние

на всякий случай. Как

только конфликты будут разрешены, вам нужно вручную отбросить преды­

дущее сохраненное состояние командой

git stash drop, чтобы удалить его из

стека состояний.
Если вы хотите только воссоздать контекст, сохраненный в стеке состояний

без его удаления из стека, используйте команду

— это успешная команда apply,

git stash apply.

после которой следует команда

Команда рор

drop.

Какую команду,
понадобится

apply или рор , использовать, думаю понятно . Если вам еще
это сохраненное состояние, используйте apply, если вы хотите

восстановиться без сохранения состояния, используйте рор.
Команда

git stash list выводит стек сохраненных контекстов

от самого

последнего до самого старого:

$ cd my-repo

$ 1s

filel file2
$ echo «some foo»

>>

filel

$ git status

# On branch master

# Change s no t staged f or commit :
# (us e «git a dd . .. » to update what will

Ье

committed)

# (use «git checkout — … » to discard changes in
wo rki ng directory )

#
# modified: filel
#

‘- ————————— —- —————— ——— ———————— -f!il

Git.

Практическое руководство

no changes added to comrnit (use «git add» and / or «git comrnit
— а»)

$ git stash save » Исправление file l»

Saved working directory and index state On master:
fi lel
HEAD is now at 3889def Add some files

Ис правление

$ git commit —dry-run

branch master
nothing to comrnit (working directory clean)
#

Оп

$ echo « some bar»

>>

file2

$ git stash save » Редак’l’ирование file2 «

Saved working directory and index state On master:
Редактирование file2
HEAD i s now at 3889def Add some files
$ git stash list

stash@{0}: On master :
stash@{l}: On master:

Git

file 2
filel

Редактирование
Исправление

всегда присваивает самому последнему состоянию число О . П оскольку

записи становятся старше, увеличиваются и их номера. Имена различных

записей

stash — stash@{O}, stash@{1} «Reflog~.

о них мы еще поговорим в разделе

Команда

git stash show показывает изменения индекса и файлов, записан­
ные для заданной записи stash, относительно к ее родительской фиксации :
$ git stash show

file2 1 1 +
1 files changed , 1 insert i ons(+) ,

О

deletions(-)

Эта сводка может предоставить вам ту информацию, которую вы искали.

Если же она показалась вам малоинформативной, добавьте опцию -р, чтобы
увидеть другую полезную информацию. Обратите внимание на то, что по

&1-··················································································

Глава

умолчанию команда

и

11. Stash

reflog

git stash show показывает наиболее последнюю запись,

stash@{O}.
Поскольку изменения, которые используются для создания stаsh — состояния ,
относительны определенной фиксации, показ состояния

— это сравнение со­

стояние-состояние, что больше похоже на вывод

а не на последова­

git diff,

тельность фиксаций

(git log). Таким образом , все опции, подходящие для git
diff, можно указывать и для git stash show.
А сейчас давайте посмотрим на использование опции -р для получения раз­

личий · в патче для данного stаsh — состояния:

$ git stash show

stash@{l}

diff — git a / fil e l Ь/ filel
index 257 сс 5 6 . . f 9e 62e 5 1 0064 4
a / filel
+++ Ь/ filel
@@ -1 +1 , 2 @@

fo o
+some f oo
Рассмотрим другой классический случай использования

git stash. Пока вы

не знакомы с использованием удаленных репозитар ие в и получением из ­

менений по запросу, для вас данная информация мало целесообразно. Но

очень скоро она для вас будет очень актуальной. Допустим , вы ведете разра ­
ботку в своем локальном репозитарии и сделали несколько фиксаций . У вас
есть некоторые измененные файлы, которые вы еще не зафиксировали , но
вы понимаете, что есть восходящие изменения, которые вам нужны . Если у

вас будут конфликтные изменения, обычная команда

git pull

провалится,

отказываясь перезаписать ваши локальные изменения . Один из способов

решить эту проблему

— использовать git stash:

$ git pull

#

с б ой

pull

$ git stash save

$ git pull

$ git stash

рор

и з — за

к о нфликт о в

с ли я ния

.. .

…. — —- . ——— . ————-. ——- — — —. — —. — —— — —-. —- —— —

Git.

Практическое руководство

В данной точке, возможно, вам придется разрешить конфликты, создан­

ные командой рор. В случае если у вас есть новые, незафиксированные

значит origin / master
First , rewinding head to replay your work on top of it . . .
Applying:

А

fix for

а

bug.

Applying : The fix f o r s omething else .

.. —-. —. —.. —.. — —-. ———.. —. ·- -. —————. ——-. — ——.. -. —

Git.

Практическое руководство

После того, как вы получите фиксации из удаленного репозитария и пе­

ребазируете ваши локальные фиксации на их вершину, ваш репозитарий
подходит для отправки вашей работы в удаленный репозитарий. Как ре­

шите, вы можете отправить свою работу в удаленный репозитарий коман­
дой

git push:

#

О тправляем вашу работу в удаленный реп о зитарий!

$

git push

Или после восстановления вашего предыдущего состояния рабочего ка­
талога:

$ git stash рор

Auto-rnerging filel . h
# Оп branch rnaster
# Your branch is ahead of ‘origin / rnaster’

Ьу

2 cornrnits .

#
# Changed but not updated:
# (use «git add … » to update what will

cornrnitted)
# (use «git checkout — … » to discard changes in
wo rking directory)
Ье

#
# rnodified: filel.h

# rnodified: filel.c

#
по

changes added to cornrnit (use «git add» and/or «git cornrnit

— а «)

Dr opped ref s / stash@ {О}

( 7е254 6f5808a95a2e6934fcffЬ554 8 651badf0

Od)
$ git push

Если вы решите использовать

git push

после извлечения вашего stаsh­

состояния, помните, что только завершенная, зафиксированная работа
будет отправлена в удаленный репозитарий. Не нужно волноваться об от­
правке вашей частичной, незавершенной работы.

E:Et ········ · ······ ··· ·· · · ····· ·· · · · · ·· · · ···· · ··· · ·· · ·· ·· ··· ·· ·· · ··· · · · — · · · ··· · · · · ····

Глава

11. Stash

и

reflog

Иногда восстановление предыдущего состояния может повлечь за собой
трудноразрешимые конфликты слияния. Однако, вы все еще можете вос­
становить сохраненное состояние в новую ветку. Для этого используется

команда

git stash branch.

Данная команда преобразовывает содержимое

сохраненного состояния в новую ветку на основе фиксация, которая была

текущей на момент создания stаsh-записи.
Давайте посмотрим, как это работает на практике:

$ qit loq —pretty=one
d5efбc9

—aЬbrev-commit

Some commit .

efe990c Initial commit .
Теперь сохраняем ваше текущее состояние:

$ qit stash
Saved working directory and index state WIP on master :

d5efбc9

Some commit.
HEAD is now at

d5efбc9

Обратите внимание на

Some commit .

ID фиксации d5ef6c9.

Далее вы сделали несколько фиксаций, и ветка ушла из состояния

$ qit loq —pretty=one

d5ef6c9.

—aЬbrev-commit

2c2af13 Another mod
ldle905 Drifting file state .
Some commit .

d5efбc9

efe990c Initial commit .
•$ qi t show-branch

[master] Another mod
И хотя сохраненная работа доступна, она не может быть чисто применена к
текущей ветке

master:

$ qit stash list

·······-·························································-············· · · · fJ!I

Практическое руководство

Git.

stas h@ (0J : WIP on master: d5efбc9 Some commit .
$ qit stash рор

Auto — merging foo
CONFLI CT

(content): Merge conflict in foo

Auto — merging bar
CON FLICT

(content ): Merge conflict in bar

Давайте создадим новую ветку с названием mod, в которую и выгрузим
сохраненное ранее состояние . Только перед этим нужно сбросить текущее
состояние:

$ qit reset —hard master

HEAD is now at 2c2afl3 Another mod
$ qit stash branch mod

Sw it ched to

а

new b r anch ‘ mod ‘

# On branch mod

# Ch anges not staged for commit :
# (use «git add … » to update what will

Ье

committed)

# (use «git checkout — . .. » to discard changes in
working directory)

#
# mod ified : bar
# modified : foo

#
no changes added to commit

(use «git add» and / or «git commit

-а»)

Dropped ref s/ stash@

{О}

( 96e5 3 daбlf7e503 lef04d68Ьf 60a 3 4bd4 fl ЗЬd

9f )
Есть несколько важных моментов, на которые следует обратить ваше вни­
мание. Во-первых , заметьте, что созданная ветка основана на исходной фик­

сации

d5ef6c9, а не на текущей

$ qit show-branch

фиксации

2c2af13.

[master] Another mod

IZ!I- ·· · ········ · ·············· · ·· · ······················ · ······ · ··········· · ········ ‘

Глава

11 . Stash

и

reflog

* [mod ] Some commit .
[master ] Another mod
+ [masterл ] Drifting file state .
+* [mod] Some commit .

+

Во-вторых, поскольку сохранное состояние всегда воссоздается против ис ­

ходной фиксации, команда всегда будет успешно выполнена, а восстановле­
ние состояние

— отброшено из стека состояний.

Наконец, воссоздание сохраненного состояние автоматически не фиксиру­

ет ни одно из ваших изменений в новой ветке . Все сохраненные модифика­

ции файла ( изменения индекса, если требуется) останутся в вашем рабочем
каталоге на новой активной ветке.

$ qit commit —dry-run

# On branch mod
# Changes not staged f or commit :
# (use «git add … » to update what will

Ье

committed)

# (use «git checkout — … » to discard changes in

working directory)

#
# modified : bar
# modified : foo
#
no changes added to commit (use «git add» and /o r «git commit
-а»)

В этой точке, конечно, вы можете фиксировать изменения на новую ветку,

если посчитаете необходимым . Нет, это не чудодейственное средство про­
тив конфликтов слияния. Однако , если при попытке восстановления сохра­

ненного состояния непосредственно на ветку

master

будут конфликты, по­

пытайтесь восстановиться в новую ветку. Однако слияние этой новой ветки
с веткой

master приведет к тем же

$ qit commit

конфликтам слияния.

-m «Stuff from the stash»

[mod 42cl04 f] Stuff from the stash

..

.. . . . . . -… — — .. — … —… — . — . -… —……. —… -… -… —.. . -. — -.. — — . — . -.. —

it.

Практическое руководство
О

2 files changed , 2 insertions(+),

deletions(-)

$ git show-branch

! [master] Another mod
* [mod] Stuff fr o m the stash

*

[mod] Stuff from the stash

+

[master] Another mod

+

[masterл]

+*

[modл]

Drifting file state .

Some commit.

$ git checkout master

Switched to branch ‘ master ‘
$ git merge mod

Auto-merging foo
CONFLICT (content ): Merge conflict in foo
Auto-merging bar
CONFLICT (c on tent) : Merge conflict in bar
Automatic merge failed ; fix conflicts and then commit the
result.
Напоследок позвольте дать небольшой совет относительно команды

stash.

git

Пусть приведенная аналогия будет грубой, но я все же ее приведу: вы

называете своих домашних животных, но нумеруете свой скот. Аналогич­

но, ветки называют, а stаsh-состояния

рабочее состояние

нумеруют. Возможность сохранять

прекрасна, но не злоупотребляйте ею и не создавайте

слишком много состояний. Если вы хотите долго хранить то или иное со­

стояние, преобразуйте его в ветку.

11 .2. Reflog
Хорошо, я признаюсь. Иногда

Git

делает что-то, что выглядит чем — то

таинственным или волшебным и что заставляет задавать вопрос: «Что же

произошло?1>. Иногда вопрос может звучать иначе: «Что же он сделал? Он

— — — — —- — ———— . — —. —- —- . — —.. —. — — -… -.. — —-… — .. — -.

Глава

11 . Stash

и

reflog

не должен быть сделать этого! ~. Но уже слишком поздно, вы потеряли глав­
ную фиксацию и результаты целой недели работы!
Не волнуйтесь!

Git

предоставляет команду

reflog,

которая, по крайней

мере, поможет разобраться в том, что же произошло . У вас также будет воз­
можность восстановить потерянные фиксации в случае, если что-то таки
потерялось.

Reflog —

это запись изменений в головы веток в пределах непустых репо­

зитариев . Каждый раз , когда делается изменение ссылки, в том числе и

HEAD, reflog обновляет запись ,

содержащую информацию об этом измене ­

нии . Думайте об этом механизме как о следе из хлебных крошек, который

позволяет определить, где вы были.

Reflog записывает сведения о следующих операциях:

Клонирование ;

Помещение данных в удаленный репозитарий ;

Создание новых фиксаций ;

Изменение или создание веток;

Операции перебазирования;

Операции сброса.

Обратите внимание, что некоторые сложные операции , такие как git fil terbranch, в конечном счете , сводятся к простым фиксациям и тоже регистри­
руются. Любая операция Git, изменяющая вершину ветки, будет записана.

По умолчанию

reflog включен во все непустых репозитариях и отключен в
reflog контролируется логической опци­
ей конфигурации core.logAllRefU pdates. Он может быть включен командой
git config core.logAllRefUpdates true или отключен путем передачи значения
false в ту же команду. Reflog включается/отключается отдельно для каждого
пустых репозитариях. В частности,

репозитария .

На что же похож

reflog?

$ git reflog show

a44d 980 HEAD @{ O}: r ese t : mov ing t o ma s te r

..

.. . . . . . . .. . . . . . . . . . . . . . . . . .. . . . . . . . .. . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . . . .. . . . . . .. . . .

Git.

Практическое руководство

79е881с

HEAD@{l}: comrnit : last foo change

a44d980 HEAD@{2}: checkout : moving from master to fred
a44d980

НЕАD@{З}:

rebase -i

(finish) : returning to refs/heads/

master
a44d980 HEAD@{4}: rebase -i

(pick): Tinker bar

a777d4f HEAD@{S}: rebase -i

(pick): Modify bar

е3с46Ь8

НЕАD@{б}:

rebase -i (squash) : More foo and bar with

additional stuff .
8а04са4

HEAD@{7}: rebase -i (squash) : updating HEAD

la4be28 HEAD@{B} : checkout: moving fr om master to la4be28
еdбе906 HEAD@{9}: comrnit: Tinker bar
6195b3d HEAD@{lO } : comrnit: Squash into ‘more foo and bar ‘
488Ь893

HEAD@{ll } : comrnit: Modify bar

la4be28 HEAD@{ 12}: comrnit : More foo and bar
8а04са4

HEAD@{ 13} : comrnit (initial): Initial foo and bar.

Не смотря на то, что

show

reflog записывает транзакции для всех ссылок, git reflog

показ ывает транзакции только для одной ссылки за один раз. Пре­

дыдущий пример показывает ссылку по умолчанию, то есть

HEAD.

Если

вы хотите просмотреть журнал изменений для другой ветки, укажите ее в

качестве параметра. В следующем примере мы выводим журнал изменений

ветки

fred:

$ git refiog fred

a44d980 fred@{O}: reset : moving to master
79е881с

fred@{l}: comrnit : last foo change

a44d980 fred@{2} : branch: Created from HEAD
Каждая строка

это отдельная транзакция из истории ссылки, начиная с

самого последнего изменения и вплоть до самого первого. Самый первый

столбец

— это ID фиксации на тот момент, когда она была сделана. Запи­
HEAD@{7} во втором столбце предоставляют удобные имена для
фиксации в каждой транзакции. Здесь HEAD@{O} — самая последняя за­
пись, HEAD@{1} — предпоследняя и т.д. Самая старая запись в нашем при­
мере — HEAD@{13}, это начальная запись в данном репозитарии. Оставша­
си вроде

..

яся часть каждой строки описывает, что же произошло. Также для каждой

. . . -.. — .. — -. —… — . — . — … —……. -…….. — ……. — … —.. — …. -…. -.. . — ..

Глава

11 . Stash

и

reflog

транзакции записывается время и дата ее осуществл ения (но здесь не по­
казывается).

Reflog выводит имена фиксаций

вроде

HEAD@{1}, которые можно

исполь­

зовать в качестве символьных имен фиксаций для л юбой другой команды

Git.

Например:

$ git show

comm i t
Author :

НEAD@{lO}

6195b3dfd30e464ffЬ9238d89e3d 1 5 f 2c l dc35b0

Ф едя Колобков

Date : Sat Oct 29 09 : 57 : 05 2020 — 0500
Squa sh into ‘ more foo and bar ‘
diff — git a / fo o

Ь/fоо

i ndex 7 4 0 f d05 .. а941931 100644
— a / f oo
+++

Ь/ f оо

@@ — 1 , 2 +1 @@
-Foo !
— mo re f oo
+junk
Это означает, что в процессе разработки вы записываете фиксации , пере­
мещаете ветки , выполняете перебазирование и другие манипуляции, но вы

всегда можете обратиться к

reflog, чтобы узнать символьное имя фиксации.
HEAD@{ 1} всегда ссылается на предыдущую фиксацию ветки, имя
HEAD@{2} — на основную фиксацию до этого и т.д . Имейте в виду, что не
всегда имя транзакции представляет имя фиксации. Ведь reflog записывает
Имя

каждое изменение ветки , в том числе, когда вы перемещаете вашу ветку на

другую фиксацию. Поэтому НЕАD@{З} не всегда означает третью с конца
операцию

git commit.
Примечание. Вы испортили слияние и хотите попытаться снова? Ис­
пользуйте команду
если нужно

git reset HEAD@{1 }.

Добавьте параметр

—hard,

.

········· ···· ········· · ··· ·························· ········· · ···················· -IIПI

Git.

Практическое руководство

Git также

поддерживает англоязычные спецификаторы, позволяющие ука­

зать, когда была сделана транзакция. Следующая команда показывает фик­
сацию

HEAD,

сделанную в прошлую субботу:

$ qit loq ‘ НEAD@{last saturday}’

commit
Author:

la4be2804f7382b2dd 39989 leef097eЫ0ddcleb
Федя Колобков

Date : Sat Oct 29 09 : 55:52 2020 -050 0
More f oo and bar
commit
Author:

8a04ca4207elcb74dd3a3e26ldбbe72ell8ace9e
Федя Колобков

Date: Sat Oct 29 09:55:07 2020 -0500
Initial foo and bar.

Git

поддерживает много спецификаторов для ссылок. Например:

(вчера),

noon

(полдень),

midnight

yesterday

(полночь), названия дней недели, назва­

ния месяцев, А.М . , Р.М., абсолютные даты и время, относительные фразы
вроде

last Monday (прошлый понедельник) , 1 hour ago (1 час назад), 10 minutes ago (10 минут назад) и их комбинации вроде 1 day 2 housr ago (1 день 2
часа назад).

Также вместо названия ветки, например,

fix@{noon} вы можете использо­
вать сокращение@{nооn}, при условии, что ветка fix — активна. Сокращение
@{noon} подразумевает использование текущей ветки .
Несмотря на то, что эти спецификаторы довольно либеральны, они не совер­
шенны . Помните, что

Git

использует эвристику, чтобы интерпретировать

их. Также помните, что понятие времени локально и относительно вашего
локального репозитария. Используя ту же фразу в другом репозитарии, вы

получите разные результаты. Если у вас нет истории

reflog,

покрывающей

заданный период, вы получите предупреждение. Например:

$ qit loq

..

НEAD@{last-monday}

warning: Log for ‘HEAD’ only goes back to Sat, 29 Oct 2020
09:55:07 -05 00 .

. . . .. . . . . . .. . . … .. .. . . . . . .. . . .. . . . . . .. . . .. . . .. . . . . . .. .. . .. . . . . . . . . . .. . . .. . . . . . .

Глава

11 . Stash

и

reflog

8a04ca4207elcb74dd3a3e261dбbe72e118ace9e

comrnit
Author:

Федя Колобков

Date: Sat Oct 29 09 : 55:07 2020 — 0500
Initial foo and bar.
Одно последнее предупреждение. Не позволяйте оболочке обманывать вас.
Между этими двумя командами есть значительная разница:

#

Не пра вильн о !

$ git log dev@{2 days ago}

#

Правильн о

$

git log ‘dev@{ 2 days ago}’

для

вашей

оболочке

Второй вариант важен для командной оболочки , чтобы она считала назва­
ние ветка со спецификаторами в ней одним параметром командной строки,

в противном случае строка

dev@{2 days ago}

будет расценена как

тра. Чтобы упростить проблему разрыва параметра,

Git

3 параме­

позволяет указы­

вать спецификаторы так:

#

Все

три

в ариан та

аналогичны

$ git log ‘dev@{2 days ago} ‘
$ git log dev@{2 .da ys .ago}
$ git log dev@{2-days-ago}
Есть еще один повод для

беспокойства. Если

Git поддерживает полную
историю транзакций, то как это сказывается на дисковом пространстве?
К счастью, об этом не нужно беспокоиться. Время от времени

Git запускает

процесс сборки «мусора>>. Во время этого процесса удаляются некоторые
старые записи reflog. Недостижимые фиксации удаляются спустя
после создания, а достижимые фиксации

30

дней

— спустя 90 дней.

Если такое расписание для вас не подходит, используйте переменные кон­

фигурации

gc.reflogExpire U nreachaЬle

и

gc.reflogExpire соответственно.
git reflog delete для удаления от­
команду git reflog expire для непосред-

Также вы можете использовать команду
дельных записей или использовать

· ·· ······· ·· ···· · ·· ·· ··· · · ·· ···· · ······· · ····· · ········· ····· ····· · ·· ······ · · · ·· ··-&1

Git.

Практическое руководство

ственного удаления старых записей. Эта же команда может использоваться

для принудительного истечения записей

$

$

reflog:

git reflog e xpire —e xpi re=now —a l l
git gc

Как вы могли предложить к настоящему времени,
заны. Фактически ,

stash реализован

на базе

stash и reflog глубоко свя­

reflog.

Одна важная деталь реализации: reflog хранит свои записи в каталоге .git/
logs. Файл .git/ logs/ HEAD содержит историю значений HEAD, а каталог
.git/ logs/ refs содержит историю всех ссылок, в том числе stash. Подкаталог
.git/ logs/ refs/ heads содержит историю голов веток.
Вся информация хранится в

reflog. Удаление

.git/ logs или отклю­
чение reflog нарушает внутреннюю структуру данных Git. Это означает, что
все ссылки вида master@{ 4} больше не могут быть разрешены.
С другой стороны, включенный

reflog

каталога

позволяет доступ к фиксациям , ко­

торые иначе могут быть недостижимыми. Если вы пытаетесь очистить ре­

позитарий с целью уменьшения его размера, отключение

reflog

приведет к

удалению недостижимых (то есть неважных) фиксаций.

— —— — —- —- — ———- — — — —— — — — ———— ————— —- .

Глава

12.

Удаленные
репозитарии

.

2

.

3

Git.

Практическое руководство

До сих пор вы работали с одним локальным репозитарием . Пришло вре­
мя рассмотреть хваленные распределенные функции

Git

и изучить, как

сотрудничать с другими разработчиками через совместно используемые
репозитарии . Для работы с удаленными репозитариями вам нужно знать
несколько новых терминов.

Клон

копия репозитария . Клон содержит все объекта оригинального ре­

позитария , в результате каждый клон

— это

независимый и автономный ре­

позитарий и истинный , симметричный колена оригинала. Клон позволяет

каждому разработчику работать локально и независимо без централизации,

загрузок и блокировок. В конечном счете, клонирование способствует мас­
штабируемости

Git и стирает· географические границы.

Отдельные репозитарии особенно полезны в следующих ситуациях :

Разработчики работают автономно

…. . .

·——————·—·—···—·-·——···——-··—·—······—··-· ·—-··

Глава

12.

Удаленные репозитарии

Разработчики распределены по всему миру. Группа разработчиком в од­
ном месте может совместно использовать локальный репозитарий для
накопления локализованных изменений

Ожидается, что будут несколько версий проекта, которые будут суще­
ственно отличаться друг от дру га

В предыдущих главах мы рассмотрели ветки , которые можно создавать в

пределах одного репозитария, а также механизмы их слияния. Однако при

желании и для получения большей масштабируемости отдельные направ­
ления разработки можно помещать в различные репозитарии, которые мо­

гут быть снова объединены, если это уместно . Клонирование репозитария
является первым шагом в совместном использовании кода. Вы также долж­

ны связать один репозитарий с другим , чтобы установить пути для обмена
данными.

Git устанавливает эти

Удаленная

соединения репозитария через удаленные.

— это ссылка (или дескриптор) на другой репозитарий через фай­

ловую систему или сетевой путь. В ы можете использовать удаленную как
сокращенное имя для длинного и сложного

Git URL.

Вы можете опреде­

лить любое число удаленных в репозитарии.
Как только удаленная установлена,

Git может передавать данные от одного
push или pull. Установившаяся

репозитария к другому с помощью модели
практика

передавать данные фиксации от исходного репозитария к его

клону из соображений синхронизации клона. Вы можете создать удален­
ную для перемещения данных от клона к его оригиналу или же настроить

двунаправленный режим обмена данными.
Чтобы отслеживать данные из других репозитариев
ленные ветки отслеживания

ветка

Git использует уда­
(remote-tracking branches). Каждая удаленная

это ветка, которая работает как прокси для определенной ветки в

удаленном каталоге. Вы можете настроить локальные ветки отслеживания,

которые формируют базис для интеграции ваших локальных изменений с
удаленными изменения из соответствующей удаленной ветки .

·———————————————————————————-18

Git.

Практическое руководство

Наконец, вы можете сделать свой репозитарий доступным для других.

Git

обычно называет это публикацией репозитария и предоставляет для этой
задачи несколько методов. В этой главе будут рассмотрены примеры и ме­
тоды для совместного использования, отслеживания и получения данных
через множество репозитариев .

12.1.

Понятия репозитария

Чистый репозитарий и репозитарий разработки
Репозитарий в
работки

Git может быть или чистый (bare) или репозитарием раз­
(development, nonbare).

Репозитарий разработки используется для нормальной, ежедневной раз­

работки. Он обслуживает текущую ветку и предоставляет копию текущей
ветки в рабочем каталоге . Все репозитарии, с которыми вы сталкивались до
этого в данной книге, были репозитариями разработки .
У чистого репозитария нет рабочего каталога, и он не может использоваться

для обычной разработки. В чистом репозитарии нет понятия ветки. Думай­
те о нем как о просто содержимом каталога

.git.

Другими словами, вы не

должны делать фиксации в чистом репозитарии.
Чистый репозитарий, как может показаться, мало полезен, но его роль край­

не важна: он служит авторитетным фокусом для совместной разработки.
Операции

clone , fetch и push выполняются

именно через чистый репозита­

рий . Чуть позже мы рассмотрим пример, как все это происходит.

Если вы запустите команду

git clone с опцией —bare, Git создаст чистый ре­

позитарий. В противном случае будет создан репозитарий разработки.

Примечание. Заметьте, мы не говорили , что

git clone —bare

создает

новый или пустой репозитарий. Мы сказали, что эта команда создает

чистый репозитарий. И этот только что клонированный репозитарий
будет содержать копию содержимого от uрstrеаm-репозитария.
Команда

git init

создает новый и пустой репозитарий , но этот новый

репозитарий может быть в одном из вариантов

,

чистый или разра —

. ……… ………………………………………………………………

Глава

12.

Удаленные репозитарии

ботки. Для большей конкретики нужно указывать опцию

—bare,

если

нужен именно чистый репозитарий:

$ c d /tmp
$ gi t

ini t fluff2

Initialized empty Git repository in / tmp / fluff2/ . git/
$ g i t ini t —bare fluff

Initialized empty Git repository in / tmp / fluff /
По умолчанию

включает

Git

позитариях разработки, но

reflog (запись
reflog выключен

изменений в ссылках) на ре­

на чистых репозитариях. Это

снова означает, что именно первый тип репозитариев предназначен для раз­

работки, но никак не последний. По тем же причинам нельзя создать уда­
ленные в чистом репозитарии .

Если вы настраиваете репозитарий, в который разные разработчики будут

помещать (с помощью команды

push)

изменения, он должен быть чистым.

Клонырепозитариев
Команда

git clone

создает новый репозитарий

Git,

основанный на ориги­

нальном репозитарии, который вы определяете через файловую систему

или сетевой адрес.

Git

Git

не копирует всю информацию из оригинала в клон.

игнорирует информацию, которая подходит только для оригинального

репозитария, например, удаленные ветки отслеживания.

При нормальном использовании

git clone

локальные ветки разработки ис­

ходного репозитария, сохраненные в гefs/heads становятся удаленными
ветками отслеживания в новом репозитарии-клоне и помещаются в

remotes. Удаленные

refs/

ветки отслеживания исходного репозитария не клони­

руются.

Теги исходного репозитария копируются в клон, как и все достижимые объ­
екты. Однако, специфичная для репозитария информация, такая как пере­

хватчики

(hooks), конфигурационные файлы, reflog и stash исходного репо­

зитария не воспроизводится в клоне.

В главе

3 было показано ,

как использовать

шего репозитария puЬlic_html:

git clone для

создания клона ва­

•.———————————————————————————&1

Git.

Практическое руководство

$ git c l o ne puЫi c_h t m l my_websi te

Здесь puЬlic_html рассматривается как исходный, «удаленный~ репозита­
рия . Клон будет называться

my_ website.

Аналогично, вы можете использовать

git clone для

создания копии удален­

ного р епозитария, например:

#

Все

$ gi t

в

о дн о й

стр о к е

c l on e

git: //g it.kernel. o r g/p u Ь/sc m / lin ux/k er n el / g it/to r v alds / lin ux —

2 . 6. g it
П о умолчанию, каждый новый клон содержит ссылку обратно на свой ро­
дительский репозитарий через удаленную с именем

origin.

Однако сам ро­

дительский репозитарий ничего не знает об этой ссылке. Это типичные
односторонние отношения .

Если вам не нравится имя

—origin

«origin,>,

вы можете изменить его, указав опцию

имя во время операции клонирования.

Git также

настраивает удаленную

origin для refspec fetch:

fet c h = +r efs / heads / *:re fs / remotes/o rigin / *
Установка этого

refspec

означает, что вы хотите обновлять ваш локальный

репозитарий, получая изменения от исходного репозитария. В этом случае
ветки удаленного репозитария доступны в клоне с именами с префиксом

origin/ , например, origin/ master, origin/ dev или origin/ maint.

Удаленные
Репозитарий , в котором вы в настоящее время работаете , вызывают локалъ­

нъtм или текущим репозитарием, а репозитарий, с которым Вы обменива­
етесь файлами , вызывают удаленным репозитарием. Но последний термин
не очень точный , потому что этот репозитарий может физически находить-

1!1———.. —… -.·—.. —… —… -.-.—.. —.. —.·—.. —· ……. -.. —· —… —.—.

Глава

12.

Удаленные репозитарии

ся, как на удаленной машине, так и на вашей локальной машине

— это просто

может быть другой репозитарий в локальной файловой системе.

Git использует удаленные отслеживания для упрощения соединения с дру­
гим репозитарием . Удаленная ветка предоставляет дружественное имя для
репозитария и может использоваться вместо фактического

URL

репози­

тария. Для создания, удаления, манипуляции и просмотра удаленных ис ­

пользуйте команду

git remote.

в файле

Также все удаленные могут управляться посредством

команды

.git/ config.
git config.

В дополнение к

Все созданные удаленные регистрируются

git clone доступны другие команды,

относящиеся к удален­

ным репозитариям:

gitfetch
Получает объекты и связанные с ними метаданные из удаленного репози­
тария.

git pull
Подобна

git fetch,

но также объединяет изменения в соответствующую ло­

кальную ветку.

gitpush
Отправляет объекты и относящиеся к ним метаданные в удаленный репо ­
зитарий

git ls-remote
Показывает список ссылок, хранимых данной удаленной . Позволяет отве­

тить на вопрос: .

·———————- — — —- —— ————- —— — —- ———————-

it.

Практическое руководство

Ветки отслеживания

Как только вы клонируете репозитарий, вы можете синхронизироваться с
оригинальным репозитарием, даже если вы делаете локальные фиксации и
создаете локальные ветки.

По мере развития самого

Git

развивалась и терминология . Некоторая тер­

минология уже успела стать стандартной . Чтобы разъяснить назначение

разных веток были созданные разные пространства имен. Несмотря на то,
что любые ветки в вашем локальном репозитарии все еще считаются ло­
кальными ветками, они могут быть раздел ены на разные категории.

Удаленные ветки отслеживания

— ассоциируются с удаленными и имеют

специальное назначение следовать за изменениями каждой ветки в уда­
ленном репозитарии.

Локальная ветка отслеживания

— это

форма ветки интеграции, которая

собирает изменения из вашей локальной разработки и изменения из уда­
ленной ветки отслеживания.

Любую локальную, неотслеживаемую ветку обычно называют топиком
или веткой разработки.

Наконец, удаленная ветка

— это ветка, расположенная в удаленном репо­

зитарии. Она может быть источником для удаленной ветки отслежива­
ния .

Во время операции клонирования

Git создает удаленную

ветку отслежива­

ния в клоне для каждой ветки разработки в удаленном репозитария . Набор
удаленных веток отслеживания представлен в новом, отдельном простран­

стве имен в локальном репозитарии, который является определенным для
удаленного, клонируемого . Локальный репозитарий использует свои уда­

ленные ветки отслеживания , чтобы отслеживать из менения , внесенные в
удаленном репозитарии.

Примечание. Вы можете вспомнить ссылки и символьные ссылки из

главы

что локальная ветка разработки, которую вы называете

на самом деле называется

dev,
refsjheads/dev. Точно также удаленные вет-

— ———————————————————————————-·

Глава

12. Удаленные репозитарии

ки отслеживания хранятся в пространстве имен
тельно , ветка удаленного отслеживания

refs/remotes. Следова­
origin/master на самом деле

— это refs/remotes/origin/master.
Поскольку удаленные ветки отслеживания помещены в собственное
пространство имен , есть четкое разделение между ветками, созданными в

репозитарии вами (ветки разработки), и ветками, которые, фактически, ос­
нованы на удаленном репозитарии (удаленные ветки отслеживания).

Все операции , которые вы можете выполнить на обычной ветке, могут быть
также выполнены на ветке отслеживания . Однако есть определенные огра­

ничения и инструкции, которые нужно соблюдать. Поскольку удаленные
ветки отслеживания используются исключительно для наблюдения за из­
менениями другого репозитария, вы должны обрабатывать их в режиме
только чтение. Вы не должны пытаться объединять их или создавать фик­
сации на них. В противном случае удаленные ветки отслеживания выйдут
из синхронизации с удаленным репозитарием. Надлежащее управление

ветками отслеживания описано далее в этой главе.

12.2.

Ссылки на другие

репозитарии
Чтобы координировать ваш репозитарий с другим репозитариям, вы опре­
деляете удаленную , которая сохранена в файле конфигурации. Она состо­

ит из двух частей . Первая часть задает имя другого репозитария в форме

URL.

Вторая часть называется

refspec

и она определяет, как ссылка (кото­

рая обычно представляет ветку) должна быть отображена от пространства
имен одного репозитария в пространство имен другого репозитария .

Давайте посмотрим на каждый из этих компонентов поочередно .

.————- ——- . — . — . — . — . ——— . — . — . -.. — . — —- — —. -.. — -.. — -. —

it.

Практическое руководство

Ссылки на удаленные репозитарии

Git поддерживает

несколько форм

URL (Uniform Resource Locators), кото­

рые вы можете использовать для задания имен удаленных репозитариев.

Эти формы определяют протокол доступа и размещение или адрес данных.
Технически,

Git не поддерживает ни URL, ни URI (универсальные иденти­
Git URL не соответствуют, ни RFC
1738 или RFC 2396. Поэтому формы URL, которые поддерживаются Git,
для краткости мы будем называть Git URL. Кроме того, в файле .git/ config
также используются Git URL.
фикаторы ресурса), поскольку формы

Самая простая форма

Git URL

ссылается на репозитарий , находящийся в

локальной файловой системе, будь это физическая файловая система или
виртуальная файловая система, смонтированная локально через сетевую

файловую систему

(Network File System, NFS).

Рассмотрим две переста­

новки:

/п уть /к/ реп о .git
file: /// п y ть / к / peп o .git

Несмотря на то, что эти две формы чрезвычайно похожи , между ними есть

тонкое , но важное отличие. Чтобы избежать проблем, связанных с совмест­
но используемыми репозитариями, рекомендуется использовать форму

file://.
Другие формы

Git URL

относятся к репозитариям в удаленных системах .

Когда у вас есть действительно удаленный репозитарий, данные которого
нужно получить через сеть, самую эффективную форму передачи данных

начато называют собственным протоколом
внутренний протокол

Git, используемый
URL с использованием этого протокола:

Git (Git native protocol).

Это

для передачи данных . Примеры

g i t : //ex a mpl e . co m / п y ть / к / p eпo .git

g it: //е ха mрlе. соm/~ п о льз о ватель / п у ть / к / реп о .git

. ……… ………………………………………………….. …….. … .. ..

Глава

Git-daemon

12.

Удаленные реnозитарии

использует эти формы для публикации репозиториев для ано­

нимного чтения . Эти формы

URL

можно использовать, как в операции

clone, так и в операции fetch.
Данные формы не предусматривают аутентификации клиента, никакие

пароли для доступа к репозитарию не запрашиваются. Следовательно, как
может использоваться формат -пользователь для ссылки на домашний ка­

талог пользователя, если

не несет никакой смысловой нагрузки. По сути,

здесь нет аутентифицированного пользователя, чей бы домашний каталог

можно было использовать. Поэтому форма -пользователь работает только,
если сторона сервера разрешает ее опцией

—user-path.

Для безопасных , аутентифицируемых соединения

Git предлагает туннели­

рование посредством SSН-соединения :

ssh://[пользователь@]ехаmрlе.соm[:порт]/путь/к / репо.git

ssh://[пользователь@]ехаmрlе.соm / путь/к/репо.git
ssh://[пользователь@]ехаmрlе . соm/~пользо ватель 2/путь/к/ре п о .

git
ssh://[пользователь@]ехаmрlе.соm/~/путь/к/репо.git

Третья форма позволяет два разных имени пользователя . Первое исполь­
зуется для аутентификации сеанса, а второе

используется для доступа к

домашнему каталогу.

Git также поддерживает URL в

sср-стиле. Они подобны SSН-формату, но в

них не указывается порт:

[пользователь@]ехаmрlе.соm:/путь/к/репо.git
[пользователь@]ехаmрlе.соm:~пользователь/путь/к / репо . git

[польз о ватель@]ехаmрlе. соm :п уть/к/репо . git

Хотя протоколы НТТР и

Git,

в версии

HTTPS

поддерживались с самых ранних версий

1.6.6 они подверглись важным

изменениям.

http: // example.com / пyть / к / peпo.git
https : //example.com/пyть/к/peпo.git

.. . . -. — .. —.. -.. —… —.. -… — —.. -. .. —.. —… -… —… -. -. ——-.. — . —..

Git.

Практическое руководство

До версии

HTTPS не были так эффективны , как соб­
ственный протокол Git. В версии 1.6.6 была существенно улучшена под­
держка протоколов НТТР / HTTPS и они стали столь же эффективными
как собственный протокол Git.
1.6.6

ни НТТР, ни

Учитывая улучшенную поддержку НТТР /

HTTPS,

теперь эти формы

URL

станут более популярными. Хотя бы потому, что большинство корпоратив­
ных брандмауэров оставляет порты
а родной протокол

80 (НТТР) и 443 (HTTPS) открытыми,
Git использует порт 9418, который обычно блокируется,

что требует настройки брандмауэра. К тому же эти протоколы используют­
ся многими популярными хостинг-сайтами
Наконец, поддерживается протокол

Git вроде GitHub.

Rsync:

rsync: // example.com / пyть/к / peпo . git

Протокол

Rsync использовать не рекомендуется.

С его помощью вы можете

создать только начальный клон, но если вы продолжите использовать этот

протокол для дальнейших обновлений, это может привести к потере ло­
кально созданных данных.

Refspec
В главе

6

было показано, как ссылка именует определенную фиксацию в

истории репозитария. Обычно ссылка

это имя ветки.

Refspec —

это осо­

бый вид ссылки, который отображает имена веток удаленного репозитария
в имена веток в вашем локальном репозитарии.

Поскольку rеfsрес-ссылка должна одновременно ссылаться и на локальный
и на удаленный репозитарии , в

refspec часто требуется указывать полные
refspec имена веток разработки начинаются префиксом refs/
heads, а имена удаленных веток отслеживания начинаются префиксом refs/
rernotes/
имена веток. В

Rеfsрес-синтаксис следующий:

[+]источник:назначение

. . ………………………………………………………………………..

Глава

12.

Удаленные репозитарии

состоит из двух частей: ссылки источника и ссылки назначения,

Refspec

разделенных двоеточием. В начале строки может стоять ~ плюс>>

( +),

ко­

торый указывает, что во время передачи не будет использоваться обычная
проверка безопасности. Кроме того , звездочка(*) означает все имена веток.

В некоторых случаях ссылка источник необязательна, но вторая часть, то
есть двоеточие и назначение

— обязательна.

Rеfsрес-ссылки используются командами

git fetch

и

git push.

Но здесь

есть особый трюк. Формат rеfsрес-ссылки всегда одинаковый , то есть
источник: назначение. Однако , роли источника и назначения зависит от

выполняемой Git-операции . Здесь вам поможет таблица

Таблица

Операция

push

fetch

12.1.

Потоки данных

12.1.

refspec

Источник

Назначение

Локальная ссылка (будет

Удаленная ссылка (будет обновле-

отправлена)

на)

Удаленная ссылка (будет

Локальная ссылка (будет обновле-

получена)

на)

Типичная команда

git fetch использует ссылку refspec вида:

+refs / heads /* :ref s /re mote s / r emote/*
Этот

refspec можно перефразировать так:

Все ветки источника из удаленного репозитария в пространстве имен

heads

ref/

будут отображены в ваш локальный репозитарий с использованием

имени, собранного из имени

remote

и помещены в пространство имен

refs/

renotes/remote.
Вы можете использовать звездочку (*) , например,

refs/ heads/ *, что

позво­

ляет применять такую маску сразу ко многим веткам. Из-за звездочек эта

,

refspec
_

применяется ко всем веткам, которые будут найдены в

refs/ heads

— …… -. — .. — .. .. -… -.. ·- -.. . — .. -….. . — . — ·- — .. — . — — . ——- … — ·- — —

Git.

Практическое руководство

удаленной. Эта спецификация заставляет ветки темы отображаться в про­
странство имен вашего репозитария в качестве удаленных веток отслежива­
ния и разделяет их на подимена на основе удаленного имени.

Примечание. Используйте команду

gi t

show -ref для вывода спи­

ска ссылок в вашем текущем репозитарии. Команда

gi t ls-remote

репозитарий выводит ссылки в удаленном репозитарии.

Поскольку первый шаг команды

git pull —

это выборка

(fetch), refspec

вы­

борки также применяется и к git pull. Бы не должны производить фиксации
или слияния на удаленной ветке отслеживания на правой стороне rеfsрес­

ссылки команд

pull или fetch.

Эти ссылки будут использоваться как удален­

ные ветки отслеживания.

Операция

git push

обычно используется для публикации изменений, кото­

рые вы сделали в ваших локальных ветках разработки. Чтобы разрешить
другим пользователям найти ваши изменения в удаленном репозитарии
после того, как вы загрузите их, ваши изменения должны появиться в том

репозитарии как ветки разработки.
Итак, во время обычной команды

git push

ветки из вашего репозитария от­

правляются на удаленный репозитарий, при этом используется примерно

такая

refspec:

+ref s/ heads / *:refs / heads / *
Данную

refspec

можно перефразировать так:

Из локального репозитария взять каждую ветку, найденную в пространстве

имен

refs/heads/

и поместить ее в пространство

refs/heads

удаленного репоз­

тария под тем же именем.

Первая

refs/ heads

ссылается на ваш локальный репозитарий, а вторая ссы­

лается на удаленный репозитарий. Звездочки позволяют убедиться, что все
ветки будут реплицированы .

&1-………………………………………………………………………

Глава

Командам

git fetch

и

12. Удаленные

репозитарии

git push можно передать несколько rеfsрес-ссылок.
refspec в команде git push. Но как же тогда Git

Можно вообще не указывать

узнает, куда отправить данные?
Во-первых, если явно удаленный репозитарий не указан в командной стро­

ке,

Git предполагает, что вы хотите использовать origin. Без указания refspec
команда git push отправит ваши фиксации в удаленный репозитарий для
всех веток, которые будут общими между вашим локальным и удаленным
репозитариями. Любая локальная ветка, которой нет в удаленном репоз и­

тарии, не будет отправлена. Таким образом, чтобы записать в удаленный
репозитарий новую ветку, это нужно сделать явно

После их можно будет отправлять одной командой

— по имени этой ветки .
git push. Исходя из все го

сказанного, следующие две команды эквивалентны:

$

git pus h o r i gi n bran ch

$

git push or igin bra n ch :ref s / heads / branc h

12.3.

Примеры

использования удаленных
репозитариев
Теперь у вас есть необходимый минимум, чтобы приступить к некоторому
сложному совместному использованию

Git.

В этом разделе будет показано,

как использовать несколько репозитариев на одной физической машине .

В реальной жизни все будет практически также, за исключением того , что ,
возможно, эти репозитарии будут расположены на разных узлах Интернета.
Давайте рассмотрим общий сценарий использования

Git.

Ради иллюстра­

ции давайте настроим репозитарий, который все разработчики будут счи­
тать авторитетным, несмотря на то, что технически он ничем не отличается

от других репозитариев. Другими словами, авторитетность основана лишь

в том, что все считают его авторитетном, а не в каких-либо особых мерах

безопасности .

……. … … . ….. ……. … …….. ……… —………. — . .. — …. … … …… …. .

Git.

Практическое руководство

Данный репозитарий, который мы будем считать авторитетным , часто по ­

мещается в специальный каталог и называется базой
употреблять термины главный

(master)

и репозитарий

(depot). Не нужно
(repository), чтобы

не было путаницы в терминологии.
Часто есть серьезные основания для того, чтобы настроить базу. Например,

вы хотите заставить своих коллег помещать свои наработки в базу, чтобы
избежать катастрофических потерь. База будет удаленным источником для
всех разработчиком.
Следующие разделы показывают вам , как создать базу, клонировать ее, а
также произвести синхронизацию с ней.

Чтобы проиллюстрировать параллельную разработку базе, ее клонирует
второй разработчик, после чего он будет работать с клоном , а затем поме­
стит свои изменения обратно в базу, чтобы они стали доступны всем.

Создание авторитетного репозитария
Вы можете поместить свою базу в любой место вашей файловой системы. В
этом примере мы будем использовать каталог

/ tmp/ Depot.

В этом каталоге

или в одном из его репозитариев не должна вестись фактическая разработ­
ка. Вместо этого отдельные разработчики должны использовать его клоны .
На практике этот авторитетный репозитарий часто размещается на неко­

тором сервере, например, на

GitHub, git.kernel.org

или одной из частных

машин.

Данные шаги обрисовывают в общих чертах то , что нужно, чтобы преобра­
зовать репозитарий в другой чистый клон , способный быть авторитетным
репозитарием, то есть базой.
Первый шаг

заполнить

/ tmp/ Depot

начальным репозитарием. Предста­

вим , что вы хотите работать с содержимым веб-сайта, которое сейчас на­
ходится в — /puЬlic_html. Также представим , что в -/puЬlic_html уже есть

Git-репозитарий, поэтому нам нужно сделать копию репозитария — /puЬlic_

html и поместить его в /tmp/Depot/puЬlic_html.git.
#

Считаем ,

ВI —

что

в

~/ puЬlic_html

уже

соз д ан

репо зит арий

Git

———————————————————————————.

Глава

12.

Удаленные репозитарии

$ cd /tmp/Depot/
$ git clone

—Ьаrе ~/puЫic_html puЫ i c_html.git
/tmp/Depot/puЫic

Initialized empty Git repository in

html.

git/
Команда

clone

копирует удаленный репозитарий

кущий рабочий каталог, то есть в

/ tmp/ Depot.

Git из

-/puЬlic_html в те­

Последний аргумент

это

имя нового репозитария, то есть puЬlic_html.git. В данном случае мы ис­

пользуем имя с суффиксом

.git. Это

не обязательно, но считается хорошим

тоном.

У исходного репозитария разработки есть полный набор файлов проекта,

проверенных на верхнем уровне, хранилище объектов и все конфигураци ­
онные файлы расположены в подкаталоге

.git:

$ cd ~/puЫic_html/

$ 1s -aF

./ fuzzy . txt index.html techinfo . txt
.. /

. git/ poem.html

$ 1s — aF .git

. / config hooks/ objects/
. . / description index ORIG HEAD
branches / FETCH_HEAD info / packed-refs
COММIT_EDITMSG

HEAD logs / refs/

Поскольку у чистого

(bare)

репозитария нет рабочего каталога, у его фай­

лов более простая разметка:

$ cd /tmp/Depot/

$ 1s -aF

puЫic_html . git

. / branches/ description hooks/ objects/ refs/
.. / config HEAD info / packed-refs
Теперь вы можете обработать этот чистый репозитарий /tmp/Depot/puЬlic_

html.git как авторитетную версию.

Поскольку использовалась опция —Ьаге во время операции клонирования,

Git не представил удаленную remote.

‘-

— —- ——- ——- ——- — — — ———— —- — —- — ——- — ——— — —

Git.

Практическое руководство

Далее приведена конфигурация нового, чистого репозитария:

#

В

/ tmp / Depot / puЬlic_html . git

$ cat config

[core]
repositoryformatversion

О

filemode = true
bare = true

Создание вашей собственной удаленной

origin

Прямо сейчас у вас есть два репозитария, которые фактически идентичны,

за исключением того, что у начального репозитария есть рабочий каталог, а
у клона

— нет.

Кроме того, поскольку репозитарий -/puЬlic_html в вашем домашнем ката­
логе создавался с использованием

ния, у него нет

origin.

git init,

а не через операцию клонирова­

Фактически, у него вообще нет удаленной конфигу­

рации.

Однако ее достаточно просто добавить. В некотором смысле вы должны
вручную преобразовать свой начальный репозитарий в полученный клон.

Разработчик, который клонирует базу первым, автоматически создаст

origin.

git remote.
представляет несколько новых настроек в файле .git/ config:
Команда для управления удаленными называется

Эта операция

$ cd ~/puЫic_html
$ cat . git/config

[core]
repositoryf o rmatversi o n

О

filemode = true
bare = false
l o gallrefupdates = true
$ git r emote add origin

/tmp/Depot/puЬlic_html

&1—————————————————————….. —.—· ·—-.-.

Глава

12.

Удаленные репозитарии

$ cat . git/config

[core]
reposit o ryformatversion

О

filemode = true
bare = false
logallrefupdates = true
[remote «origin»]
url = / tmp / Depot / puЫic_html
fetch = +refs / heads/*:refs/remotes/origin / *
Команда

origin

git remote

добавила новый раздел

remote

с названием

origin.

Имя

не является каким -то магическим или специальным. Вы можете ис­

пользовать любое другое имя, если в этом есть необходимость .
Удаленная устанавливает связь между вашим текущим репозитарием и уда­

ленным репозитарием , в нашем случае с /tmp/Depot/puЬlic_html . git, как
указано в параметре

url. Как уже было отмечено, использовать суффикс .git

совсем необязательно: и /tmp/ Depot/puЬlic_html, и /tmp/ D epot/puЬlic_

html.git будут работать. Теперь в этом репозитарии вы можете использовать
имя origin для доступа к удаленному репозитарию.
Отношения между репозитарием, который содержит удаленную ссылку

и удаленным репозитарием асимметричны. Удаленная всегда указывает в
одном направлении от репозитария до удаленного репозитария. Другими
словами: клон всегда знает, какой репозитарий является основным , но ос­
новной репозитарий ничего не знает о клонах.

Давайте завершим процесс настройки удаленной

origin

путем установки

новой удаленной ветки отслеживания в исходном репозитарии для пред­
ставления веток из удаленного репозитария . Во-первых, как вы можете ви­
деть, здесь есть только одна ветка

#

Вывод

в сех

$ git branch
* master

веток

Теперь используйте команду

— master:

git remote update:

$ git remote update

·— — — ——- — —- — — — — — —- —— — — —— —— — — — —— — — ——— — — -&1

Git.

Практическое руководство

Updating origin
From / tmp / Depot / puЫic html
* [new branch] master -> origin / master
$ git branch -а

* master
origin / master
В зависимости от вашей версии

быть покащана без

Git удаленная ссылка отслеживания может
или с префиксом remotesj:

* master
remotes / origin / master
$

git branch

* master
remotes / origin / master

origin/ master в репозитарий. Это
origin. Никто не ведет разра­
ботку в этой ветке. Вместо этого ее назначение — хранение и отслеживание
изменений, сделанных в удаленной origin ветки master репозитария . Вы
Git

представил новую ссылку с именем

удаленная ветка отслеживания в удаленной

должны считать ее прокси локального репозитария для фиксаций, сделан­

ных в удаленной, в -конечном счете, вы можете использовать ее, чтобы пере­
нести те фиксации в ваш репозитарий.

Фраза

«Updating

origiш,, выводимая командой

git remote update, вовсе

не

означает, что удаленный репозитарий будет обновлен. Вместо этого она
означает, что будет обновлена ссылка

origin

локального репозитария. Эта

ссылка будет обновлена на основе информации, полученной из удаленного
репозитария.

Примечание. Команда

git remote update обновит каждую удаленную

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

$ git remote update

имя_удаленной

— —- — ——- —— ——- ——— — — —— — ———— —-. -… —-. — . —.

Глава

Также вы можете указать опцию
борку

$

(fetch)

-f, чтобы

12.

Удаленные репозитарии

немедпенно произвести вы ­

из удаленного репозитария, заданного опцией

git remote add -f origin

-f:

репозитарий

Теперь вы соединили ваш репозитарий с удаленным репозитарием в вашей

базе.

Разработка в вашем репозитарии
Давайте произведем некоторую работу в вашем репозитарии и добавим
другую поэму

— файл fuzzy.txt:

$ cd ~/puЬlic_html

$ qit show-branch

[master] Merge branch ‘rnaste r ‘ of . . /rny_website
$ cat fuzzy.txt

Fuzzy Wuzzy was а bear
Fuzzy Wuzzy had no hair
Fuzzy Wuzzy wasn ‘ t very fuzzy,
Was he?
$ qit add fuzzy . txt
$ qit commit

Created comrnit бf16880: Add а hairy poern .
1 files changed, 4 insertions(+), О deletions( — )
create rnode 100644 fuzzy.txt
$ qit show-branch

* [rnaster] Add

а hairy роет .
[origin / master] Merge branch ‘master’ o f . . /my_website

*

[rnaster] Add а hairy роет.
[origin/rnaster] Merge branch ‘rnaster’ of .. / rny_website

·-· . …. …. .. .. …….. … … ….. . .. .. ··············· ………………. · ··· ···

Git.

Практическое руководство

В этой точке у вашего репозитария на одну фиксацию больше, чем в репо­
зитарии в

/ tmp/ Depot.
(master) с

ветки, одна

Более интересно, что у вашего репозитария есть две
новой фиксацией, а другая

(origin/ master) — ветка

отслеживания удаленного репозитария.

Передача ваших изменений
Любое фиксируемое вами изменение абсолютно локально для вашего репо­

зитария и не передается автоматически в удаленный репозитарий. Чтобы

master в удаленный
команда git push с параметром master:

передать изменения ветки

репозитарий , используется

$ git push origin master

Counting ob jects: 4, done .
Compress ing objects: 100% (3 /3 ), done .
Writing objec ts: 100 % (3/3) , 400 bytes, done.
Total 3 (delta 0) , reused

О

(delta

О)

Unpacking ob jects: 100 % (3/3 ), done.
То

/tmp/Depo t / puЫic_html

0d4ce8a ..
Этот вывод

master — > master

бf16880

Git

означает, что изменения ветки

ному репозитарию с именем

origin. Git

master

отправлены удален­

также производит дополнительное

действие: он берет эти же изменения и добавляет их в ветку
в вашем репозитарии.

Git

origin/ master

достаточно умен, чтобы не загружать эти же из­

менения с удаленного репозитария, ведь, по сути, фиксации уже находятся
в вашем репозитарии.

Теперь обе локальные ветки

(master

и

origin/ master)

отображают одинако ­

вые фиксации:

$ git show-branch

* [master] Add

а

hairy poem .

[origin/master] Add

*+ [master] Add

а

а

hairy poem.

hairy poem.

.. -·· ·······-··-····-··· .. — . ··- ···-·········· … —·- ··—· · · -···- -· …. ··········

Глава

12.

Удаленные репозитарии

Можно зондировать удаленный репозитарий и проверить, что он также был
обновлен. Если удаленный репозитарий находится в локальной файловой

системе, это легко сделать, перейдя в каталог базы:

$ cd /tmp/Depot/puЬ li c_html.git
$ git show-branch
а

[master] Add

hairy poem.

Когда удаленный репозитарий физически находится на другой машине,

следующая команда может быть использована для определения информа­
ции ветки удаленного репозитария:

#

Переходим

опра шиваем

к

действительно

удаленн ому

реп о зитарию и

ег о

$ git ls-remote origin
6fl68803fбflb987dffd5fff7753ldcadf7f4b68

HEAD

6fl68803 fбflb987dffd5fff 7753 ldcadf7f4b 68

refs / heads / master

Затем вы можете показать, что те

10 фиксации

соответствуют вашим теку­

щим, локальным веткам с использованием чего-то подобного

git rev-parse

HEAD или git show id-фиксации.

Добавление нового разработчика
Как только вы установили авторитетный репозитарий, достаточно просто

добавить нового разработчика в проект, разрешив ему клонировать репози­
тария и начинать работу.
Давайте добавим в проект пользователя ВоЬ, предоставив ему его собствен­

ный клон репозитария , в котором он будет работать :

$ cd /tmp/bob
$ git clone /tmp/Depo t/puЬlic_html . git

Cloning into
done .

‘puЫic_html’

….

.———…… -. — . —— .. -…… -……. —· — -.. — —. — -.. . — . —.. — . — —- ·- — . —

Git.

Практическое руководство

$ 1s
puЫic

$

cd

html

puЫic

html

$ 1s

fuzzy . txt index . html poem.html techinfo . txt
$ git branch

* master
$ git log -1
бf168803fбflb987dffd5fff7753ldcadf7f4b68

commit
Author:

Федя Колобков

Date : Sun Sep 14 21 : 04:44 2020 — 0500
Add

а

hairy poem .

Из вывода команды

ls видно,

что у клона заполнен рабочий каталог, в него

помещены все файлы, которые находятся под управлением системы кон­

троля версиями. Клон Б обика

это репозитарий разработки, а не чистый

репозитарий . В этом репозитарии пользователь Бобик будет вести некото­
рую разработку.

Из вывода команды git log видно, что в репозитарии Бобика доступна самая
новая фиксация . Кроме того, репозитарий Бобика был клонирован из роди­

тельского каталога и у него есть удаленная с именем

origin.

Получить боль ­

ше информации об этой удаленной можно, выполнив следующую команду

внутри репозитария Бобика:

$ git remote show origin

* remote origin
URL: /tmp/Depo t /puЬl ic_html . git
Remote branch merged with ‘ git pull ‘ while on branch master
master
Tracked remote branch
master

В!t ······

······-········· —···—….. -·······-·· ……. ········· ···-···· … ····—···.

Глава

12. Удаленные

репозитарии

Рассмотрим полное содержимое конфигурационного файла после клониро ­
вания, обратите внимание , как представлена удаленная

$ cat

origin:

.git / config

[core]
repositoryformatversion

О

filemode = true
bare = false
logallrefupdates

true

[remote » origin » ]
url =

/ tmp / Depot / puЫic_html.git

fetch = +refs / heads / * :refs / remotes/origin / *
[branch «master»]
remote = origin
merge = refs / heads / master
В дополнение к удаленной

origin

в репозитарии Бобика есть несколько ве­

ток. Просмотреть список веток в своем репозитарии он может с помощью

команды

git branch

-а:

$ git branch

* master
o rigin / HEAD
origin/master
Ветка

master —

это главная ветка разработки Бобика. Это обычная локаль­

ная ветка разработки. Есть также локальная ветка отслеживания, ассоции­
рованная с соответствующей удаленной веткой отслеживания

master. В етка

origin/ master — это удаленная ветка отслеживания, отслеживающая фикса­
ции из ветки master репозитария origin. Ссылка origin/ HEAD указывает,
какая удаленная рассматривается как активная ветка. Звездочка рядом с
веткой

master говорит о том , что эта ветка является текущей .

Представим, что Бобик сделал фиксацию , которая изменяет поэму и затем
отправляет (команда

push)

эти изменения в базу. Сначала мы просмотрим

изменения, затем сделаем фиксацию:

•.———————————————————————————-IJII

it.

Практическое руководство

$ git diff

diff —git a /f uzzy.txt
index

0dб0lfa

Ь/fuzzy . txt

. . 608аЬ5Ь 100644

— a / fuzzy.txt
+++

Ь/fuzzy.txt

@@ -1,4 +1,4 @@
Fuzzy Wuzzy was

а

bear

Fuzzy Wuzzy had no hair
Fuzzy Wuzzy wasn’t very fuzzy,
-Was he?
+Wuzzy?
$ git commit fuzzy.txt

Created commit 3958f68 : Make the name pun complete!
1 files changed, 1 insertions(+), 1 deletions(-)
Чтобы завершить цикл разработки Бобика, нужно отправить его изменения
в базу, используя команду git

push:

$ git push

Counting objects : 5, done.
Compressing objects: 100% (3/3), done .
Writing objects : 100 % (3 /3) , 377 bytes , done .
Total 3 (delta 1), reused

О

(delta

О)

Unpacking objects : 100% (3 /3 ), done.
То

/ tmp /D epot /p uЫic_html . git
бf16880

.. 3958f68 master — > master

Получение обновлений репозитария
Давайте предположим, что Бобик ушел в отпуск, а тем временем вы внесли
свои изменения и отправили их в базу. Давайте разберемся, что нужно сде­
лать Бобику, чтобы получить последние изменения.
Ваша фиксация выглядит так:

&1-·………………………………………………………… —..—… -.. —.

Глава

$ cd

12.

Удаленные репозитарии

~/puЫic_html

$ git di ff

diff —git a / index . html

Ь/index.html

index 40b00ff . . 063ас92 100644
a / index.html
Ь/index.html

+++

@@ -1,5 +1,7 @@

Му

web site is alive!

+
+ Read

а

hairy< / a>

роет!

$ git commit -m «Add

Created commit

а

55с15с8:

hairy poem link. » index .

html
Add

а

Используя команду

роет

hairy

1 files changed, 2 insertions(+),

О

link.

deletions(-)

git push, поместите вашу фиксацию в репозитарий:

$ git push

Counting objects: 5, done.
Compressing objects: 100 % (3 / 3), done.
Unpacking objects : 100 % (3 / 3), done.
Writing objects: 100 % (3/3), 348 bytes , done.
Total 3 (delta 1) , reused
То

/ tmp / Depot / puЫic

О

О)

(delta

html

3958f68 . . 55с15с8 master — > master
Теперь, когда Бобик вернулся из отпуска, он хочет обновить свой клон ре ­
позитария. Основная команда для загрузки обновлений

— git pull:

$ git pull

remote: Counting o bjects: 5, d o ne.

‘.

remote : Compressing objects: 100 % (3 / 3), done.
remote : Total 3 (delta 1), reused

О

(delta

О)

—— …. — —- … .. -.. . — .. . — . .. — .. . — .. . — …. -.. -…… .. …. ………. ……. . . .

it.

Практическое руководство

Unpacking objects: 100 % (3 /3 ), done.
From

/ tmp / Depot / puЫic_html

3958 f68 . . 55c15c8 master — > orig in / master
Updating

3958fб8

..

55с15с8

Fast forward
index.html 2 ++
1 files changed, 2 insertions(+),
Полный синтаксис команды

git pull

О

deletions(-)

выглядит так:

git pull

репозитарий

ref-

spec.
Если репозитарий не задан в командной строке или как

Git URL, по умол­
не укажите refspec в команд­

чанию используется удаленная
ной строке, будет

origin. Если вы
использоваться refspec удаленной.

Если вы укажите ре ­

позитарий (непосредственно или с и с использованием удаленной), но не

укажите

refspec, Git получит ссылку HEAD удаленной .

Операция git pull состоит из двух шагов. Фактически — это команда git fetch,
за которой следует команда
шаг

— это merge,

git merge или git rebase.

По умолчанию, второй

но практически всегда это требуемое поведение.

Поскольку

pull всегда производит на втором шаге команду merge или step,
команды git push и git pull не считают противоположностями . Вместо них,
противоположными считаются команды git push и git fetch. Но push и fetch
являются ответственными за передачу данных между репозитариями, но в
противоположных направлениях .

Иногда вы можете захотеть выполнить

git fetch

и

git merge

как две отдель­

ные операции. Например, вы можете получить обновления в ваш репозита­

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

щью команд

git log, git diff или

даже

gitk),

помо ­

а затем выполнить слияние, как

будете готовы .
Даже если вы никогда не будете разделять операции загрузки обновлений и
обновления, вы должны знать, что происходит при их вызове. Давайте по­
смотрим на каждую из них в деталях.

Шаг fetch: получение обновлений

ED ———————————————————.————————.

Глава

На первом шаге (операция

fetch) Git

12.

Удаленные репозитарии

определяет местоположение удален­

ного репозитария. Если имя удаленного репозитария не задано в команд­

ной строке (как

URL

или как имя удаленной), подразумевается имя уда­

ленной по умолчанию , то есть

origin. Информация об этой удаленной есть в

конфигурационном файле:

[remote » o rigin»J
url =

/ tmp / Depot / puЫic_html.git

fetch = +refs / heads / *:refs / remotes / origin / *

Git теперь знает, что нужно использовать URL /tmp/D epot/puЬlic_html в
качестве исходного репозитария. Поскольку командная строка не содержит

refspec, Git будет использовать вместо нее строку fetch из записи remote. В
данном случае будут получены все ветки refs/ heads/ * из удаленной .
Далее

Git

выполняет протокол согласования с исходным репозитарием,

чтобы определить, какие новые фиксации находятся в удаленном репозита­

рии и отсутствуют в вашем репозитарии ( при этом используется
строка

fetch

refspec или

из файла конфигурации).

Примечание. Если вам не нужно получать все ветки (как в нашем слу­

чае

refsjheads/*), вы

не обязаны использовать звездочку. Вместо это­

го вы можете указать определенную ветку (или две):

[remo te «newde v «]
url =

/ tmp / Depot / puЫic_html.git

fetch

+refs / heads / dev:refs / remotes / origin / dev

fetch =

+refs / heads / staЫe:refs / rem o te s/o rigin /

staЫe

Вывод

pull,

снабженный префиксом

remote отражает информацию

о согла­

совании, сжатии и протоколе передачи. Вы узнаете, каким способом фикса­
ции придут в ваш репозитарий:

remo te: Cou n t i n g obj e c ts: 5 , d one.
remo te: Compressing obje c ts: 10 0% (3 / 3), d o ne .

·- — —— — — — — — ———- —————— — -· — —··—··-·· · ·········-······· · ···· -ED

Git.

Практическое руководство

remote: Total 3 (delta 1), reused

Git помещает новые фиксации

О

О)

(delta

в ваш репозитарий в соответствующую вет­

ку отслеживания и затем сообщает вам, где искать новые фиксации:

From

/ tmp/Depot / puЫic_html

3958f68 .. 55cl5c8 master -> origin/mas ter
Эти строки сообщают, что

Git

соединяется с удаленным репозитарием

/
master и помещает ее содержи­
мое обратно в ваш репозитарий, в вашу ветку origin/ master. Этот процесс
— это сердце отслеживания. На этом шаг fetch заканчивается.

tmp/Depot/puЬlic_html, «берет>,} его ветку

Шаг

merge (rebase):

слияние

На втором шаге операции

pull, Git выполняет слияние — операцию merge
(по умолчанию) или rebase. В этом примере Git объединяет содержимое
удаленной ветки отслеживания origin/ master в вашу локальную ветку от­
слеживания master, используя специальный тип слияния — перемотку (fastforward).
Но как

Git узнал, что нужно объединить именно эти две определенные вет­

ки? Ответ приходит из конфигурационного файла:

[branch «master»]
remote = origin
merge = refs /heads/master
Этот раздел содержит параметр для ветки

master.

Когда ветка

master явля­

origin используется по умолчанию для получения
fetch или pull). Во время шага merge команды git
pull используется refs/ heads/ master удаленной как ветка по умолчанию для
слияния с веткой master.
ется текущей, удаленная

обновлений (командами

Значение поля

master)

merge

в разделе

branch

файла конфигурации

обрабатывается как удаленная часть

refspec

(refs/ heads/

и она должна соответ ­

ствовать одной из ссылок источника, выбранной во время работы команды

E!J- ————————————————————··—·—-· ———-·

Глава

git pull.

12. Удаленные

репозитарии

Это немного замысловато, но думайте о ней как о подсказке, пере­

даваемой от шага

fetch шагу rnerge.

Поскольку значение конфигурации

pull, оно

не распространяется на

rnerge применяется только во время git
команду git rnerge, введенную вручную. В

этом случае вам нужно указать имя ветки явно:

#

Или полное имя

refs / remotes / origin / master

$ qit merqe oriqin/master

Updating 3958f68 ..

55с15с8

Fast forward
index . html

1

2 ++

1 files changed , 2 insertions(+),

О

deletions(-)

Примечание . Есть небольшие семантические различия между пове­
дением слияния, когда задано несколько
или когда они найдены в записи

remote.

refspec

в командной строке

В первом случае выполня­

ет слияние осьминога, rде все ветки объединяются одновременно в
п-стороннюю операцию, что не происходит во втором случае. Внима­
тельно прочитайте страницу руководства команды

Если вы выбрали операцию

rebase

вместо

rnerge, Git

git pull!

выполнит портирова­

ние изменений в локальную ветку отслеживания только что полученной

HEAD соответствующей удаленной ветки отслеживания. Данная операция
10.12 и 10.13 в главе 10.

отображена на рис.
Команда

git pull

—геЬаsе заставит

Git

выполнить перебазирование (вместо

слияния) вашей локальной ветки отслеживания в удаленную ветку отсле­

живания. Чтобы выполнить обычную операцию

rebase для ветки, установи­
те переменную конфигурации Ьгаnсh.имя _ ветки.геЬаsе в true:
[branch «mydev «]
remote = origin
merge = refs / heads / master
rebase = true

Нужно выполнять слияние или перебазирование?

.-….. …. …. ……………. .. …. .. …….. .. …. ……….. ….. ………….. .

Git.

Практическое руководство

Какую операцию

манды

( слияние

или перебазирование) выполнить во время ко­

pull? Короткий ответ:

korg /nex t
[new branch] pu — > korg/pu
[new branch] t od o — > korg /tod o

$ qit branch

имя

I qrep

вет ки и

переключаемся

на

нее

split-Ьlob

remotes/origin/jc/split -Ы ob

$ qit branch

* master
$ qit checkout jc/split-Ыob

Branch
Ыob

jc/split-Ыob

set up to track remote branch jc / split-

fr om o rigin .

Switched to

а

new branch

‘jc /sp lit-Ьl ob ‘

$ qit branch

* j с/ split -Ы ob
master
Заметьте, что мы использовали полное имя ветки — js/split-Ыob, а не просто
split- Ыob. В этом случае, когда имя ветки неоднозначно, вы можете устано­
вить и настроить ветку непосредственно:

&!8 …………. -…………………………………………………………..

Глава

$ git branch — а

Удаленные репозитарии

12.

I egrep ‘maint$’

remotes / korg/maint
remotes / origin / maint
$ git checkout maint

error : pathspec ‘maint’ did no t match any file(s)
#

Просто

выберите

одну

из

known to git.

maint-вeтoк

$ git checkout — — track korg/maint

Branch maint set up t o track remote branch maint from korg.
Switched to

а

new branch ‘maint ‘

Вероятно, что две ветки представляют ту же фиксацию, как найдено в двух

разных репозитариях и вы можете просто выбрать одну из них, на которой
можно базировать вашу локальную ветку.
Если по некоторым причинам вы хотите использовать другое имя для ва ­

шей локальной ветки, используйте опцию -Ь :

$ git checkout — Ь mypu — -track korg/pu

Branch mypu set up to track remote branch pu from korg .
Switched to

Git

а

new branch ‘mypu’

автоматически добавляет запись

branch

в файл

.git/ config,

чтобы ука­

зать, что удаленная ветка должна быть объединена с вашей новой локаль­
ной ветки. Собранные изменения из предыдущего ряда команд приводят к
следующему файлу:

$ cat . git/config

[core]
repo sitoryformatversion

О

filemode = true
bare = false
logallrefupdates

true

[remote « o rigin»]
fetch = +refs / heads / *:refs / remo tes / origin / *

url = git: // github.c om/ gitster / git.git

.. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . . . .

..

it.

Практическое руководство

[branch «master » ]
remote = o rigin
merge = refs /he ads / master
[remote «korg»]
url =

g it : //git . kernel. org/ puЬ/scm /g it / git . git

fetch = +refs / heads /* : refs / remotes/korg/*
[branch

«jc /s plit-Ыob»]

remote = origin
merge =

refs /heads/ jc / split-Ыob

[branch «maint»]
remote = korg
merge = refs/heads/maint
[branch «mypu»]
remote = korg
merge = refs/heads/pu
Как обычно, вы можете использовать

git config или текстовый редактор для

изменения вашего конфигурационного файла.

Примечание. Если вы заблудитесь в своих ветках, используйте коман­
ду

git remote show удаленная,

чтобы отсортировать ваши удаленные и

ветки.

В этой точке должно быть точно понятно, что по умолчанию в клоне будет
локальная ветка отслеживания

master для удаленной ветки origin/ master.

Чтобы укрепить идею, что создание фиксаций непосредственно на удален­
ной ветки не является хорошей мыслью, переключение удаленной ветки с
использованием ранних версий

Git (до версии 1.6.6) приводит к отсоедине­
нию HEAD. Как было упомянуто в главе 7, отсоединенная HEAD — по сути,
является анонимной веткой . Создание фиксаций на отсоединенной HEAD
возможно, но вы не должны потом обновлять вашу HEAD удаленной ветки
никакими локальными фиксациями, чтобы не перенести проблемы позже
при получении новых обновлений из той удаленной. Если вам нужно со­

хранить любые фиксации на отсоединенной

git checkout -Ь my_ branch для создания

HEAD,

используйте команду

новой, локальной ветки, на которой

вы продолжите свою разработку. А вообще это не очень хороший подход .

&1· …………………………………………………………………….. .

Глава

12.

Удаленные репозитарии

Если вы не хотите переключаться на локальную ветку после ее создания,

вы можете использовать команду git branch

—track локальная-ветка удален­

ная-ветка для создания локальной ветки и записи ассоциации локальная­

удаленная ветка в файл

.git/ config, например:

$ git branch —track dev origin/dev

Branch dev set up to track remote branch dev fr om origin .
Если у вас уже есть ветка и вы решили связать

ero

с удаленной веткой уда­

ленного репозитария, вы можете установить это отношение, используя оп­

цией

—set-upstream. Обычно

это делается после добавления новой удален­

ной :

$ git remote add upstreamrepo git: //gi t.example . org/

upstreamrepo . git
#

Ветка

#

Оставьте

mydev
ее

уже

в

с ущес твует .

покое,

но

свяжите

с

upstreamrepo/dev.

$ git branch —set-upstream mydev upstreamrepo/dev

Впереди и сзади
После установки пары локальная -удаленная ветка, между этими ветками

могут быть произведены относительные сравнения. В дополнение к обыч­
ному

diff, log и другим контентно-зависимым сравнениям , Git предоставля­

ет бы~трую сводку числа фиксаций на каждой из веток и состояний веток,
способных определить, где находится ветка

— «позади~

или «сзади~ относи­

тельно другой ветки.

Если ваша локальная разработка представляет новые фиксации на локаль­

ной ветки, считается, что она «впереди» соответствующей удаленной ветки.
Аналогично, если вы получили новые фиксации в удаленную ветку и они
отсутствуют в вашей локальной ветке,

Git

рассматривает вашу локальную

ветку как находящуюся за («сзади») соответствующей удаленной веткой.
Команда

git status обычно показывает этот статус:

$ git fetch

.—….. … …. …….. … .. …. … .. …………………………. …….. ……. .

it.

Практическое руководство

remote: Counting objects: 9, done.
remote: Compressing objects: 100% (6/6) , done.
remote: Total 6 (delta 4), reused

О

(delta 0)

Unpacking objects: 100% (6 /6 ), done .
From example .com :SomeRepo
Ыа68а8

.. Ь722324 ver2 -> origin/ver2

$ git status

# On branch ver2

# Your branch is behind ‘origin /ver2 ‘
fast-forwarded.

Ьу

2 commits, and can

Чтобы увидеть, какие фиксации у вас есть в ветке
ветке

rnaster,

Ье

но отсутствуют в

origin/rnaster, выполните команду:

$ git log origin/master .. master

Yes, it is

possiЬle

to

Ье

both ahead and behind

simultaneously!
# Make one local commit on top of previous example
$ git commit -m «Something» main.c

$ git status

# On branch ver2

# Your branch and ‘origin /ver2 ‘ have diverged,
# and have 1 and 2 different commit(s) each, respectively .
И в этом случае вы, возможно, пожелаете использовать симметрическую
разницу для просмотра изменений:

$ git log origin/master … master

. .. . . . . . . . . . . . . . . .. .. . . . . . . . . . . . . . . .. .. . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .. . . . .. . . . . .

Глава

12.6. Добавление

12.

Удаленные репозитарии

и

удаление удаленных веток
Любая новая разработка, для которой вы создаете новую ветку в вашем ло­
кальном клоне, не видима в родительском репозитарии до тех пор, пока вы

явно не сообщите об этом. Точно так же удаление ветки в вашем репозита­
рии остается локальным изменением и эта ветка не удаляется из родитель­
ского репозитария , пока вы явно не запросите это.

В главе

7 вы

узнали, как добавить новые ветки и удалить существующие с

помощью команды

git branch.

Но команда

git branch

работает только с ло­

кальным репозитарием.

Чтобы произвести аналогичные операции над ветками удаленного репо­
зитария, вам нужно указать различные формы

Вспомним синтаксис

refspec

в команде

refspec,

в котором указыва­

git push.

refspec:

[+]источник:назначение

Отправка ваших изменений

(push)

использует

ется только ссылка источник ( ссылка назначения не нужна), создает новую
ветку в удаленном репозитарии:

$ cd …. /puЫic_html
$ git checkout -Ь foo

Switched to

а

new branch «foo»

$ git push origin foo

Total
То

О

(delta

О) ,

reused

О

(delta 0 )

/ tmp / Depot / puЫic_html

* [new branch] f oo — > foo

Отправка

(push)

данных, которая содержит только ссылку источник, яв­

ляется просто сокращением для того, чтобы использовать то же имя и для

‘ ····· ··· ·········· ·· ···· ···········································-······ ······—

Git.

Практическое руководство

источника и для назначения. Отправка, содержащая и источник, и назна­
чение, имена которых отличаются, может использоваться для создания но­

вого назначения с именем ветка или расширения существующей целевой
ветки контентом из локальной ветки.

Команда

mystuff в
удаленный репозитарий и создает или расширяет ветку с именем dev. Из-за
чрезвычайной гибкости Git, у всех следующих команд будет одинаковый
git push origin mystuff:dev

отправляет локальную ветку

эффект:

$

git push upstream new de v

$ git push upstream new dev:new dev
$ git push upstream new_dev:refs / heads / new_dev

Обычно

это ссылка на надлежащий удаленный репозитарий и

upstream —

обычно принимает значение
Отправка

(push),

origin.

использующая только ссылку назначение (то есть когда

ссылка источник не задана) приведет к удалению ссылки назначение из

удаленного репозитария. Чтобы указать только назначение, но не указать
источник, вы должны задать перед именем назначения двоеточие:

$ git push or1g1n : foo
То

/ tmp / Depot / puЫic_html

[deleted] foo

Если форма

: ветка

вам не :нравится, вы можете использовать эквивалент­

ную форму :

$

git push origin —delete f o o

А что насчет переименования удаленной ветки? К сожалению, здесь нет
простого решения. Проще всего создать новую ветку в удаленном репозита­
рйи с новым именем, а затем удалить старую:

#

Создаем

новое

имя

(new)

на

существ ующей

фик с ации

(old)

$ git branch new origin/old

. ………………………………………………………………………

,

Глава

12. Удаленные

репозитарии

$ git push origin new

#

Удаляем имя

o ld

$ git push origin :old
Но это

— просто

и очевидно. А что насчет распределенного использования?

Вы узнаете, у кого есть клон удаленного репозитария, который только что

изменен? Если да, они должны выполнить операции

fetch

и

remote prune

для обновления своих репозитариев. Если нет, они столкнутся с пробле­
мами. К сожалению, нет никакого реального способа для распределенного
переименования ветки.

Могу только порекомендовать быть предельно осторожными, как и с пере­
записью вашей истории .

12. 7.

Чистые

(bare)

репозитарии и команда

git

push
В следствие одноранговой семантики репозитариев

Git у всех репозитариев
( и получить изме­

одинаковая важность. Вы можете отправить изменения

нения, соответственно) в чистый репозитарий точно так же, как и в обыч­
ный репозитарий , поскольку между ними нет никакого фундаментального
различия.

Такой симметричный дизайн критически важен для

Git,

но приводит к не­

которому неожиданному поведению, если вы пытаетесь считать чистые ре­

позитарии и репозитарии разработки равными.

Вспомните, что команда

git push

не проверяет файлы в получающем репо­

зитарии. Она просто передает объекты из исходного репозитария в целевой

репозитария и затем обновляет соответствующие ссылки на целевом репо­
зитарии.

В чистом репозитарии это поведение

все, что можно ожидать, поскольку

здесь нет никакого рабочего каталога, который мог бы быть обновлен за­

груженными файлами . Это хорошо. Однако в репозитарии разработки , ко —

·———————————————————————————- —

Git.

Практическое руководство

торый является получателем операции

push, такое поведение push может

вызвать беспорядок.
Операция

HEAD.

push может обновить состояние репозитария, включая фиксацию

Т.е. даже при том, что разработчик на удаленной стороне ничего не

сделал, ссылки ветки и

HEAD

могли измениться и выйти из синхрониза­

ции с загруженными файлами и индексом .

Разработчик, активно работающий в репозитарии, который происходит
асинхронная операция

push,

не видит

push.

Но последующая фиксация

этого разработчика произойдет на неожиданной
историю. Принудительная операция

push

HEAD, создавая странную

потеряет добавленные другим

разработчиком изменения . Разработчик в том репозитарии может оказать­
ся неспособным согласовать его историю с удаленным репозитарием или
загруженным клоном, поскольку больше нет перемотки вперед, которая
должна быть. И он не узнает почему: репозитарий без всякого предупреж­
дения изменил ее. Кошки и собаки будут жить вместе. Это плохо.
В результате вы будете стараться отправить свои изменения в чистый репо­

зитарий. Это не обязательное правило, но хороший совет среднестатисти­
ческому разработчику и является отличной практикой. Есть несколько сце­

нариев , в которых нужно отправить изменения в репозитария разработки,
но вы должны точно отдавать себе отчет в том, что вы делаете. Если нужно
таки отправить изменения в репозитарий разработки, вы можете использо­
вать один из двух основных подходов .

В первом сценарии вы действительно хотите иметь рабочий каталог с ак­
тивной веткой в целевом репозитарии. Например, вы знаете, что ни один

другой разработчик не ведет в нем активную разработку и нет никого дру­
гого, кто может вслепую добавить изменения в репозитарий .
В этом случае вам нужно включить обработчик в целевом репозитарии, вы­
полняющий проверку некоторой ветки. Чтобы проверить, что целевой репо­

зитарий находится в нормальном состоянии, обработчик должен убедиться,
что рабочий каталог репозитария разработки н е содержит измененных фай­
лов и что его индекс не содержит неподготовленных файлов. Когда эти два

условия не соблюдены, вы рискуете потерять те изменения, поскольку они
будут перезаписаны.

Есть и другой сценарий, при котором

push в репозитарий разработки целе ­

сообразен. По соглашению каждый разработчик, который отправляет изме-

— -… -. .. — … — . -·- … — . — .. — -… — . — …………….. — …. — …… — … — …

Глава

12.

Удаленные реnозитарии

нения, должен отправить их в неактивную .ветку, которая считаются просто

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

•.——————————————————————————.—&1

Издательство «Наука и Техника» рекомендует:

Пономарев С. Н .

Angular
на примерах
Создаем wеЬ-приложения
с нуля

> hepawA с•Ат > Осиоанwе •.nементw
ка

Angul•r

Angu18r

>Яаwк
.ilH1, [Г
Тype8ortpt ~

Пономарев С. Н.

Angular на примерах. Создаем wеЬ-прwюжения с нуля. Техника» -288 с., ил.

СПб.: «Наука и

Angular — это передовой фреймворк по разработке одностраничных веб-приложений (англ.
single page application, SPA). Одностраничность приложения позволяет изменять содержимое
в окне браузера не путем открытия новых страниц с новым содержимым (как это реализуется
на обычных сайтах (не

SPA)), а путем обновления/замены содержимого одной и той же, перво­

начальной страницы. Короче говоря , одностраничное приложение —

это веб-приложение или

веб-сайт, использующий единственный НТМL-документ как оболочку для всех веб-страниц
и организующий взаимодействие с пользователем через динамически подгружаемые

HTML,

CSS, JavaScript.
С помощью практических примеров этой книги Вы сможете быстро освоить базовые навыки
работы с Angular. По ходу прочтения вы создадите несколько готовых веб-приложений разной
степени сложности.

Издательство «Наука и Техника рекомендует:
II

Дьяков М. Ю.

Landing. Создание и продвижение продающих веб-страниц своими руками
— СПб.: «Наука и Техника» -256 с., ил.
Эта книга о том, что такое посадочная страница

Landing Page

и как знание правил

создания посадочных страниц помогает продвигать товары и услуги на онлайн-рын­

ке. В книге разобран простой пример создания посадочной страницы с нуля: объ­

яснены основы до непосредственного внесения информации на страницу, алгоритм
внесения информации на страницу и последующее продвижение, совершенствова­
ние и улучшение механизмов продажи через лендинг-страницы .

В книге содержатся все инструкции, необходимые для создания Вами минимально
жизнеспособного лендинга/посадочной страницы, с настроенными процессами, как
привлечения клиентов, удержания клиентов на лендинге/посадочной странице, так
и обеспечения улучшения всех настроенных процессов

Издательство «Наука и Техника»

КНИГИ ПО КОМПЬЮТЕРНЫМ ТЕХНОЛОГИЯМ,
МЕДИЦИНЕ, РАДИОЭЛЕКТРОНИКЕ

Уважаемые читатели!
Книги издательства «Наука и Техника» вы можете:
► заказать в нашем интернет-магазине БЕЗ ПРЕДОПЛАТЫ по ОПТОВЫМ ценам

www.nit.com.ru

• более 3000 пунктов выдачи на территории РФ, доставка 3-5 дней
• более 300 пунктов выдачи в Санкт-Петербурге и Москве, доставка — на следующий день
Справки и заказ:

www.nit.com.ru

• на сайте
• потел .(812)412-70-26
• по эл . почте nitmail@nit.com.ru

► приобрести в магазине издательства по адресу:
Санкт-Петербург, пр. Обуховской обороны, д . 107
М. Елизаровская,

200 м за ДК им . Крупской
10.00 до 18.30
Справки и заказ: тел . (812) 412-70-26
Ежедневно с

► приобрести в Москве:
« Новый книжный » Сеть магазинов

тел .

ТД « БИБЛИО- ГЛОБУС»

ул . Мясницкая, д.

(495) 937-85-81 , (499) 177-22-11
6/3, стр . 1, ст. М «Лубянка »
тел . (495) 781-19-00, 624-46-80

Московский Дом Книги ,

ул . Новый Арбат,

«ДК на Новом Арбате»

тел .

8, ст.
(495) 789-35-91

М «Арбатская »,

Московский Дом Книги ,

Ленинский пр ., д.40, ст. М «Ленинский пр .»,

«Дом технической книги»

тел.

Московский Дом Книги,

Комсомольский пр., д.

«Дом медицинской книги»

тел .

Дом книги « Молодая гвардия »

ул. Б . Полянка, д.
тел .

(499) 137-60-19
25, ст.

М «Фрунзенская »,

(499) 245-39-27
28, стр. 1, ст. М « Полянка »
(499) 238-50-01

► приобрести в Санкт-Петербурге:
Санкт- Петербургский Дом Книги
Буквоед. Сеть магазинов

Невский пр . 28, тел . (812) 448-23-57
тел. (812) 601-0-601

► приобрести в регионах России:
г. Воронеж, «Амиталь» Сеть магазинов

г. Екатеринбург, «Дом книги » Сеть магазинов
г. Нижний Новгород, «Дом книги » Сеть магазинов
г. Владивосток, — «Дом книги » Сеть магазинов
г. Иркутск, « Продалить» Сеть магазинов
г. Омск, «Техническая книга» ул . Пушкина, д . 101

тел . (473) 224-24-90
тел. (343) 289-40-45
тел . (831) 246-22-92
тел. (423) 263-10-54
тел . (395) 298-88-82
тел . (381) 230-13-64

Мы рады сотрудничеству с Вами!

Фишерман Л . В .

Git
Практическое руководство
Управление и контроль версий в разработке
программного обеспечения

Группа подготовки издания:
Зав . редакцией компьютерной литературы : М. В . Финков

Редактор : Е. В. Финков
Корректор: А . В. Громова

ООО «Наука и Техника»
Лицензия №000350 от

192029, г.

23

декабря

1999 года .

Санкт-Петербург, пр . Обуховской обороны , д.

Подписано в печать

23.10.2020. Формат

70х100

Бумага офсетная. Печать офсетная. Объем
Тираж

19

1350. Заказ 12311 .

Отпечатано ООО « Принт-М »

142300,

Московская область,

г. Чехов , ул . Полиграфистов, дом

1

107.
1/1 6.

п. л .

Книга в формате pdf! Изображения и текст могут не отображаться!

Настройки текста:


ПРАКТИЧЕСКОЕ

PYKOBODCTBO

Управление и контроль версий
в разработке программного

обеспечения

ФишЕРмдн Л . В.

Практическое руководство
Управление и контроль версий в разработке
программного обеспечения

«Наука и Техника»

Санкт-Петербург

Telegram:

https://t.me/it_boooks

УДКОО4.42

ББКЗ2.973
Фишерман Л. В.

G1т. ПРАКТИЧЕСКОЕ РУКОВОДСТВО. УПРАВЛЕНИЕ И КОНТРОЛЬ ВЕРСИЙ В
РАЗРАБОТКЕ ПРОГРАММНОГО ОБЕСПЕЧЕНИЯ —

— 304 с.,

СПБ.: НАУКА и ТЕХНИКА,

2021.

ил.

ISBN 978-5-94387-547-2

Git

в настоящее время нужен практически всем программистам, которые

занимаются разработкой программного обеспечения.

Git —

это система

управления версиями, с помощью которой вы сможете вести и контроли­

ровать разработку нескольких версий одного приложения, осуществлять
совместную разработку одного приложения несколькими разработчиками

(учитывать изменения, которые делаются на том или ином шаге разработки
тем или иным разработчиком). С помощью системы

Git у

вас будет полная

иерархия всех версий программного кода разрабатываемого приложения.

Данная книга представляет собой подробное практическое руководство по

Git, в

котором описывается

Git и

приводится разбор конкретных ситуаций

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

кой предварительной подготовки не требуется: по ходу изложения даются
все необходимые определения и пояснения. Лучший выбор, чтобы освоить

Git и максимально быстро начать его применять на практике.

Все права защищены . Ни какая часть данной книги не может быть воспроизведена в какой бы то ни было форме без пись­
менного разрешения владельцев авторских прав .

Издательство не несет ответственности за доступность материалов, ссылки на которые вы можете найти в этой книге . На
момент подготовки книги к изданию все ссылки на интернет-ресурсы были действующими .

15BN 978-5-94387-547-2
Контактные телефоны издательства :

(812)4127026
Оф ициальный сайт:

www.nit.com.ru

© Фишерман Л. В.

9 78 — 5- 94387- 547- 2

©

Наука и Техника (оригинал-макет)

Содержание
ГЛАВА

1.

ВВЕДЕНИЕ В

GIT ………………………………… 9

1. 1.

НЕОБХОДИМОСТЬ РЕЗЕРВНОГО КОПИРОВАНИЯ

1.2.

ЭТАПЫ РАЗВИТИЯ

1.3.

ЧТО В ИМЕНИ ТВОЕМ?

ГЛАВА
2.1.

2.

…………………….. 1 О

…………………………………………………………. 11
…………………………………………………….. 12

УСТАНОВКА

GIT ……………………………….. 13

ИСПОЛЬЗОВАНИЕ ДВОИЧНЫХ ДИСТРИБУТИВОВ

LINUX …. …………. 14

DeЬian/Ubuntu …….. ……. .. … ……………… …… …….. … …. .. .. ……. .. .. .. 15

Другие дистрибутивы ….. …… …….. ……. .. .. .. …. ……… …. ……… .. ….. 16

2.2.

ПОЛУЧЕНИЕ ИСХОДНОГО КОДА

2.3.

СБОРКА И УСТАНОВКА

2.4.

УСТАНОВКА

GIT

В

………………………….. .. ………………………. 18

WINDOWS ……………………………………………… 20

Установка пакета
Установка

ГЛАВА

3.

…. .. . …………………………………… 17

Cygwin Git …… … .. … ……. .. .. ….. … …… …… …. …… 21

msysGit ……………… …… ….. .. ….. … …. …… ….. .. ……. ……. 22

НАЧАЛО ИСПОЛЬЗОВАНИЯ

3. 1 .

КОМАНДНАЯ СТРОКА

3.2.

БЫСТРОЕ ВВЕДЕНИЕ В

…………………. 25

GIT …………………………………………………. 26
GIT … …………………………………………….. 29

Создание начального репозитария

.. …. ………. … …. …. …… …. … …. 29

Добавление файлов в ваш репозитарий ………………………………. 30

Неясные сообщения об ошибках ……………. … …….. … …….. … ……. 32
Настройка автора коммита (фиксации)

.. … …….. .. … .. …. … ….. …. .. 32

Вносим другой коммит (фиксацию) … … …. …. .. ….. …. .. … … … … …. .33
Просмотр ваших фиксаций

.. …. ………. .. .. ……. .. …….. … ……….. …. .33

Просмотр разницы между коммитами (фиксациями)

…. … … … …. 35

Удаление и переименование файлов в вашем репозитарии

Копирование вашего репозитария

….. .. 36

…… …… …. .. .. …. .. ……….. ….. … 37

3.3. ФАЙЛЫ КОНФИГУРАЦИИ …………… .. ………………………………….. 38
Настройка псевдонимов
Резюме

….. … …. .. ………… … …… ………. ….. …. ….. .40

….

……. …. …………. …….. .. ……. …. …. ……….. … … .. ……… … ….. .41

… .. . .. . . . . . . . . . . . . . . . .. . —.. —. — —…… —. -……… -… -…. -… -…. -.. —

Git. Практическое руководство

ГЛАВА
4. 1.

4.

БАЗОВЫЕ ПОНЯТИЯ

БАЗОВЫЕ ПОНЯТИЯ

………………………….. ………………… . ……… . . 43

Репозитарии

…….. .. ….. .. ……. … …. … …….. …… .. … .. .. ….. .. .. … … … .. .44

Типы объектов
Индекс

GIT …………………….. 42

Git .. … .. ……… …… ….. .. …….. ……. …….. ……….. … .. …44

……… …….. ….. ………… …… ……. .. …. .. … …. ….. ….. ……… … … 46

Глобально уникальные идентифи каторы

Git отслеживает

контент …. ………. .. .. … …… ….. ……………. ………. … 47

Путь по сравнению с содержанием
Расk-файлы

4.2.

………


Git. Практическое руководство. Управление и контроль версий в разработке программного обеспечения

Название: Git. Практическое руководство. Управление и контроль версий в разработке программного обеспечения
Автор: Фишерман Леонид
Издательство: Наука и техника
Год: 2021
Формат: pdf
Страниц: 306
Размер: 68,5 Мб
Язык: русский

Git в настоящее время нужен практически всем программистам, которые занимаются разработкой программного обеспечения. Git — это система управления версиями, с помощью которой вы сможете вести и контролировать разработку нескольких версий одного приложения, осуществлять совместную разработку одного приложения несколькими разработчиками.

Git. Практическое руководство

Практическое руководство.

Фишерман Л. «Git. Управление и контроль версий в разработке программного обеспечения» НиТ, 2021 год, 304 стр., ISBN 978-5-94387-547-2; (PDF-DJVU)

Описание Содержание Links

Описание книги.

Данная книга представляет собой подробное практическое руководство по Git, в котором описывается Git и приводится разбор конкретных ситуаций и применений, например, как изменения из одной ветки разработки включить в другую ветку, но не все. Изложение начинается с самых азов, никакой предварительной подготовки не требуется: по ходу изложения даются все необходимые определения и пояснения. Лучший выбор, чтобы освоить Git и максимально быстро начать его применять на практике.

Оглавление.

Глава 1. Введение в GIT
Глава 2. Установка GIT
Глава 3. Начало использования
Глава 4. Базовые понятия GIT
Глава 5. Управление файлами. Индекс
Глава 6. Коммиты (Фиксации)
Глава 7. Ветки в GIT
Глава 8. Различия в GIT
Глава 9. Слияния
Глава 10. Изменение коммитов (Фиксаций)
Глава 11. Stash И Reflog
Глава 12. Удаленные репозитории

Git для новичков

PDF (RU)       DJVU (RU)

Похожая литература

576

https://www.htbook.ru/kompjutery_i_seti/programmirovanie/git-prakticheskoe-rukovodstvohttps://www.htbook.ru/wp-content/uploads/2021/12/git-prakticheskoe-rukovodstvo-e1638866865610.jpghttps://www.htbook.ru/wp-content/uploads/2021/12/git-prakticheskoe-rukovodstvo-e1638866865610-130×200.jpg2021-12-07T12:54:17+04:00Программирование и БДПрограммирование,руководствоПрактическое руководство.
Фишерман Л. ‘Git. Управление и контроль версий в разработке программного обеспечения’ НиТ, 2021 год, 304 стр., ISBN 978-5-94387-547-2; (PDF-DJVU)
Библиотека технической тематики. Техническая литература

Понравилась статья? Поделить с друзьями:
  • Глюкометр акку чек актив инструкция по применению выдает ошибку
  • Трамадол инструкция по применению уколы внутривенно
  • Дкс 101 руководство по эксплуатации
  • Раствор регидрона инструкция по применению для детей
  • Руководства прокуратуры татарстана