Skip to content

Latest commit

 

History

History
472 lines (372 loc) · 38.3 KB

File metadata and controls

472 lines (372 loc) · 38.3 KB

Задание 1. Init Repo (optional)

  1. Создай папку my-project

  2. Создай внутри файл hello.txt

  3. Выполни в контекстном меню папки my-project команду GitExt Create new repository

  4. Убедись, что появилась скрытая папка .git

Для Windows: чтобы отображались скрытые файлы и папки, в проводнике нужно отметить галочку Вид - Скрытые элементы. Лучше рядом также отметить галочку Расширения имен файлов

  1. Выполни в контекстном меню папки my-project команду GitExt Open repository. Пока в репозитории пусто. Так и должно быть.

Задание 2. Commits

  1. Найди в GitHub репозиторий https://github.com/kontur-courses/git-sheet, сделай его fork в свой профиль, а затем склонируй форкнутый репозиторий. НЕ СПУТАЙ: это НЕ репозиторий с презентацией и текстом этого задания!

  2. Открой папку git-sheet в VS Code (File - Open Folder).

  3. Через VS Code создай файл init.md со следующим содержимым (здесь и далее копировать надо то, что между тройных бэктиков как этот текст, но не сами «бэктики»):

## S1. Everything Is Local
### Все работает локально
1. `git init` — создать пустой репозиторий
2. `git clone <url>` — склонировать репозиторий в новую директорию

  1. Открой репозиторий, убедись, что в нем есть коммит с названием Initial commit

  2. Нажми кнопку Commit, чтобы открыть окно коммита

  3. Переведи init.md из верхней части в нижнюю часть окна кнопкой Stage либо двойным нажатием по имени файла. Теперь init.md находится в Commit index

  4. Введи в качестве сообщения к коммиту Add init.md и сделай коммит кнопкой Commit

  5. Убедись, что коммит появился в истории коммитов

  6. Создай файл commit.md со следующим содержимым:

## S2. Tree Of Commits
### Хранится последовательность состояний некоторой директории

  1. Выбери в истории коммитов Working directory и убедись, что там есть измененный файл commit.md
  2. Открой окно коммита и переведи commit.md в Commit index и закрой окно коммита
  3. Выбери в истории коммитов Commit index и убедись, что измененный файл commit.md теперь находится там
  4. Замени содержимое commit.md на следующее:
## S2. Tree Of Commits
### Хранится последовательность состояний некоторой директории
1. `git add .` — добавить все измененные файлы в индекс
2. `git commit -m <msg>` — записать изменения из индекс в репозиторий
3. `git status -sb` — вывести состояние директории и индекса кратко с указанием текущей ветки
4. `git log --oneline` — вывести список коммитов, связанных с HEAD, в кратком виде
5. `git log --oneline --graph` — вывести историю коммитов, связанных с HEAD, в виде дерева
6. `git log --oneline --graph --all` — вывести историю всех коммитов в виде дерева

  1. Посмотри историю коммитов. Убедись, что commit.md изменен как в в Working directory, так и в Commit index
  2. Открой окно коммита и убедись, что commit.md находится как в верхней части окна, так и в нижней, причем содержимое у файлов разное и при выборе commit.md в верхней части показывается отличия от Commit index, а не предыдущего коммита
  3. Выполни коммит с сообщением Add commit.md header
  4. В истории коммитов найди только что созданный коммит и убедись, что в него попали только изменения из Commit index
  5. Закоммить оставшиеся в Working directory изменения с сообщением Change commit.md

Задание 3. Tag (optional)

  1. Выбери в дереве коммитов последний коммит и создай в нем тег v0.1 с помощью контекстного меню
  2. Перейди на Initial commit с помощью команды Checkout this commit в контекстном меню
  3. Используй пункт главного меню Commands / Checkout revision, чтобы вернуться обратно на помеченный тегом коммит. Для этого введи имя тега v0.1 в поле для ввода ревизии.

Задание 4. Feature Branches

  1. Создай новую ветку branch-feature с помощью контекстного меню. Git Extensions автоматически сделает checkout на нее, а значит при следующем коммите именно она сдвинется вслед за HEAD.

  2. Создай новый файл branch.md со следующим содержимым:

## S3. Refer To Branch
### Используются именованные ссылки
1. `git tag` — вывести список тегов
2. `git tag <tagname>` — создать тег
3. `git branch` — вывести список локальных веток
4. `git branch -av` - вывести список локальных и удаленных веток
5. `git branch <branchname>` — создать ветку
6. `git branch -d <branchname>` — удалить ветку
7. `git checkout <commit>` — переместить HEAD на коммит
8. `git checkout <branch>` — переместить HEAD на ветку
9. `git checkout -m <branch>` — переместить HEAD, объединить текущие изменения с состоянием ветки
10. `git checkout -b <new_branch>` — создать новую ветку и перейти на нее

  1. Закоммить изменения с сообщением Add branch.md

  2. Перейди назад на ветку master, используя контекстное меню и создай ветку bullet-feature

  3. Во всех доступных md-файлах замени нумерованные списки на ненумерованные списки. На примере init.md это выглядит следующим образом. Было:

## S1. Everything Is Local
### Все работает локально
1. `git init` — создать пустой репозиторий
2. `git clone <url>` — склонировать репозиторий в новую директорию

Стало:

## S1. Everything Is Local
### Все работает локально
- `git init` — создать пустой репозиторий
- `git clone <url>` — склонировать репозиторий в новую директорию

Аналогично сделай для commit.md.

  1. Закоммить изменения с сообщением Replace with bullets

  2. Перейди назад на ветку master, используя контекстное меню

  3. Замени содержимое commit.md на следующее:

## S2. Tree Of Commits
### Хранится последовательность состояний некоторой директории
1. `git add .` — добавить все измененные файлы в индекс
2. `git commit -m <msg>` — записать изменения из индекс в репозиторий
3. `git status -sb` — вывести состояние директории и индекса кратко с указанием текущей ветки
4. `git show <commit>` — показать содержимое коммита
5. `git log --oneline` — вывести список коммитов, связанных с HEAD, в кратком виде
6. `git log --oneline --graph` — вывести историю коммитов, связанных с HEAD, в виде дерева
7. `git log --oneline --graph --all` — вывести историю всех коммитов в виде дерева

  1. Закоммить изменения с сообщением show command for commit.md
  2. Обрати внимание, что история коммитов стала похожа на дерево, а на концах веток этого дерева расположены метки master, branch-feature, bullet-feature. А вот тег v0.1, остался на своем месте.

Правильное дерево коммитов для этого этапа

Задание 5. Merge Conflict

  1. Начни вливать bullet-feature в master: HEAD уже находится на master, поэтому укажи на bullet-feature и с помощью контекстного меню выбери Merge into current branch. Но выполнение Merge закончится конфликтом. Конфликт произошел, потому что в этот файл вносились изменения и в bullet-feature и в master.

  2. Git Extensions предложит сразу перейти ко второй части слияния — разрешению конфликтов. Согласись. Откроется окно Resolve merge conflicts со списком файлов с конфликтами. В списке будет только один файл — commit.md. Конфликт произошел, потому что в этот файл вносились изменения и в bullet-feature и в master. Нажми на кнопку Open in vscode и в качестве инструмента для объединения изменений откроется VS Code. Часто конфликты разрешаются выбором варианта из одной из веток, но это не тот случай. В VS Code нажми Compare Changes и убедись, что поменялось все. Придется объединять изменения аккуратно вручную. Сначала выбери Accept Both Changes — теперь текст обоих изменений станет доступен для редактирования. Затем напиши правильную версию блока. В ней должна быть команда git show и перед каждой командой должны быть дефисы. Когда закончишь редактирование сохрани изменения (как обычно Ctrl+S), закрой файл в VS Code и переключись на Git Extensions.

  3. Git Extensions сообщит, что все конфликты разрешены и предложит перейти к третьей части слияния — коммиту. Согласись. Откроектся знакомое окно коммита, в котором в Commit index будут показаны все изменения относительно HEAD. В Commit message будет указано хорошее подробное сообщение: его можно не менять. Закоммить результаты merge.

  4. Убедись, что в результате твоих действий был создан новый коммит, объединяющий две ветви изменений. HEAD сдвинулся на него, а master сдвинулся за HEAD.

Задание 6. Hidden Conflict

  1. Начни вливать branch-feature в master, как и в прошлый раз. Конфликтов в этот раз не будет, поэтому шаг разрешения конфликтов будет пропущен. А еще Git Extensions автоматически сделает commit. Таким образом слияние будет выполнено.

  2. Хоть «настоящих» конфликтов нет, после слияния появился «логический» конфликт. Дело в том, что файл branch.md до сих пор содержит нумерованный список. Замени числа в нем на дефисы, аналогично другим файлам.

  3. Теперь пришло время добавить в историю эти изменения. Простой способ это сделать — коммит с сообщением вида Fix after merge. Прекрасно работает. Но можно воспользоваться Ammend Commit. Эта команда позволяет дополнить последний коммит дополнительными изменениями. Открой окно коммита, выбери опцию Ammend Commit: в Commit message появится сообщение из предыдущего коммита, затем добавь в Commit index файл branch.md и сделай commit. Появится предупреждение о том, что переписывается история. Да, так и есть. Соглашайся.

Задание 7. Fast-Forward Merge

  1. Создай ветку merge-feature и перейди на нее
  2. Создай файл merge.md со следующим содержимым:
## A1. Merge Them All
### Два состояния можно объединить через merge, mergetool и commit
- `git merge <commit>` — объединить текущую ветку с другой
- `git mergetool` — разрешить имеющиеся конфликты

  1. Закоммить изменения с сообщением Add merge.md
  2. Перейди назад на ветку master
  3. Влей merge-feature в master
  4. Заметь, что в этот раз не только конфликтов не было, но и новый коммит не был создан. Потому что в master не было изменений и для объединения двух веток было достаточно передвинуть master на коммит, на который ссылалась merge-feature.

Правильное дерево коммитов для этого этапа

Задание 8. Hot Rebase

  1. Создай ветку rebase-feature и перейди на нее. Используй сочетание Ctrl+B, чтобы вызвать диалог создания ветки: так быстрее!
  2. Создай файл rebase.md со следующим содержимым:
## A2. Immutable History
### Нельзя переписать историю — можно создать новую
- `git commit --ammend` — заменить последний коммит ветки на отредактированный с дополнительными изменениями
- `git rebase <upstream>` — применить все коммиты от общего родителя до текущего к `<upstream>`
- `git rebase -i <upstream>` — применить заново все коммиты, указав действие с каждым коммитом
- `git cherry-pick <commit>` — применить указанный коммит к HEAD

  1. Закоммить изменения с сообщением Add rebase.md Воспользуйся сочетанием Ctrl+Space, чтобы открыть окно коммита: так быстрее!
  2. Создай файл reflog.md со следующим содержимым:
## A4. Hide The Garbage
### Видно только то, на что есть ссылки
- `git gc` — удалить ненужные файлы и оптимизировать локальный репозиторий
- `git clean` — удалить неотслеживаемые файлы из директории
- `git reflog show <ref>` — показать лог действий со ссылкой
- `git reflog` = `git reflog show HEAD` — показать лог действий с HEAD

  1. Закоммить изменения с сообщением Add reflog.md. Используй Ctrl+Space.

  2. Перейди на ветку master. Используй Ctrl+..

  3. Создай файл reflog.md со следующим содержимым:

## A4. Hide The Garbage
### Lorem ipsum dolor sit amet, consectetur adipiscing elit

  1. Закоммить изменения с сообщением Add stub for reflog.md. Используй Ctrl+Space.

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

  3. Установи тег old-rebase-feature на коммит, на который ссылается rebase-feature

  4. Перейди на ветку rebase-feature

  5. Выполни rebase rebase-feature на master: HEAD уже находится на rebase-feature, поэтому укажи на master и с помощью контекстного меню выбери Rebase current branch on, а затем Selected commit. При rebase возникнет конфликт.

  6. Первый коммит Add rebase.md успешно скопирован, а вот Add reflog.md по понятным причинам порождает конфликты. Нажми кнопку Solve conflicts, чтобы разрешить конфликты в VS Code. Несмотря на то, что файлы были созданы в разных ветках, Git видит, что первые строчки совпадают и по ним конфликта нет. А вот оставшиеся строчки конфликтуют. Так как в ветке rebase-feature был правильный текст, нажми Accept Incoming Change, затем сохрани изменения, закрой файл в VS Code, перейди в Git Extensions и нажми Continue rebase. Раз оба коммита были успешно скопированы, rebase на этом будет закончен.

  7. Обрати внимание, что в результате rebase были созданы коммиты Add rebase.md и Add reflog.md. Хоть они похожи на исходные, все же это новые коммиты с новыми ревизиями. Ветка rebase-feature была перемещена и теперь ссылается на новый коммит. Старые коммиты остались в репозитории и на последний из них все еще ссылается тег old-rebase-feature.

  8. Перейди на ветку master и влей в него изменения из rebase-feature. Это будет fast-forward merge.

Задание 9. Reflog (optional)

  1. Удали тег old-rebase-feature. Коммит, на который он ссылался будет скрыт, но продолжит существовать в репозитории.
  2. Выбери пункт главного меню Commands / Show reflog. В результате ты увидишь список коммитов, по которым передвигался HEAD. Найди в списке действие commit: Add reflog.md и выполни Copy SHA-1 из контекстного меню. Ревизия этого коммита скопируется в буфер обмена.
  3. Используй пункт главного меню Commands / Checkout revision, чтобы перейти на коммит с ревизией из буфера обмена.
  4. Убедись, что скрытый коммит найден и снова виден. По крайней мере пока на него ссылается HEAD.
  5. Перейди на master

Задание 10. Fetch From Remote

  1. Добавь новый репозиторий для синхронизации. Для этого в меню слева найди Remotes и в контекстном меню выбери Manage. В открывшемся окне Remote repositories нажми плюс и введи параметры репозитория. Name: ext Url: https://github.com/kontur-courses/git-sheet-ext Сохрани изменения с помощью Save changes. После сохранения Git Extensions сам предложит выполнить fetch из добавленного репозитория. Соглашайся. Если не справился с GUI, то то же самое можно сделать через консоль одной командой: git remote add ext https://github.com/kontur-courses/git-sheet-ext И убедиться, что удаленные репозиторий был добавлен с помощью команды git remote -v

  2. Для тренировки выполни fetch вручную. Выбери пункт главного меню Commands / Pull/Fetch. Откроется диалоговое окно Fetch. В нем в качестве Remote выбери ext. Также убедись, что в Merge options выбран пункт Do not merge, only fetch remote changes. Нажми на кнопку Fetch, чтобы получить изменения из удаленного репозитория. Так как fetch уже был выполнен ранее, новых изменений не добавится.

  3. Убедись, что в истории появилась ветка ext/sheet-feature из удаленного репозитория, а также несколько новых коммитов.

Задание 11. Interactive Rebase

  1. Выполни Checkout branch на ветку ext/sheet-feature. Git Extensions предложить создать связанную локальную ветку с именем sheet-feature. Согласись. В удаленную ветку нельзя коммитить, поэтому создание локальной ветки чаще всего необходимо. Но не обязательно.

  2. Выполни интерактивный rebase sheet-feature на master: укажи на master и с помощью контекстного меню выбери Rebase current branch to, а затем Selected commit interactively. Откроется текстовый редактор.

  3. В текстовом редакторе описан сценарий действий для rebase. Сейчас он заключается в том, что надо взять и переместить на новое место все коммиты последовательно: сначала первый, затем второй и т.д. Все как обычно. Ниже сценария приведены комментарии по возможным действиям с коммитами. Прочитай, что делает reword, squash и fixup.

  4. В первой строчке файла замени pick на reword, а последующих строчках замени pick на fixup. Сохрани изменения и закрой текстовый редактор. Редактор откроется снова и в нем надо будет ввести новое сообщение для Sheet markup. Введи в качестве сообщения Extension.

  5. Убедись, что ветка sheet-feature теперь ссылается на новый коммит с названием Extension. А внутри этого коммита объединены все изменения скопированных коммитов.

  6. Перейди на ветку master и влей в него изменения из sheet-feature. Это будет fast-forward merge.

  7. Удали ветку sheet-feature используя контекстное меню. При удалении выбери Force delete, потому что эта ветка связана с ext/sheet-feature, которая в master не влита.

Правильное дерево коммитов для этого этапа

Задание 12. Push Force

  1. Создай новый файл push.md со следующим содержимым:
## R2. Will Push Force Be With You
### Изменить удаленный репозиторий — это push
- `git push <remote> <local_branch>:<remote_branch>` — добавить изменения из локальной ветки `<local_branch>` и переместить ветку `<remote_branch>` удаленного репозитория
- `git push` = `git push origin HEAD` — добавить изменения из текущей локальной ветки и переместить соответствующую ветку удаленного репозитория

  1. Закоммить изменения с сообщением Add push.md

  2. Сделай push локальной ветки master в master из origin с помощью Commands / Push в главном меню.

  3. Замени содержимое push.md на следующее:

## R2. Will Push Force Be With You
### Изменить удаленный репозиторий — это push
- `git push <remote> <local_branch>:<remote_branch>` — добавить изменения из локальной ветки `<local_branch>` и переместить ветку `<remote_branch>` удаленного репозитория
- `git push` = `git push origin HEAD` — добавить изменения из текущей локальной ветки и переместить соответствующую ветку удаленного репозитория
- `git push -f` — выполнить `push`, даже если удаленная ветка находится в другом поддереве
- `git push <remote> -d <branch>` — удалить ветку в удаленном репозитории

  1. Закоммить изменения с опцией Ammend Commit, чтобы не создавать лишний коммит.
  2. Обрати внимание, что старый коммит остался видимым, ведь на него ссылается origin/master.
  3. Если сейчас выполнить push, то он завешится ошибкой, т.к. навозможно продвинуть origin/master вперед по истории так, чтобы он стал ссылаться на коммит, на который ссылается master. Поэтому выполни push с опцией force. Простой способ это сделать — выполнить push, а при возникновении ошибки выбрать Force push.

Задание 13. Upstream

  1. Создай ветку upstream-feature и перейди на нее
  2. Создай новый файл upstream.md со следующим содержимым:
## R3. Upstream Mapping
### Связь локальных и удаленных веток устанавливается явно
- `git branch -vv` — вывести список локальных веток с указанием привязанных к ним upstream-веток
- `git branch -u <upstream> [<branchname>]` — задать upstream-ветку для указанной или текущей ветки
- `git push -u origin HEAD` — создать удаленную ветку, соответствующую локальной и установить между ними upstream-связь, затем добавить изменения из локальной ветки в удаленный репозиторий
- `git checkout <remote_branchname>` — создать локальную ветку, соответствующую удаленной и установить между ними upstream-связь, затем переместить HEAD на нее
- `git pull` = `git pull origin` — получить содержимое основного удаленного репозитория и влить изменения из удаленной ветки в соответствующую локальную ветку
- `git pull --ff-only` — получить содержимое, а затем влить, если возможен fast-forward merge
- `git pull --rebase` — получить содержимое и выполнить rebase локальной ветки на удаленную ветку
- `git config --global push.default simple` — задать simple-режим действий с upstream-связями при push. Это режим по умолчанию в Git 2.0 и выше

  1. Закоммить изменения с сообщением Add upstream.md
  2. Начни делать push этой ветки. Git Extensions предупредит, что ветки в удаленном репозитории еще нет. Надо согласиться. Затем Git Extensions предупредит, что у ветки upstream-feature еще нет связи с удаленной веткой и предложит ее установить. Тоже надо согласиться. В результате Git Extensions выполнит примерно такую команду: push -u origin upstream-feature:upstream-feature. То же самое можно сделать через консоль такой командой: push -u origin HEAD

Задание 14. Stash

  1. Перейди на ветку master.
  2. Создай ветку reset-feature и перейди на нее
  3. Создай новый файл reset.md со следующим содержимым:
## A3. Reset The Difference
### Хранятся файлы, разница вычисляется на лету

  1. Закоммить изменения с сообщением Add reset.md

  2. Замени содержимое reset.md на следующее:

## A3. Reset The Difference
### Хранятся файлы, разница вычисляется на лету
- `git reset --hard <commit>` — переместить текущую ветку на `<commit>`, задать индекс и директорию согласно коммиту, устранив всю разницу
- `git reset --mixed <commit>` — переместить текущую ветку на `<commit>`, задать индекс согласно коммиту, оставить разницу между исходным и новым состоянием в директории
- `git reset --soft <commit>` — переместить текущую ветку на `<commit>`, не задавать индекс и директорию согласно коммиту, а оставить разницу между исходным и новым состоянием в индексе и директории
- `git reset --hard HEAD~1` — отменить последний коммит
- `git stash` — сохранить все модифицированные файлы в виде набора изменений
- `git stash pop` — восстановить последний сохраненный набор изменений и удалить его из списка
- `git stash list` — показать список сохраненных наборов изменений

  1. Ты не влил upstream-feature в master, поэтому придется прервать работу. Выбери пункт главного меню Commands / Manage stashes. Откроется окно Stash для управления сохраненными изменениями. Нажми Stash all changes, чтобы создать новый stash. Закрой окно. Обрати внимание, что в Working directory изменения пропали.
  2. Перейди на ветку master, влей в нее ветку upstream-feature, сделай push.
  3. Перейди назад на ветку reset-feature.
  4. Верни изменения из stash. Для этого выбери пункт главного меню Commands / Manage stashes. Так как пока сохранен только один stash, просто нажми Apply Selected Stash. Изменения попадут в Working directory.
  5. Закоммить изменения с сообщением Change reset.md
  6. Похоже разработка закончена, поэтому можно влить в нее master и отдать в тестирование. Влей master.

Задание 15. Hard Reset

  1. К сожалению ты забыл добавить некоторые изменения в reset-feature. Придется отменить merge. Хорошо, что еще reset-feature не запушен.
  2. Выбери коммит Change reset.md и с помощью контекстного меню выполни Reset current branch to here. В открывшемся окне выбери опцию Hard, чтобы полностью затереть все изменения, и выполни reset.
  3. Замени содержимое reset.md на следующее:
## A3. Reset The Difference
### Хранятся файлы, разница вычисляется на лету
- `git reset --hard <commit>` — переместить текущую ветку на `<commit>`, задать индекс и директорию согласно коммиту, устранив всю разницу
- `git reset --mixed <commit>` — переместить текущую ветку на `<commit>`, задать индекс согласно коммиту, оставить разницу между исходным и новым состоянием в директории
- `git reset --soft <commit>` — переместить текущую ветку на `<commit>`, не задавать индекс и директорию согласно коммиту, а оставить разницу между исходным и новым состоянием в индексе и директории
- `git reset --hard HEAD~1` — отменить последний коммит
- `git stash` — сохранить все модифицированные файлы в виде набора изменений
- `git stash pop` — восстановить последний сохраненный набор изменений и удалить его из списка
- `git stash list` — показать список сохраненных наборов изменений
- `git revert <commit>` — создать коммит, отменяющий изменения из коммита
- `git diff <from_commit> [<to_commit>]` — вывести разницу между двумя коммитами
- `git diff --name-status <from_commit> [<to_commit>]` — список измененных файлов
- `git difftool <from_commit> [<to_commit>]` - вывести разницу с помощью difftool из настроек

  1. Закоммить изменения с сообщением Change reset.md again
  2. Снова влей master в reset-feature, чтобы в ней были все актуальные изменения.
  3. Перейди в master. Пришло запушить последнуюю версию. Для этого влей reset-feature в master и сделай push. Так как в master не произошло изменений с последнего влития master в reset-feature, это будет fast-forward merge.

Задание 16. Soft Reset (optional)

  1. Выбери начальный коммит Initial commit и с помощью контекстного меню выполни Reset current branch to here. В открывшемся окне выбери опцию Soft, чтобы вся разница между коммитами оказалась в Commit index, и выполни reset.
  2. Создай ветку solved и перейди на нее
  3. Закоммить изменения с сообщением Solved
  4. Сделай push

Правильное дерево коммитов для этого этапа