lab02: система контроля версий Git

main
Дмитрий Козлюк 2 лет назад
Родитель e24ed82de2
Сommit 39a7d57696

@ -16,7 +16,7 @@
## Лабораторные работы
1. [Основы языка C++](labs/lab01)
2. Система контроля версий Git
2. [Система контроля версий Git](labs/lab02)
3. Структурирование программ
4. Использование библиотек

@ -0,0 +1,830 @@
# Система контроля версий Git
# Цель работы
1. Знать понятия и компоненты систем контроля версий (СКВ),
порядок и приемы работы с ними.
2. Уметь участвовать в командной разработке, используя конкретную СКВ — Git,
а также типовой web-интерфейс Gitea.
# Выполнение работы и составление отчета
Необходимо выполнить все действия без пропусков.
Читайте пункт задания до конца перед тем, как выполнять его.
Для удобства по тексту отмечены пункты,
способ выполнения которых нужно придумать **самостоятельно.**
Нужно читать и осмысливать текст, который печатается в ответ на команды.
Если допущена ошибка, нужно повторить команду правильно.
Отчет должен содержать все введенные команды, ответы системы, пояснения,
что было сделано между пунктами (например, отредактирован файл), а также то,
что требуется добавить в отчет по тексту задания.
Весь текст, который был в терминале, в отчете должен быть как текст,
а не как скриншоты терминала. Скриншоты `gitk` и web UI не нужны.
Отчет нужно закоммитить в репозитарий, который создается в ходе ЛР,
как текстовый файл `README.txt` (простой текст)
или как `README.md` в формате Markdown.
Это лучше сделать одним последним коммитом после выполнения работы.
## Вход в терминал и создание структуры каталогов
Большая часть работы будет выполняться в терминале (командной строке).
Для Windows вместе с Git поставляется программа Git Bash: эмулятор терминала
Linux. Ее можно запустить из контекстного меню любого каталога пунктом
*Git Bash Here* или из меню «Пуск».
**Самостоятельно.**
Создайте на рабочем столе каталог `lab02` для данной ЛР
и запустите в нем Git Bash.
**Внимание.**
Даже если работа выполняется в компьютерном классе,
создавайте каталог на рабочем столе, а не на сетевом диске,
так как git не сможет нормально с ним работать.
В терминале откроется *приглашение (prompt)* примерно такого вида:
```
user@mpei-dc-win7 MINGW32 /c/Users/user/Desktop/lab02
$
```
Здесь важен рабочий каталог `/c/Users/user/Desktop/lab02`
и символ `$` — начало ввода команд.
Просмотреть файлы в рабочем каталоге можно командой `ls`.
В каталоге `lab02` пусто, поэтому `ls` ничего не выведет.
В ходе работы будем имитировать проект с двумя участниками: Алисой и Бобом.
Компьютеры Алисы и Боба имитируют папки `lab02/alice` и `lab02/bob`:
``` sh
mkdir alice
mkdir bob
```
Переход между каталогами делается командой `cd`.
Перейдем «на компьютер Алисы» — в каталог `alice`:
``` sh
cd alice
```
**Самостоятельно.**
Создайте здесь каталог `project` и перейдите в него.
Перейти на уровень выше можно командой `cd ..`
(две точки в конце, после `cd` пробел).
**Самостоятельно.**
Перейдите из каталога проекта вверх, затем вернитесь в каталог `project`.
Все команды нужно заносить в отчет.
Текст в Git Bash копируется при выделении, ничего нажимать не нужно.
Скопированное можно вставить в любую другую программу *Ctrl+V,* как обычно.
Для вставки в сам Git Bash из буфера обмена
нажмите правую кнопку мыши или *Ctrl+Insert.*
## Инициализация репозитария и настройка Git
Инициализируем репозитарий в текущем каталоге (`project`):
``` sh
git init
```
К приглашению командной строки добавилось `(master)`: имя текущий ветви Git.
Ветвь `master` используется по умолчанию.
Git хранит свои данные в каталоге `.git` в той папке, где сделано `git init`.
Ее можно увидеть командой `ls -A`.
Заходить в `.git` и что-либо делать там не нужно.
Если удалить этот каталог, репозитарий будет безвозвратно утерян.
Git хранит три набора настроек:
* Системные — для всех пользователей компьютера.
* Пользовательские — для данного пользователя системы (`user` в примере).
На практике чаще всего пользуются ими. Хранятся в профиле пользователя.
* Локальные — для отдельного репозитария, хранятся в нем же.
Используются, если нужно работать с проектами от разного имени
(примеры: личные и корпоративные проекты отдельно, Алиса и Боб в случае ЛР).
Локальные настройки перекрывают пользовательские.
Пользовательские настройки перекрывают системные.
Настройки Git сами не находятся под контролем версий,
они специфичны для конкретного компьютера или конкретной копии репозитария.
Настроим репозитарий Алисы, чтобы коммиты были от ее имени:
``` sh
git config user.name 'Alice (IvanovII)'
git config user.email 'alice@example.com'
```
**Самостоятельно.** Укажите данные пользователя, как в примере.
Вместо `IvanovII` используйте свое имя и инициалы латиницей.
Используйте свой университетский адрес почты.
Git сам по себе не отправляет писем на этот адрес.
Кавычки должны быть парными.
Они могут быть одинарными (`'`) или двойными (`"`).
Если нарушить парность кавычек или нажать *Enter,* не закрыв кавычку,
ввод команды продолжится на следующей строке. В этом случае можно прервать
выполнение команды, нажав *Ctrl + C,* затем ввести команду правильно.
## Создание коммитов
Запустите CodeBlocks и создайте проект в репозитарии Алисы. Убедитесь,
что не создается ненужных подкаталогов:
*Project title:* `project`\
*Folder to create project in:* `C:\Users\user\Desktop\lab02\alice`\
*Project filename:* `project.cbp`\
*Resulting filename:* `C:\Users\user\Desktop\lab02\alice\project\project.cbp`
Соберите проект.
На этом этапе должна быть следующая структура файлов и каталогов:
``` text
lab02
├── alice
│   └── project <--------- текущий рабочий каталог
│   ├── .git <--------- создан командой "git init"
│   ├── bin <--------- создан CodeBlocks при сборке
│   ├── obj <--------- (то же самое)
│   ├── main.cpp <-- код программы
│   └── project.cbp <-- файл проекта
└── bob
```
### Занесение файлов под контроль версий
Вернувшись в Git Bash, просмотрим состояние рабочей копии:
``` sh
git status
```
**В отчете** нужно пояснить, что означает каждая строка вывода этой команды.
Добавим файл `main.cpp` в отслеживаемые (в индекс):
``` sh
git add main.cpp
```
На Windows может отобразиться такое сообщение:
``` text
warning: LF will be replaced by CRLF in main.cpp
The file will have its original line endings in your working directory
```
Оно безвредно. Смысл в том, что Git хранит файлы с немного измененном виде,
чтобы обеспечивать удобную работу с репозитарием в любой операционной системе.
**Самостоятельно.**
Еще раз просмотрите состояние рабочей копии и поясните в отчете изменения.
Выполним коммит с файлом `main.cpp` и коротким сообщением:
``` sh
git commit -m 'code: заготовка программы'
```
### Составление сообщений к коммитам
На практике важно, чтобы описания коммитов были информативными: в будущем
по ним быстро читают историю проекта, ищут коммиты по ключевым словам.
Заголовок (первая строка) должен быть коротким (желательно до 50 символов)
и описывать суть изменений, потому что только он показывается в списке
коммитов. Часто в заголовок включают тему (к какой части проекта относится
коммит) или номер задачи в системе отслеживания ошибок:
* `code: заготовка программы` — изменен код (а не документация, например)
* `build: update CMake version` — коммит относится к сборке
* `обрабатывает пустой массив | fixes #1234` — исправляет ошибку № 1234
* `timer: учет високосных лет #4321` — доработка таймера по задаче № 4321
Временным незаконченным коммитам иногда приписывают `WIP:` (work in progress).
Из заголовка должно быть ясно, что в целом сделано и зачем (почему, для чего).
Обычно нет смысла писать, какие именно файлы и функции были изменены, потому
что это можно просмотреть в самом коммите. После заголовка через пустую строку
может идти расширенное пояснение (тело), иногда очень длинное.
Как и для исходного кода, главный критерий — понятность и единообразие. Можно
писать на русском или английском, в совершенной форме или в повелительном
наклонении — но одинаково во всех коммитах.
**Самостоятельно.**
Добавьте файл `project.cbp` в индекс и сделайте коммит с ним, тема — `build`.
Сообщение после темы придумайте по смыслу изменений, например, для этого
коммита подошло бы «добавлен файл проекта» или «add project file».
### Создание коммитов с изменениями
Заменим тело функции `main()` на ввод двух чисел:
``` cpp
cout << "Enter A and B: ";
int a, b;
cin >> a >> b;
```
**Самостоятельно.**
Просмотрите состояние репозитария (`git status`). В отчете поясните различия
между случаем, когда добавлялся новый файл, и когда изменился существующий.
Чтобы закоммитить изменения, есть три способа, описанных ниже. Обратите
внимание: Git «видит» состояние файлов на диске, поэтому после добавления
изменений нужно сохранять файл в CodeBlocks. Желательно также собирать
программу после изменений.
**Способ 1.**
Сначала выбрать файлы, изменения которых должны войти в коммит, затем сделать
коммит:
``` sh
git add main.cpp
git commit -m "..."
```
Этот способ удобен, если изменения присутствуют не только в тех файлах, которые
коммитятся. Например, если работа над кодом уже закончена, а документация еще
не дописана и коммитить ее не нужно.
**Самостоятельно.**
Добавьте в программу вывод суммы `a` и `b`.
**Способ 2.**
Добавить в индекс все изменения, затем сделать коммит:
``` sh
git add -u
git commit -m "..."
```
Способ удобен, если измнено много файлов. После `git add -u`, которая
добавляет в индекс измененные файлы, можно командой `git add <файл>` добавить
в индекс новые файлы.
**Самостоятельно.**
Добавить в программу вывод разности `a` и `b`.
**Внимание.**
Код доработок должен быть составлен в точности так:
``` cpp
cout << "A + B = " << a + b << '\n'
<< "A - B = " << a - b << '\n';
```
Дальнейшие дополнения тоже должны продолжать одну большую инструкцию вывода,
а не быть отдельными. Это нужно для того, чтобы в последующих пунктах
можно было наблюдать некоторые примечательные ситуации.
**Способ 3.**
Добавить все изменения в индекс и сделать коммит в один шаг:
``` sh
git commit -a -m "..."
```
Способ полностью эквивалентен предыдущему и удобен, если коммит меняет
только существующие файлы.
## Игнорирование файлов
Можно заметить, что в выводе команды `git status` все время присутствуют
каталоги `bin/` и `obj/`. Они содержат бинарные файлы (целевой `*.exe`
и промежуточные), которые являются производными от исходного кода, уже
находящегося под контролем версий. Является грубой ошибкой заносить
под контроль версий продукты сборки. То же самое относится к файлам,
в которых некоторые среды сохраняют, например, состояние редактора: открытые
файлы и расположение окон одного члена команды не нужны в общем хранилище.
Укажем Git игнорировать присутствие каталога `bin`. Для этого создадим
в CodeBlocks новый файл *(File → New... → Empty)* и запишем в него строку:
``` text
/bin
```
Косая черта в начале означает путь от корня репозитария (каталога `project`),
без нее игнорировался бы файл или каталог `bin` в любой подпапке. Сохраним
файл в корне репозитарий под именем `.gitignore`, именно с точкой в начале.
Каждое правило игнорирования пишется на отдельной строке `.gitignore`.
Выполнив `git status`, можно видеть, что каталог `bin` не отображается.
**Самостоятельно.**
Занесите каталог `obj` в список игнорируемых и убедитесь, что это удалось.
Файл `.gitignore` может и обычно должен находиться под контролем версий.
**Самостоятельно.**
Создайте коммит с `.gitignore`, тема — `git`.
## Просмотр истории
### Работа с журналом репозитария
Журнал репозитария показывает команда `git log`. У нее много опций, например:
* `git log --stat` показывает файлы, измененные в коммитах;
* `git log --oneline --decorate` показывает коммиты компактно;
* `git log --oneline --decorate --all --graph` делает то же для всех веток.
Среди прочего, команда показывает для каждого коммита его хэш,
например, `d2e8af7ff9c4684d0deb60d3305474bcaf69ce5c`. Некоторые версии
команды показывают хэш сокращенно — краткий вариант тоже будет восприниматься
командами Git, которые принимают хэш.
Если лог изменений длинный, `git log` показывает текст с прокруткой.
Чтобы выйти из этого режима, нажмите `q`.
Попробуйте каждую из приведенных команд. **В отчете** подробно опишите,
что показывается `git log --stat` для последнего коммита.
Коммиты можно фильтровать по разным признакам:
* `git log -- main.cpp` показывает затрагивающие `main.cpp`;
* `git log --grep "code:"` показывает коммиты с `code:` в сообщении.
**Самостоятельно.**
Найдите сначала коммиты по теме `build`, затем коммиты, затрагивающие
`project.cbp`.
### Просмотр коммитов
Содержимое отдельных коммитов просматривается командой `git show <refspec>`,
где `<refspec>` может быть хэшем коммита, именем ветви или выражением,
которое задает, на сколько от них отступить в истории.
Просмотрим последний коммит тремя эквивалентными способами:
1. `git show HEAD` (текущий)
2. `git show master` (по имени ветви)
3. `git show d2e8af` (по хэшу нужного коммита)
Для просмотра предыдущего коммита можно либо записать его хэш,
либо указать, что от последнего нужно отступить на один коммит: `HEAD~1`.
**Самостоятельно.**
Просмотрите предпоследний коммит **(в отчете** зафиксируйте результат единожды)
тремя способами.
### Просмотр изменений
Внесем изменения в `main.cpp`: добавим печать произведения чисел,
но не станем пока делать коммит.
Просмотрим изменения в рабочей копии:
``` sh
git diff
```
**В отчете** необходимо пояснить все компоненты отображаемого патча.
Первый аргумент команды `git diff` включает показ изменений от указанного
коммита до последнего, включая изменения в рабочей копии:
``` sh
git diff HEAD~2
```
С двумя аргументами команда показывает разницу между указанными коммитами,
например, так можно исключить изменения в рабочей копии из вывода предыдущей
команды:
``` sh
git diff HEAD~2 HEAD
```
**Самостоятельно.**
Просмотрите изменения между самым первым коммитом и коммитом, добавляющим
вывод разности.
### Использование GUI
Просмотр истории — одна из операций в СКВ, которую иногда удобнее выполнять
из графической среды. Вместе с Git поставляется графическая оболочка gitk
(Git GUI), которую можно вызвать пунктом *Git GUI Here* в контекстном меню
папки проекта. Эта оболочка очень примитивная, на практике пользуются
[более мощными](https://git-scm.com/downloads/guis) или встроенными в среду
разработки.
Просмотр истории в gitk делается из меню *Repository → Visualize All Branch
History.* Можно выбирать коммит для просмотра из списка; смотреть
как изменения *(Diff),* так и версии файлов *(Old version, New version);*
искать коммиты.
**В отчет** ничего заносить не нужно.
## Откат изменений
**Самостоятельно.**
Закоммитьте изменения в рабочей копии (вывод произведения).
Предположим, необходимо отменить (откатить) этот коммит, то есть вернуться
к предыдущему. Для этого воспользуемся командной `git reset`:
``` sh
git reset --hard HEAD~1
```
Здесь `HEAD~1` указывает на коммит, к которому нужно откатить состояние рабочей
копии, а ключ `--hard` означает, что нужно привести рабочую копию точно
к состоянию выбранного коммита.
CodeBlocks (и другие среды) могут при этом показать предупреждение, что файл
на диске был изменен, и предложить загрузить его заново. Следует согласиться.
Добавим над функцией `main()` комментарий:
``` cpp
// you may type whatever you want
```
Уберем изменения в `main.cpp` другим способом — откатив этот файл к состоянию
в последнем коммите (`HEAD`):
``` sh
git checkout HEAD -- main.cpp
```
Второй способ необходим, чтобы откатывать отдельные файлы. Аргумент `HEAD`
необязателен, но вместо него можно указать не последний, а любой другой
коммит. Это полезно, если нужно восстановить состояние одного файла таким,
какое оно было в известный момент.
## Обмен кодом через удаленное хранилище
### Регистрация на сервере
Зарегистрируйтесь на [Git УИТ](http://uit.mepi.ru/git)
под именем вида `KozlyukDA` (своя фамилия и инициалы, как почта МЭИ).
Пароль придумайте самостоятельно.
### Настройка SSH
Отправлять изменения в удаленный репозитарий обычно могут не все.
Так, доступ на запись к репозитариям по умолчанию есть только
у создателя (пользователя, зарегистрированного на предыдущем шаге).
Загрузка комитов (доступ на чтение) из публичных репозитариев разрешена всем.
Сервер должен выяснить, что клиент, представившийся определенным пользователем,
действительно им является (провести *аутентификацию*).
Клиент git взаимодействует с сервером по протоколу SSH (secure shell),
который использует для аутентификации пары ключей:
открытый (public, публичный) и закрытый (private, приватный) ключ.
Конкретный открытый ключ связан с конкретным закрытым.
Сначала открытый ключ загружается на сервер через web-интерфейс.
Затем любой клиент, который обладает соответствующим закрытым ключом,
может доказать это серверу.
У одного пользователя может быть несколько пар ключей,
например, для рабочего и домашнего компьютера,
тогда на сервер загружаются два открытых ключа.
**Внимание.**
Закрытый ключ является таким же секретом, как пароль пользователя.
Любой, кто получит закрытый ключ, сможет вносить на сервер изменения
от имени вашего пользователя.
Закрытый ключ нельзя давать никому, открытый ключ можно давать свободно.
Создать пару ключей:
``` sh
ssh-keygen
```
По умолчанию закрытый ключ записывается в файл `/home/user/.ssh/id_rsa`,
можно оставить это значение по умолчанию (нажать *Enter*).
Далее нужно ввести пароль, которым будет защищен ключ, и повторить его.
Пример вывода команды:
`Generating public/private rsa key pair.
Enter file in which to save the key (/home/user/.ssh/id_rsa):` *(Enter)*\
`Enter passphrase (empty for no passphrase): ` *(ввод не отображается)*\
`Enter same passphrase again: ` *(ввод не отображается)*\
`Your identification has been saved in /home/user/.ssh/id_rsa
Your public key has been saved in /home/user/.ssh/id_rsa.pub`\
*(Далее следуют уникальные для каждого ключа строки.)*
Вводить пароль каждый раз, когда используется ключ, неудобно.
Используют программу-агент, которая работает в фоне и предоставляет ключи
другим программам, в том числе git.
Пароль требуется тогда вводить один раз — при загрузке ключа в агент.
Запустить агент:
``` sh
eval `ssh-agent -s`
```
Загрузить ключ (потребуется ввести пароль):
``` sh
ssh-add
```
По умолчанию `ssh-add` загружает `~/.ssh/id_rsa`, для загрузки других ключей,
если это нужно, можно передавать ей путь к файлу ключа явно.
Отобразить открытый ключ можно командой:
``` sh
cat ~/.ssh/id_rsa.pub
```
**Самостоятельно.**
Скопировать открытый ключ (текст) и добавить в список открытых ключей
своей учетной записи. Это делается в настройках (меню пользователя
в правом верхнем углу, пункт *Settings*), раздел *SSH and GPG keys,*
кнопка *New SSH key.*
Если работа выполняется в компьютерном классе, закрытый ключ будет утерян
после выхода из учетной записи (или выключении компьютера). Проще всего
дома или на следующем занятии создать новый ключ и добавить его на сервер.
На практике ключи не уничтожают (кроме случаев, когда их украли),
а переносят как файлы, например, при переустановке системы.
Из проводника Windows файл закрытого ключа
виден как `C:\Users\User\.ssh\id_rsa`,
если понадобится его скопировать.
### Отправка проекта на сервер
[Создайте репозитарий](https://help.github.com/articles/create-a-repo/)
под названием `cs-lab02`. Вопреки рекомендациям по ссылке, не нужно добавлять
в репозитарий файл `README.md` или лицензию.
После создания пустого репозитария будет показана страница с инструкциями,
как настроить связь с удаленным хранилищем:
1. В разделе *Quick setup* нужно выбрать вариант SSH.
2. В разделе *…or push an existing repository from the command line*
даны команды, которые необходимо выполнить.
Обновите страницу и убедитесь, что файлы проекта видны в web-интерфейсе.
Любой файл можно просмотреть в бразуере.
По ссылке *Commits* можно просматривать коммиты.
### Получение проекта с сервера
Предположим, к разработке проекта присоединяется Боб.
Откройте новый терминал Git Bash в каталоге `bob`.
Клонируйте проект:
``` sh
git clone <адрес> <каталог>
```
На место `<адреса>` нужно подставить адрес, который использовался в команде
`git remote add` (его можно всегда отобразить командой `git remote -v`).
Каталог — название папки для проекта: используйте `project`, если не указывать,
это было бы название репозитария (`cs-lab02`). Угловых скобок в команде быть
не должно!
Перейдите в каталог проекта «на машине Боба» (здесь и далее это означает
работу во втором терминале и над файлами в `bob/project`):
``` sh
cd project
```
**Самостоятельно.**
«На машине Боба» настройте Git (`git config`) аналогично тому, как это
делалось для Алисы в начале лабораторной работы.
## Совместная работа над проектом без конфликтов правок
«На машине Боба» добавьте в программу печать произведения чисел и сделайте
коммит. Просмотрите последний коммит и убедитесь, что он сделан от имени
Боба.
Отправьте коммит на сервер.
``` sh
git push
```
**Примечание.**
Поскольку работа от лица Алисы и Боба ведется одним локальным пользователем,
используется один и тот же ключ SSH, поэтому Бобу не требуется отдельной
учетной записи на сервере и отдельного ключа SSH.
На практике у каждого разработчика, разумеется, своя учетная запись и ключ.
Обновите страницу в web-интерфейсе и убедитесь, что коммит попал в удаленный
репозитарий. Обратите внимание, что авторство коммитов записано в самих
коммитах, оно не зависит от пользователя системы.
«На машине Алисы» (то есть в первом терминале, в каталоге `alice/project`)
выполните загрузку изменений:
``` sh
git fetch
```
Убедитесь, что в рабочей копии изменений еще не произошло.
Просмотрите историю всех веток:
``` sh
git log --oneline --decorate --all --graph
```
Как можно видеть, ветка `master` отстает на один коммит от ветки
`origin/master` (версии ветки `master` из удаленного репозитария под названием
`origin`, то есть на сервере).
Продвиньте ветку `master` к скачанной версии:
``` sh
git pull --ff-only
```
Убедитесь, что рабочая копия проекта «у Алисы» соответствует версии «у Боба».
Команда `git pull` автоматически делает `git fetch`, поэтому можно было бы
применять только ее, но важно понимать, что получение изменений в Git
двухфазное: загрузка новой части истории и синхронизация положения веток.
**Самостоятельно.**
«От имени Алисы» добавьте в программу печать деления, сделайте коммит,
отправьте его на сервер и получите новую версию «на машине Боба».
Иначе говоря, повторите шаги выше, поменяв местами роли Алисы и Боба.
## Разрешение конфликтов правок при совместной работе
Предположим, Алиса решает добавить в программу печать максимума из чисел,
а Боб — минимума.
**Внимание.** Код вывода в программе перед выполнением дальнейшего должен
иметь следующий вид:
``` cpp
cout << "A + B = " << a + b << '\n'
<< "A - B = " << a - b << '\n'
<< "A * B = " << a * b << '\n'
<< "A / B = " << a / b << '\n';
```
В противном случае код нужно привести в соответствие отдельным коммитом
и синхронизировать состояние «у Алисы» и «у Боба».
«На машине Алисы» дополните программу печатью максимума, сделайте коммит
и отправьте его на сервер.
«На машине Боба» дополните программу печатью минимума, сделайте коммит
и попытайтесь отправить его на сервер. Как можно видеть, удаленный
репозитарий не принимает изменений: коммит Боба основан не на последнем
существующем коммите.
«От лица Боба» загрузите коммиты из удаленного хранилища и отобразите
историю всех веток — результат нужно представить **в отчете.**
Можно видеть, что ветка `master` раздвоилась. Бобу нужно переместить свой
коммит поверх коммита Алисы, то есть поверх `origin/master`:
``` sh
git rebase origin/master
```
Однако эта команда завершается с ошибкой, сообщающей о конфликте в `main.cpp`.
Просмотрите состояние хранилища и поясните **в отчете.**
«На машине Боба» в CodeBlocks место конфликта будет отмечено прямо в коде.
Необходимо **самостоятельно:**
1. Удалить метки конфликта: `<<<< ...`, `... >>>>` и `=====`.
2. Отредактировать код так, чтобы он включал и правки Алисы, и правки Боба.
3. Убедиться, что программа компилируется и работает.
После того, как конфликт разрешен, нужно добавить файл в индекс и продолжить
прерванную операцию `rebase`:
``` sh
git add main.cpp
git rebase --continue
```
Убедитесь, что история хранилища теперь имеет желаемый вид (зафиксировав
это **в отчете)** и отправьте изменения на сервер.
## Использование веток
Предположим, пока Боб синхронизировал изменения, Алиса решила изменить
тип чисел с целых на действительные. Предполагая, что это займет время,
Алиса ведет работу в отдельной ветке. На момент начала работы репозитарий
Алисы *не* синхронизирован с сервером, то есть последний коммит добавляет
печать максимума. Все действия ведутся «на машине Алисы».
Создайте ветку `double`:
``` sh
git branch double
```
Переключитесь на нее:
``` sh
git checkout double
```
**Примечание.** Создание ветки и переключение на нее можно делать одной
командой: `git checkout -b double`. Этой команде можно передать
аргумент-ссылку на коммит, где создать ветку.
Можно заметить, что текущая ветка в приглашении терминала изменилась.
Замените тип переменных `a` и `b` на `double` и сделайте коммит.
Переключитесь на ветку `master`:
``` sh
git checkout master
```
**Самостоятельно.**
Синхронизируйте ветку `master` «на машине Алисы» с сервером.
Просмотрите историю всех веток и занесите результат **в отчет.**
Слейте ветку `double` в `master`:
``` sh
git merge double
```
В результате слияния образуется специальный новый коммит (merge commit),
к которому Git предлагает написать сообщение в редакторе. Строки,
начинающиеся с октоторпа («решетки», `#`), в сообщение не войдут.
Отправьте изменения на сервер.
Просмотрите и занесите **в отчет** историю всех веток репозитария.
### Редактор Vim
Vim — продвинутый текстовый редактор. Он не является частью Git, но популярен
в системах семейства \*nix, поэтому предлагается по умолчанию. Не обязательно
его использовать, но нужно знать минимум для обращения с ним.
После запуска Vim находится в так называемом *нормальном режиме.*
Чтобы начать вводить текст, нужно перейти *в режим вставки,*
нажав `i` (одну клавишу).
В режиме вставки можно набирать текст обычным образом.
Вернуться в нормальный режим можно нажатием *Escape.*
Находясь в нормальном режиме, можно сохранить сообщение и выйти из Vim
нажатием `ZZ` (две заглавные Z, то есть *Shift+Z* два раза).
Если вместо *Shift+Z* нажать *Ctrl+Z,* Vim будет приостановлен, а коммит
останется незавершенным. В этом случае нужно вернуться в Vim командой `fg`
в терминале.
Чтобы писать длинные сообщения, но не использовать Vim, можно указать
другой редактор (например, примитивный `nano`):
``` sh
EDITOR=nano git merge double
```
# Формат защиты
Защита состоит из ответов на теоретические вопросы по лекции
и выполнения задания, рассчитанного на 10 минут.
Пример задания:
1. Создать новый репозитарий.
2. Закоммитить файл `task.txt` с цифрами от 0 до 9 на отдельных строках.
3. Удалить строки с цифрами от 5 до 8, закоммитить.
4. Просмотреть предпоследний коммит.
5. Создать ветку `task` от предыдущего коммита.
6. Переключиться на ветку `task`.
7. Добавить в начало файла строки с буквами `a`, `b`, `c`, закоммитить.
8. Переключиться на ветку `master`.
9. Добавить в начало файла строки с буквами `d`, `e`, `f`, закоммитить.
10. Слить ветку `task` в `master`, разрешив конфликт так, чтобы буквы шли
по порядку.
Загрузка…
Отмена
Сохранить