-
Создай папку
my-project -
Создай внутри файл
hello.txt -
Открой терминал (Git Bash для Windows). Выполни команду
cd путь_до_папки_my-project
Убедись что путь введен правильно: команда pwd должна вывести правильный путь до папки my-project
-
Выполни команду
git init -
Убедись, что появилась скрытая папка
.git
Для Windows: чтобы отображались скрытые файлы и папки, в проводнике нужно отметить галочку Вид - Скрытые элементы. Лучше рядом также отметить галочку Расширения имен файлов
Для Mac: чтобы отображались скрытые файлы и папки, нужно в Finder нажать Cmd + Shift + .
Также можно просмотреть список файлов и папок в текущей директории из консоли с помощью команды ls -la
- Найди в GitHub репозиторий https://github.com/kontur-courses/git-sheet,
сделай его fork в свой профиль, а затем склонируй форкнутый репозиторий.
НЕ СПУТАЙ: это НЕ репозиторий с презентацией и текстом этого задания!
Склонировать репозиторий можно с помощью команды git clone
Не забудь после этого открыть папку с репозиторем в терминале: cd git-sheet
-
Открой папку
git-sheetв VS Code (File - Open Folder). -
Открой Git Graph (кнопка в нижней панели VS Code). Убедись, что в нем есть коммит с названием
Initial commit -
Через VS Code создай файл
init.mdсо следующим содержимым (здесь и далее копировать надо то, что междутройных бэктиков как этот текст, но не сами «бэктики»):
## S1. Everything Is Local
### Все работает локально
1. `git init` — создать пустой репозиторий
2. `git clone <url>` — склонировать репозиторий в новую директорию
-
Выполни команду
git status. В секцииUntracked filesдолжен появитьсяinit.md. -
Выполни команду
git add init.mdТеперьinit.mdнаходится в Commit Index -
Сделай коммит с сообщением
Add init.md. Для этого выполни командуgit commit -m "Add init.md" -
Открой Git Graph и убедись, что коммит появился в истории коммитов
-
Создай файл
commit.mdсо следующим содержимым:
## S2. Tree Of Commits
### Хранится последовательность состояний некоторой директории
-
Выполни
git statusи убедись чтоcommit.mdнаходится в секцииUntracked files -
Добавь
commit.mdв Commit Index:git add commit.md -
Выполни
git statusи убедись чтоcommit.mdнаходится в секцииChanges to be commited -
Замени содержимое
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` — вывести историю всех коммитов в виде дерева
- Выполни
git status. Убедись, чтоcommit.mdнаходится как в Working Directory (секцияChanges not staged for commit), так и в Commit Index (секцияChanges to be commited) - Открой в VS Code вкладку Source Control (
Ctrl + Shift + G) и убедись, чтоcommit.mdнаходится как в верхней части окна, так и в нижней, причем содержимое у файлов разное и при выбореcommit.mdв нижней части показывается отличия от Commit Index, а не предыдущего от коммита - Выполни коммит с сообщением
Add commit.md header - В истории коммитов (Git Graph) найди только что созданный коммит и убедись, что в него попали только изменения из Commit Index
- Закоммить изменения с сообщением
Change commit.md
- Создай тег с именем
v0.1с помощью командыgit tag "v0.1"
Теги также можно создавать в Git Graph с помощью контекстного меню
- Найди в Git Graph начальный коммит
Initial commit, выбери его и с помощью контекстного меню выполниCheckout... - Выполни команду
git checkout v0.1, чтобы вернуться обратно на помеченный тегом коммит.
- Создай новую ветку
branch-featureи перейди на нее:git checkout -b branch-feature
Команда git checkout -b branch-name создает новую ветку и сразу выполняет checkout на нее. Это эквивалентно паре команд git branch branch-name и git checkout branch-name
- С помощью VS Code создай новый файл
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>` — создать новую ветку и перейти на нее
-
Закоммить изменения с сообщением
Add branch.md -
Перейди назад на ветку
master:git checkout master -
Создай ветку
bullet-featureи перейди на нее. -
Во всех доступных 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.
-
Закоммить изменения с сообщением
Replace with bullets -
Перейди назад на ветку
master -
Замени содержимое
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` — вывести историю всех коммитов в виде дерева
- Закоммить изменения с сообщением
show command for commit.md - Открой Git Graph. Обрати внимание, что история коммитов стала похожа на дерево, а на концах веток этого дерева расположены
метки
master,branch-feature,bullet-feature. А вот тегv0.1, остался на своем месте.
Правильное дерево коммитов для этого этапа
- Начни вливать
bullet-featureвmaster: Убедись чтоHEADнаходится наmasterи выполни командуgit merge bullet-feature.
Эта команда вливает указанную ветку в текущую (в ту, на которой сейчас находится HEAD).
Выполнение Merge закончится конфликтом.
Конфликт произошел, потому что в этот файл вносились изменения и в bullet-feature и в master.
- В VS Code открой вкладку Source Control.
В списке
Merge Changesбудет файл —commit.md. Выбери его.
Часто конфликты разрешаются выбором варианта из одной из веток, но это не тот случай.
В VS Code нажми Compare Changes и убедись, что поменялось все. Придется объединять изменения аккуратно вручную.
Сначала выбери Accept Both Changes — теперь текст обоих изменений станет доступен для редактирования.
Затем напиши правильную версию блока. В ней должна быть команда git show и перед каждой командой должны быть дефисы.
Когда закончишь редактирование, сохрани изменения и добавь commit.md в Commit Index: git add commit.md
-
Выполни
git status. Вывод сообщит, что все конфликты разрешены. Можно коммитить: выполни командуgit commit(без опции-m). В VS Code откроется редактор сообщения коммита. Будет указано хорошее подробное сообщение: его можно не менять. Чтобы завершить коммит, достаточно закрыть в редакторе открывшийся файлCOMMIT_EDITMSG(Ctrl + F4на Windows,Ctrl + Wна Linux,Cmd + Wна Mac). -
Убедись, что в результате твоих действий был создан новый коммит, объединяющий две ветви изменений.
HEADсдвинулся на него, аmasterсдвинулся заHEAD.
Задание 6. Hidden Conflict
-
Начни вливать
branch-featureвmaster, как и в прошлый раз. Конфликтов в этот раз не будет, поэтому шаг разрешения конфликтов будет пропущен. Таким образом слияние будет выполнено. -
Хоть «настоящих» конфликтов нет, после слияния появился «логический» конфликт. Дело в том, что файл
branch.mdдо сих пор содержит нумерованный список. Замени числа в нем на дефисы, аналогично другим файлам. -
Теперь пришло время добавить в историю эти изменения. Простой способ это сделать — коммит с сообщением вида
Fix after merge. Прекрасно работает. Но можно воспользоватьсяAmmend Commit. Эта команда позволяет дополнить последний коммит дополнительными изменениями:git commit --amendДобавь изменения файлаbranch.mdвCommit indexи выполниAmend commit.
- Создай ветку
merge-featureи перейди на нее - Создай файл
merge.mdсо следующим содержимым:
## A1. Merge Them All
### Два состояния можно объединить через merge, mergetool и commit
- `git merge <commit>` — объединить текущую ветку с другой
- `git mergetool` — разрешить имеющиеся конфликты
- Закоммить изменения с сообщением
Add merge.md - Перейди назад на ветку
master - Влей
merge-featureвmaster - Заметь, что в этот раз не только конфликтов не было, но и новый коммит не был создан.
Потому что в
masterне было изменений и для объединения двух веток было достаточно передвинутьmasterна коммит, на который ссылаласьmerge-feature.
Правильное дерево коммитов для этого этапа
- Создай ветку
rebase-featureи перейди на нее. - Создай файл
rebase.mdсо следующим содержимым:
## A2. Immutable History
### Нельзя переписать историю — можно создать новую
- `git commit --ammend` — заменить последний коммит ветки на отредактированный с дополнительными изменениями
- `git rebase <upstream>` — применить все коммиты от общего родителя до текущего к `<upstream>`
- `git rebase -i <upstream>` — применить заново все коммиты, указав действие с каждым коммитом
- `git cherry-pick <commit>` — применить указанный коммит к HEAD
- Закоммить изменения с сообщением
Add rebase.md - Создай файл
reflog.mdсо следующим содержимым:
## A4. Hide The Garbage
### Видно только то, на что есть ссылки
- `git gc` — удалить ненужные файлы и оптимизировать локальный репозиторий
- `git clean` — удалить неотслеживаемые файлы из директории
- `git reflog show <ref>` — показать лог действий со ссылкой
- `git reflog` = `git reflog show HEAD` — показать лог действий с HEAD
-
Закоммить изменения с сообщением
Add reflog.md. -
Перейди на ветку
master. -
Создай файл
reflog.mdсо следующим содержимым:
## A4. Hide The Garbage
### Lorem ipsum dolor sit amet, consectetur adipiscing elit
-
Закоммить изменения с сообщением
Add stub for reflog.md. -
Установи тег
old-rebase-featureна коммит, на который ссылаетсяrebase-feature:
git tag old-rebase-feature rebase-feature
В этой команде первый аргумент - имя тега, а второй - идентификатор коммита. В качестве идентификатора коммита можно передать его хэш или ветку, которая на него указывает
-
Перейди на ветку
rebase-feature -
Выполни rebase
rebase-featureнаmaster: убедись чтоHEADуже находится наrebase-featureи выполни командуgit rebase master. При rebase возникнет конфликт. -
Первый коммит
Add rebase.mdуспешно скопирован, а вотAdd reflog.mdпо понятным причинам порождает конфликты. Открой вкладку Source Control в VS Code. Несмотря на то, что файлы были созданы в разных ветках, Git видит, что первые строчки совпадают и по ним конфликта нет. А вот оставшиеся строчки конфликтуют. Так как в веткеrebase-featureбыл правильный текст, нажмиAccept Incoming Change. Добавьreflog.mdв Commit Index и выполни командуgit rebase --continue. Раз оба коммита были успешно скопированы, rebase на этом будет закончен. -
Обрати внимание, что в результате rebase были созданы коммиты
Add rebase.mdиAdd reflog.md. Хоть они похожи на исходные, все же это новые коммиты с новыми ревизиями. Веткаrebase-featureбыла перемещена и теперь ссылается на новый коммит. Старые коммиты остались в репозитории и на последний из них все еще ссылается тегold-rebase-feature. -
Перейди на ветку
masterи влей в него изменения изrebase-feature. Это будет fast-forward merge.
-
Удали тег
old-rebase-featureс помощью командыgit tag -d old-rebase-feature. Коммит, на который он ссылался будет скрыт, но продолжит существовать в репозитории. -
Выполни команду
git reflog -15
Опция -15 указывает лимит количества действий в рефлоге: будут показаны только последние 15 действий.
- В результате ты увидишь список коммитов, по которым передвигался
HEAD. Найди в списке действиеcommit: Add reflog.mdи скопируй хэш коммита. - Перейди на этот коммит:
git checkout COMMIT_HASH - Убедись, что скрытый коммит найден и снова виден. По крайней мере пока на него ссылается
HEAD. - Перейди на
master
- Добавь новый репозиторий для синхронизации: https://github.com/kontur-courses/git-sheet-ext
git remote add ext https://github.com/kontur-courses/git-sheet-extУбедись, что удаленный репозиторий был добавлен:git remote -v - Выполни fetch репозитория:
git fetch ext - Убедись, что в истории появилась ветка
ext/sheet-featureиз удаленного репозитория, а также несколько новых коммитов.
- Выполни checkout на ветку
ext/sheet-feature:git checkout sheet-feature
Git автоматически создаст локальную ветку с именем sheet-feature, которая будет указывать на тот же коммит, что и ext/sheet-feature.
В удаленную ветку нельзя коммитить, поэтому создание локальной ветки чаще всего необходимо. Но не обязательно: можно просто перейти на коммит, на который указывает удаленная ветка.
- Выполни интерактивный rebase
sheet-featureнаmaster:git rebase -i master - В текстовом редакторе описан сценарий действий для rebase. Сейчас он заключается в том, что надо взять
и переместить на новое место все коммиты последовательно: сначала первый, затем второй и т.д. Все как обычно.
Ниже сценария приведены комментарии по возможным действиям с коммитами.
Прочитай, что делает
reword,squashиfixup. - В первой строчке файла замени
pickнаreword, а последующих строчках замениpickнаfixup. Сохрани изменения и закрой открывшийся файл (Ctrl + F4на Windows,Ctrl + Wна Linux,Cmd + Wна Mac). Редактор откроется снова и в нем надо будет ввести новое сообщение дляSheet markup. Введи в качестве сообщенияExtensionи закрой файл. - Убедись, что ветка
sheet-featureтеперь ссылается на новый коммит с названиемExtension. А внутри этого коммита объединены все изменения скопированных коммитов. - Перейди на ветку
masterи влей в него изменения изsheet-feature. Это будет fast-forward merge. - Удали ветку
sheet-feature:git branch -D sheet-feature
Правильное дерево коммитов для этого этапа
- Создай новый файл
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` — добавить изменения из текущей локальной ветки и переместить соответствующую ветку удаленного репозитория
-
Закоммить изменения с сообщением
Add push.md -
Сделай push локальной ветки
masterвmasterизoriginс помощьюgit push -
Замени содержимое
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>` — удалить ветку в удаленном репозитории
- Закоммить изменения с опцией
--amend(Amend commit), чтобы не создавать лишний коммит. - Обрати внимание, что старый коммит остался видимым, ведь на него ссылается
origin/master. - Если сейчас выполнить push, то он завешится ошибкой, т.к. навозможно продвинуть
origin/masterвперед по истории так, чтобы он стал ссылаться на коммит, на который ссылаетсяmaster. Поэтому выполни push с опцией --force:git push --force
- Создай ветку
upstream-featureи перейди на нее - Создай новый файл
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 и выше
- Закоммить изменения с сообщением
Add upstream.md - Начни делать push этой ветки.
git pushне сработает потому что ветки в удаленном репозитории еще нет. Чтобы она появилась, нужно выполнить командуgit push -u origin upstream-feature:upstream-feature. Но Git поймет и более краткие варианты:git push -u origin upstream-feature,git push -u origin HEAD. Выполни push любым из этих способов.
- Перейди на ветку
master. - Создай ветку
reset-featureи перейди на нее - Создай новый файл
reset.mdсо следующим содержимым:
## A3. Reset The Difference
### Хранятся файлы, разница вычисляется на лету
-
Закоммить изменения с сообщением
Add reset.md -
Замени содержимое
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` — показать список сохраненных наборов изменений
-
Ты не влил
upstream-featureвmaster, поэтому придется прервать работу. Выполни командуgit stashОбрати внимание, что в Working Directory изменения пропали. -
Перейди на ветку
master, влей в нее веткуupstream-feature, сделай push. -
Перейди назад на ветку
reset-feature. -
Верни изменения из stash. Для этого выполни команду
git stash apply.
Apply не удаляет сохраненные изменения из stash. Если хочется применить изменения и тут же их удалить, то вместо apply надо использовать команду git stash pop
- Закоммить изменения с сообщением
Change reset.md - Похоже разработка закончена, поэтому можно влить в нее
masterи отдать в тестирование. Влейmaster.
-
К сожалению ты забыл добавить некоторые изменения в
reset-feature. Придется отменить merge. Хорошо, что ещеreset-featureне запушен. -
В Git Graph найди коммит
Change reset.md, выбери его и с помощью контекстного меню выполниCopy commit hash to clipboard. Хэш коммита будет скопирован в буфер обмена. После этого выполниgit reset --hard COPIED_COMMIT_HASH -
Замени содержимое
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 из настроек
- Закоммить изменения с сообщением
Change reset.md again - Снова влей
masterвreset-feature, чтобы в ней были все актуальные изменения. - Перейди в
master. Пришло время запушить последнуюю версию. Для этого влейreset-featureвmasterи сделай push. Так как вmasterне произошло изменений с последнего влитияmasterвreset-feature, это будет fast-forward merge.
- Найди в Git Graph начальный коммит
Initial commit, выбери его и с помощью контекстного меню выполниReset current branch to this Commit. В открывшемся диалоговом окне выбери вариантSoftи выполниreset. - Создай ветку
solvedи перейди на нее - Закоммить изменения с сообщением
Solved - Сделай push