-
Создай папку
my-test-project -
Создай внутри файл
hello.txt -
Открой терминал Git Bash для Windows. Выполни команду
cd путь_до_папки_my-project. -
Убедись что путь введен правильно: команда
pwdдолжна вывести правильный путь до папкиmy-test-project -
Выполни команду
git init -
Убедись, что появилась скрытая папка
.git
Для Windows: чтобы отображались скрытые файлы и папки, в Проводнике нужно отметить галочку Вид / Скрытые элементы.
Лучше рядом также отметить галочку Расширения имен файлов.
Для Mac: чтобы отображались скрытые файлы и папки, нужно в Finder нажать Cmd + Shift + .
Также можно просмотреть список файлов и папок в текущей директории из консоли с помощью команды ls -la
- Удали папку
my-test-project, она дальше не понадобится
- Найди в GitHub репозиторий https://github.com/kontur-courses/git-rules, сделай его fork в свой профиль, а затем склонируй репозиторий, полученный после форка.
НЕ СПУТАЙ: это НЕ репозиторий с презентацией и текстом этого задания!
Склонировать репозиторий можно с помощью команды git clone.
Адрес репозитория можно узнать, нажав на зеленую кнопку «Code» на странице репозитория.
НЕ СПУТАЙ: если ты клонируешь репозиторий, у которого в адресе есть kontur-courses, то ты забыл сделать форк!
Если настраивал SSH для GitHub, то в меню, открывшемся после нажатия на кнопку,
выбери вкладку SSH и используй адрес из этой вкладки!
Не забудь после этого перейти в папку с репозиторием в терминале: cd git-rules.
-
В склонированной папке найди файлы
apply-gitconfig-for-win.cmdиapply-gitconfig-for-nix.sh. Файлapply-gitconfig-for-win.cmdподключает к конфигурации репозитория настройки для Windows, а файлapply-gitconfig-for-nix.shподключает настройки для Linux и Mac. В зависимости от своей операционной системы, выполни один из файлов. Если на Linux или Mac не хватает прав, то выполни в терминалеsh apply-gitconfig-for-nix.sh. Подключение этих файлов позволит настроить Git в этом репозитории для выполнения заданий, при этом твои личные настройки Git не поменяются. -
Открой папку
git-rulesв VS Code (File / Open Folderв главном меню) -
Открой Git Graph (кнопка
Git Graphв нижней панели VS Code). Убедись, что в нем есть коммит с названиемInitial commit.
Также Git Graph можно найти с помощью бокового меню VS Code:

Если Git Graph нет, то возможно это расширение у тебя не установлено.
Открой в VS Code в боковом меню пункт Extensions (Ctrl + Shift + X), найди через поиск расширение «Git Graph» и установи.
История коммитов должна выглядеть так:

- Через VS Code создай файл
init.mdсо следующим содержимым:
## S1. Все локально
#### Все данные хранятся в локальных репозиториях, изменения между ними можно синхронизировать
1. `git init` — создать пустой репозиторий
2. `git clone <url>` — склонировать репозиторий в новую директорию
- Выполни команду
git status. В секцииUntracked filesдолжен находитьсяinit.md, подсвеченный красным цветом.
Консольные команды здесь и далее удобнее выполнять через встроенный в VS Code терминал,
который можно открыть сочетаниемCtrl + `, либо через главное менюView / Terminal
Если git status не показывает изменений, то ты скорее всего забыл сохранить файл, потому что привык работать в IDE, которые делают это за тебя.
VS Code тоже умеет сохранять изменения автоматически: в главном меню открой File и поставь галочку Auto Save.
Если git status все равно не показывает изменения, то проверь имя созданного файла: должно быть init.md.
-
Выполни команду
git add init.md. Теперьinit.mdдолжен находится в Commit Index. -
Выполни
git statusи убедись чтоinit.mdнаходится в секцииChanges to be commitedи подсвечен зеленым цветом
-
Сделай коммит с сообщением
Add init.md. Для этого выполни командуgit commit -m "Add init.md". -
Открой Git Graph и убедись, что коммит появился в истории коммитов
-
Создай файл
commit.mdсо следующим содержимым:
## S2. Хранятся состояния директории, постепенная сборка коммита
#### Хранятся файлы, разница вычисляется на лету
#### Commit index для сборки коммита
-
Выполни
git statusи убедись чтоcommit.mdне появился в секцииUntracked files, да и самой секции нет. А вместо этого есть сообщение «nothing to commit, working tree clean». А все потому, что есть файл.gitignore, который сейчас заставляет Git игнорировать все файлы с расширением.md, кромеinit.md. -
Удали правило
*.mdиз.gitignoreи сохрани изменения -
Снова выполни
git statusи убедись что.gitignoreиcommit.mdтеперь появились и подсвечены красным -
Добавь все измененные файлы, т.е.
.gitignoreиcommit.md, в Commit Index:git add . -
Выполни
git statusи убедись что.gitignoreиcommit.mdнаходятся в секцииChanges to be commited -
Замени содержимое
commit.mdна следующее:
## S2. Хранятся состояния директории, постепенная сборка коммита
#### Хранятся файлы, разница вычисляется на лету
#### Commit index для сборки коммита
1. `git add .` — добавить все измененные файлы в индекс
2. `git commit -m <msg>` — записать изменения из индекса в репозиторий
3. `git status -sb` — вывести состояние директории и индекса кратко с указанием текущей ветки
4. `git restore .` или `git checkout .` — отменить изменения в директории по индексу
5. `git restore -S .` или `git reset .` — отменить изменения индекса по коммиту (отмена `git add .`)
6. `git rm <filename>` — удалить файл из индекса, чтобы перестать хранить его историю в репозитории
-
Выполни
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находится как в верхнем списке Staged Changes, так и в нижнем списке Changes, причем содержимое у файлов разное и при выбореcommit.mdв нижнем списке показываются отличия от Commit Index, а не предыдущего от коммита -
Выполни коммит с сообщением
Add commit.md header(можешь посмотреть пункт 5, чтобы вспомнить как это делать) -
В истории коммитов (Git Graph) найди только что созданный коммит и убедись, что в него попали только изменения из Commit Index
-
Закоммить оставшиеся в Working directory изменения с сообщением
Change commit.md. Здесь и далее под фразой «закоммить изменения» будет подразумеваться добавление изменений в Commit Index и само выполнение коммита. Если забыл, как добавить файлы в Commit Index — посмотри пункт 11. Если забыл, как сделать коммит — посмотри пункт 5.
Теперь история коммитов должна выглядеть так:

- Создай тег с именем
v0.1с помощью командыgit tag "v0.1"и убедись, что у коммитаChange commit.mdпоявился тег.
Теги также можно создавать в Git Graph с помощью контекстного меню
-
Найди в Git Graph начальный коммит
Initial commit, выбери его и с помощью контекстного меню выполниCheckout... -
Выполни команду
git checkout v0.1, чтобы вернуться обратно на помеченный тегом коммит -
Выполни команду
git checkout master, чтобы вернуться на веткуmasterна том же коммите
Теперь история коммитов должна выглядеть так:

- С помощью VS Code создай новый файл
branch.mdсо следующим содержимым:
## S3. Манипуляции через ссылки, нет ссылки — в мусор
#### HEAD — текущая ссылка, tag — фиксированная ссылка, branch — движущаяся за HEAD ссылка
#### checkout — перемещение на ветку или коммит, reset — перемещение с веткой на коммит
#### Видно то, на что есть ссылки, остальное — мусор
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>` или `git switch --detach <commit|branch>` — переместить HEAD на коммит, причем получится detached HEAD
8. `git checkout <branch>`или `git switch <branch>` — переместить HEAD на ветку
9. `git checkout -b <new_branch>` или `git switch -c <new_branch>` — создать ветку и перейти на нее
10. `git reset --hard <commit>` — переместить HEAD и текущую ветку на `<commit>`
-
Закоммить изменения с сообщением
Add branch.mdНапоминание: сначалаadd, потомcommit -
Ой! Эти же изменения надо было делать в новой ветке! Теперь придется исправлять! Сейчас ветка
masterнаходится на коммитеAdd branch.md, а должна находиться на коммитеChange commit.md. А на коммитеAdd branch.mdдолжна быть новая веткаbranch-feature, которую надо было создать. Открой Git Graph и убедись, что все именно так, как описано, и осознай проблему. -
То, что ветка
branch-featureне была создана сразу — это не проблема. Просто возьми и создай ее на текущем коммите:git branch branch-feature. При этом текущей веткой останетсяmaster. -
Теперь надо вернуть
masterна коммитChange commit.md. С этим может помочь командаreset, которая не просто перемещаетHEAD, но также перемещает ветку, на которуюHEADуказывает. Убедись, что текущая ветка — этоmaster. Если почему-то это не так — надо перейти наmasterи скорее всего начать задание заново. КоммитChange commit.md— это предыдущий коммит от текущего положенияHEAD, поэтому на него можно сослаться по относительному имениHEAD~1. Это удобнее, чем выбирать коммит по хэшу. Так что итоговая команда, которую надо выполнить такая:git reset --hard HEAD~1. Сделай это!
Обычно все же удобнее выполнять команду reset через контекстное меню Git Graph, ведь можно просто выбрать целевой коммит курсором
-
Теперь
masterна месте и, чтобы продолжить развиватьbranch-feature, надо было бы перейти на нее командойgit checkout branch-feature. Но делать это не надо, ведь сейчас надо будет сделать новую фичу в новой ветке относительноmaster. -
Создай новую ветку
bullet-featureи перейди на нее:git checkout -b bullet-feature
Команда git checkout -b <branch-name> создает новую ветку и сразу выполняет checkout на нее. Это эквивалентно паре команд git branch <branch-name> и git checkout <branch-name>
- Во всех доступных md-файлах замени нумерованные списки на ненумерованные списки.
На примере
init.mdэто выглядит следующим образом.
Было:
## S1. Все локально
#### Все данные хранятся в локальных репозиториях, изменения между ними можно синхронизировать
1. `git init` — создать пустой репозиторий
2. `git clone <url>` — склонировать репозиторий в новую директорию
Стало:
## S1. Все локально
#### Все данные хранятся в локальных репозиториях, изменения между ними можно синхронизировать
- `git init` — создать пустой репозиторий
- `git clone <url>` — склонировать репозиторий в новую директорию
Аналогично сделай для commit.md.
-
Закоммить изменения с сообщением
Replace with bullets(ты же помнишь про добавление файлов Commit Index?) -
Перейди назад на ветку
master(если забыл как, то посмотри как переходил на ветку в «Задание 4. Tag») -
Замени содержимое
commit.mdна следующее:
## S2. Хранятся состояния директории, постепенная сборка коммита
#### Хранятся файлы, разница вычисляется на лету
#### Commit index для сборки коммита
1. `git add .` — добавить все измененные файлы в индекс
2. `git commit -m <msg>` — записать изменения из индекса в репозиторий
3. `git status -sb` — вывести состояние директории и индекса кратко с указанием текущей ветки
4. `git restore .` или `git checkout .` — отменить изменения в директории по индексу
5. `git restore -S .` или `git reset .` — отменить изменения индекса по коммиту (отмена `git add .`)
6. `git rm <filename>` — удалить файл из индекса, чтобы перестать хранить его историю в репозитории
7. `git show <commit>` — показать содержимое коммита
8. `git log --oneline --decorate --graph` — вывести историю коммитов от HEAD в виде дерева
9. `git log --oneline --decorate --graph --all` — вывести историю всех коммитов в виде дерева
10. `gitk` — открыть графическое представление репозитория
11. `git clean` — удалить неотслеживаемые файлы из директории
-
Закоммить изменения с сообщением
New commands for commit.md(последнее напоминание: Commit Index!) -
Открой Git Graph. Обрати внимание, что история коммитов стала похожа на дерево, а на концах веток этого дерева расположены метки
master,branch-feature,bullet-feature. А вот тегv0.1, остался на своем месте.
Теперь история коммитов должна выглядеть так:

- Начни вливать
bullet-featureвmaster. Для этого сначала убедись, чтоHEADнаходится наmaster, а затем выполни командуgit merge bullet-feature.
Эта команда вливает указанную ветку в текущую (в ту, на которой сейчас находится HEAD)
Выполнение Merge закончится конфликтом в файле commit.md.
Конфликт произошел, потому что в этот файл вносились изменения и в bullet-feature и в master.
- Открой в VS Code в боковом меню пункт Source Control.
В спискеMerge Changesбудет файл —commit.md. Выбери его.
Часто конфликты разрешаются выбором варианта из одной из веток, но это не тот случай. Придется объединять изменения аккуратно вручную.
Сначала выбери Accept Both Changes — теперь текст обоих изменений станет доступен для редактирования.
Затем напиши правильную версию блока. В ней должна быть команды git show, git log и другие, причем перед каждой командой должны быть дефисы.
Когда закончишь редактирование, сохрани изменения и добавь commit.md в Commit Index: git add commit.md
-
Выполни
git status. Вывод сообщит, что все конфликты разрешены. Можно коммитить: выполни командуgit commit(без опции-m). В VS Code откроется редактор сообщения коммита. Будет указано хорошее сообщение: его можно не менять. Чтобы завершить коммит, достаточно закрыть в редакторе открывшийся файлCOMMIT_EDITMSG. -
Убедись, что в результате твоих действий был создан новый коммит, объединяющий две ветви изменений.
HEADсдвинулся на него, аmasterсдвинулся заHEAD.
Теперь история коммитов должна выглядеть так:

Задание 7. Hidden Conflict
-
Начни вливать
branch-featureвmaster, как и в прошлый раз. Конфликтов в этот раз не будет, поэтому шаг разрешения конфликтов будет пропущен. Таким образом слияние будет выполнено. -
Хоть «настоящих» конфликтов нет, после слияния появился «логический» конфликт. Дело в том, что файл
branch.mdдо сих пор содержит нумерованный список. Замени числа в нем на дефисы, аналогично другим файлам. -
Теперь пришло время добавить в историю эти изменения. Но чтобы было понятно, что эти изменения относятся к слиянию, хочется их добавить не в новый коммит, а в предыдущий. Это можно сделать с помощью
Amend Commit. Эта команда позволяет дополнить последний коммит дополнительными изменениями:git commit --amend. Добавь изменения файлаbranch.mdв Commit Index (важно, иначе предыдущий коммит будет нечем дополнять!) и выполниAmend commit. Во время выполненияAmend commitоткроется текстовый редактор с сообщением предыдущего коммита. Это позволяет изменить сообщение коммита при желании. Но в данном случае сообщение из предыдущего коммита подходит, поэтому просто закрой текстовый редактор. После этогоAmend Commitбудет завершен.
Теперь история коммитов должна выглядеть так:

-
Создай ветку
merge-featureи перейди на нее -
Создай файл
merge.mdсо следующим содержимым:
## A1. Трехсторонний merge в три шага
#### Два состояния можно объединить через merge, mergetool и commit
#### Участвуют три стороны: current, incoming и base
- `git merge <commit>` — объединить текущую ветку с другой
- `git mergetool` — разрешить имеющиеся конфликты
- `git merge --abort` — отменить слияние
-
Закоммить изменения с сообщением
Add merge.md -
Перейди назад на ветку
master -
Влей
merge-featureвmaster -
Заметь, что в этот раз не только конфликтов не было, но и новый коммит не был создан. Потому что в
masterне было изменений и для объединения двух веток было достаточно передвинутьmasterна коммит, на который ссылаласьmerge-feature.
Теперь история коммитов должна выглядеть так:

-
Создай ветку
rebase-featureи перейди на нее -
Создай файл
rebase.mdсо следующим содержимым:
## A2. rebase, cherry-pick и amend, чтобы пересоздать историю
#### Нельзя переписать историю — можно создать новую
- `git commit --amend --no-edit` — заменить последний коммит ветки на отредактированный с дополнительными изменениями без изменения сообщения
- `git rebase <upstream>` — применить все коммиты от общего родителя до текущего к `<upstream>`
- `git rebase -i <upstream>` — применить заново все коммиты, указав действие с каждым коммитом
- `git rebase --continue` — продолжить rebase после разрешения конфликтов
- `git rebase --abort` — отменить rabase
- `git cherry-pick <commit>` — применить указанный коммит к HEAD
-
Закоммить изменения с сообщением
Add rebase.md -
Замени содержимое
branch.mdна следующее:
## S3. Манипуляции через ссылки, нет ссылки — в мусор
#### HEAD — текущая ссылка, tag — фиксированная ссылка, branch — движущаяся за HEAD ссылка
#### checkout — перемещение на ветку или коммит, reset — перемещение с веткой на коммит
#### Видно то, на что есть ссылки, остальное — мусор
- `git tag` — вывести список тегов
- `git tag <tagname>` — создать тег
- `git branch` — вывести список локальных веток
- `git branch -av` — вывести список локальных и удаленных веток
- `git branch <branchname>` — создать ветку
- `git branch -d <branchname>` — удалить ветку
- `git checkout <commit>` или `git switch --detach <commit>` — переместить HEAD на коммит, причем получится detached HEAD
- `git checkout <branch>`или `git switch <branch>` — переместить HEAD на ветку
- `git checkout -b <new_branch>` или `git switch -c <new_branch>` — создать ветку и перейти на нее
- `git reset --hard <commit>` — переместить HEAD и текущую ветку на `<commit>`
- `git reflog show <ref>` — показать лог действий со ссылкой
- `git reflog` = `git reflog show HEAD` — показать лог действий с HEAD
- `git gc` — удалить ненужные файлы и оптимизировать локальный репозиторий
-
Закоммить изменения с сообщением
Change branch.md -
Перейди на ветку
master -
Замени содержимое
branch.mdна следующее:
## S3. Манипуляции через ссылки, нет ссылки — в мусор
#### HEAD — текущая ссылка, tag — фиксированная ссылка, branch — движущаяся за HEAD ссылка
#### checkout — перемещение на ветку или коммит, reset — перемещение с веткой на коммит
#### Видно то, на что есть ссылки, остальное — мусор
- `git tag` — вывести список тегов
- `git tag <tagname>` — создать тег
- `git branch` — вывести список локальных веток
- `git branch -av` — вывести список локальных и удаленных веток
- `git branch <branchname>` — создать ветку
- `git branch -d <branchname>` — удалить ветку
- `git checkout <commit>` или `git switch --detach <commit>` — переместить HEAD на коммит, причем получится detached HEAD
- `git checkout <branch>`или `git switch <branch>` — переместить HEAD на ветку
- `git checkout -b <new_branch>` или `git switch -c <new_branch>` — создать ветку и перейти на нее
- `git reset --hard <commit>` — переместить HEAD и текущую ветку на `<commit>`
### Lorem ipsum dolor sit amet, consectetur adipiscing elit
-
Закоммить изменения с сообщением
Add reflog stub to branch.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успешно скопирован, а вотChange branch.mdпо понятным причинам порождает конфликты. Открой в VS Code в боковом меню пункт Source Control. Несмотря на то, что файлы были созданы в разных ветках, Git видит, что первые строчки совпадают и по ним конфликта нет. А вот оставшиеся строчки конфликтуют. Так как в веткеrebase-featureбыл правильный текст, нажмиAccept Incoming Change. Добавьbranch.mdв Commit Index и выполни командуgit rebase --continue. Раз оба коммита были успешно скопированы, rebase на этом будет закончен. Фанфар по этому поводу не будет. В терминале просто появится сообщение «Applying: Change branch.md» без каких-либо ошибок после. -
Обрати внимание, что в результате rebase были созданы коммиты
Add rebase.mdиChange branch.md. Хоть они похожи на исходные, все же это новые коммиты с новыми ревизиями. Веткаrebase-featureбыла перемещена и теперь ссылается на новый коммит. Старые коммиты остались в репозитории и на последний из них все еще ссылается тегold-rebase-feature. -
Перейди на ветку
masterи влей в него изменения изrebase-feature. Влитие получится в режиме fast-forward.
Теперь история коммитов должна выглядеть так:

-
Удали тег
old-rebase-featureс помощью командыgit tag -d old-rebase-feature. Коммит, на который он ссылался, будет скрыт, но продолжит существовать в репозитории. -
Выполни команду
git reflog -50
Опция -50 указывает лимит количества действий в рефлоге: будут показаны только последние 50 действий.
Результат команды можно скроллить с помощью стрелок «Вверх» и «Вниз».
Когда захочешь закрыть список — нажми q.
-
В результате ты увидишь список коммитов, по которым передвигался
HEAD. Найди в списке действиеcommit: Change branch.mdи скопируй хэш коммита в буфер обмена. -
Перейди на этот коммит, подставив вместо
COPIED_COMMIT_HASHскопированный хэш:git checkout COPIED_COMMIT_HASH -
Убедись, что скрытый коммит найден и снова виден. По крайней мере пока на него ссылается
HEAD.
Теперь история коммитов должна выглядеть так:

- Перейди на
master
Теперь история коммитов должна выглядеть так:

-
Добавь новый репозиторий https://github.com/kontur-courses/git-rules-ext для синхронизации:
git remote add ext https://github.com/kontur-courses/git-rules-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. Сейчас он заключается в том, что надо взять (
pick) и переместить на новое место все коммиты последовательно: сначала первый, затем второй и т.д. Все как обычно. Ниже сценария приведены комментарии по возможным действиям с коммитами. Прочитай, что делаетreword,squashиfixup. -
В первой строчке файла замени
pickнаreword, а последующих строчках замениpickнаfixup. Сохрани изменения и закрой файл со сценарием. После этого сценарий начнет выполняться. -
Сразу же редактор откроется снова, потому что команде
rewordтребуется новое сообщение для коммита. В открывшемся редакторе замени текущее сообщениеSheet markupна новое сообщениеExtensionи закрой редактор. -
Убедись, что ветка
sheet-featureтеперь ссылается на новый коммит с названиемExtension. А внутри этого коммита объединены все изменения скопированных коммитов. -
Перейди на ветку
masterи влей в него изменения изsheet-feature. Влитие получится в режиме fast-forward. -
Удали ветку
sheet-feature. Это придется сделать с force, потому что эта ветка связана сext/sheet-feature, которая вmasterне влита. Force обозначается-Dвместо-dв команде. Выполни «усиленное» удаление:git branch -D sheet-feature
Теперь история коммитов должна выглядеть так:

-
Надо достать для ветки
masterизменения из коммитаAdd runnerиз веткиsolved. В этом случае нужен только один коммит, который находится между другими — значит подойдетcherry-pick. Достань эту вишенку следующей командой:git cherry-pick runner. Команда сработает, т.к. коммитAdd runnerпомечен тегомrunner. -
Убедись, что в ветке
masterпоявилась копия коммитаAdd runner.
Теперь история коммитов должна выглядеть так:

- Создай новый файл
push.mdсо следующим содержимым:
## R2. Удаленное изменение — это 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. Удаленное изменение — это push
- `git push <remote> <local_branch>:<remote_branch>` — добавить изменения из локальной ветки `<local_branch>` и переместить ветку `<remote_branch>` удаленного репозитория
- `git push` = `git push origin HEAD` — добавить изменения из текущей локальной ветки и переместить соответствующую ветку удаленного репозитория
- `git push -f` — выполнить `push`, даже если удаленная ветка уже не является предком
- `git push --force-with-lease` — выполнить `push`, если является предком или удаленная ветка не сдвигалась (использовать вместо предыдущей команды)
- `git push <remote> -d <branch|tag>` — удалить ветку или тег в удаленном репозитории
- `git push <remote> tag <tag>` — отправить тег в удаленный репозиторий
- `git push <remote> --tags` — отправить все локальные теги в удаленный репозиторий
- `git push --mirror` — выполнить агрессивный `push` для всех тегов, веток и HEAD, подходит для создания удаленной копии локального репозитория
-
Добавь изменения в Commit Index, а затем выполни
Amend commit, чтобы не создавать лишний коммит. Если забыл какой командой делатьAmend commit, то поищи по слову amend в предыдущих заданиях. -
Обрати внимание, что старый коммит остался видимым, ведь на него ссылается
origin/master
Теперь история коммитов должна выглядеть так:

- Если сейчас выполнить push, то он завешится ошибкой, т.к. навозможно продвинуть
origin/masterвперед по истории так, чтобы он стал ссылаться на коммит, на который ссылаетсяmaster. Поэтому выполни push с опцией force-with-lease:git push --force-with-lease.
Теперь история коммитов должна выглядеть так:

-
Создай ветку
upstream-featureи перейди на нее -
Создай новый файл
upstream.mdсо следующим содержимым:
## R3. Явное сопоставление локальных веток с upstream
- `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 pull --rebase --autostash` — сохранить локальные изменения, получить содержимое, выполнить 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. stash, reset, revert для управления изменениями
#### Изменения можно временно припрятать
#### Можно получить разницу между любыми коммитами
#### Коммит можно отменить другим коммитом
-
Закоммить изменения с сообщением
Add reset.md -
Замени содержимое
reset.mdна следующее:
## A3. stash, reset, revert для управления изменениями
#### Изменения можно временно припрятать
#### Можно получить разницу между любыми коммитами
#### Коммит можно отменить другим коммитом
- `git stash` — сохранить все модифицированные файлы в виде набора изменений
- `git stash pop` — восстановить последний сохраненный набор изменений и удалить его из списка
- `git stash list` — показать список сохраненных наборов изменений
- `git reset --hard <commit>` — переместить текущую ветку на `<commit>`, задать индекс и директорию согласно коммиту, устранив всю разницу
- `git reset --mixed <commit>` — переместить текущую ветку на `<commit>`, задать индекс согласно коммиту, оставить разницу между исходным и новым состоянием в директории
- `git reset --soft <commit>` — переместить текущую ветку на `<commit>`, не задавать индекс и директорию согласно коммиту, а оставить разницу между исходным и новым состоянием в индексе и директории
- `git reset --hard HEAD~1` — отменить последний коммит
- `git revert <commit>` — создать коммит, отменяющий изменения из коммита
-
Ты не влил
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 -
Похоже разработка в ветке
reset-featureзакончена, поэтому можно влить в нее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. stash, reset, revert для управления изменениями
#### Изменения можно временно припрятать
#### Можно получить разницу между любыми коммитами
#### Коммит можно отменить другим коммитом
- `git stash` — сохранить все модифицированные файлы в виде набора изменений
- `git stash pop` — восстановить последний сохраненный набор изменений и удалить его из списка
- `git stash list` — показать список сохраненных наборов изменений
- `git reset --hard <commit>` — переместить текущую ветку на `<commit>`, задать индекс и директорию согласно коммиту, устранив всю разницу
- `git reset --mixed <commit>` — переместить текущую ветку на `<commit>`, задать индекс согласно коммиту, оставить разницу между исходным и новым состоянием в директории
- `git reset --soft <commit>` — переместить текущую ветку на `<commit>`, не задавать индекс и директорию согласно коммиту, а оставить разницу между исходным и новым состоянием в индексе и директории
- `git reset --hard HEAD~1` — отменить последний коммит
- `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.
Теперь история коммитов должна выглядеть так:

-
Создай ветку
solvedи перейди на нее -
Найди в Git Graph начальный коммит
Initial commit, выбери его и с помощью контекстного меню выполниReset current branch to this Commit. В открывшемся диалоговом окне выбери вариантSoftи выполниreset. -
Все изменения уже в Commit Index. Поэтому просто закоммить их с сообщением
Solved -
Сделай push, чтобы получить подсказку как сделать push с upstream, а затем сделай push с upstream




