-
Создай папку
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