-
Создай папку
my-test-project
-
Создай внутри файл
hello.txt
-
Выполни в контекстном меню папки
my-test-project
командуGitExt Create new repository
-
Убедись, что появилась скрытая папка
.git
Для Windows: чтобы отображались скрытые файлы и папки, в Проводнике нужно отметить галочку Вид / Скрытые элементы
.
Лучше рядом также отметить галочку Расширения имен файлов
.
-
Выполни в контекстном меню папки
my-test-project
командуGitExt Open repository
. Пока в репозитории пусто. Так и должно быть. -
Удали папку
my-test-project
, она дальше не понадобится
- Найди в GitHub репозиторий https://github.com/kontur-courses/git-rules, сделай его fork в свой профиль, а затем склонируй репозиторий, полученный после форка.
НЕ СПУТАЙ: это НЕ репозиторий с презентацией и текстом этого задания!
Адрес репозитория можно узнать, нажав на зеленую кнопку «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 status
все равно не показывает изменения, то проверь имя созданного файла: должно быть init.md
.
-
Открой папку
git-rules
в VS Code (File / Open Folder
в главном меню) -
Открой репозиторий с помощью контекстного меню Проводника. Убедись, что в нем есть коммит с названием
Initial commit
.
История коммитов должна выглядеть так:
- Через VS Code создай файл
init.md
со следующим содержимым:
## S1. Все локально
#### Все данные хранятся в локальных репозиториях, изменения между ними можно синхронизировать
1. `git init` — создать пустой репозиторий
2. `git clone <url>` — склонировать репозиторий в новую директорию
-
Нажми кнопку
Commit
, чтобы открыть окно коммита -
Переведи
init.md
из верхней части в нижнюю часть окна кнопкойStage
либо двойным нажатием по имени файла. Теперьinit.md
находится вCommit index
.
Если Git Extensions не показывает изменений, то ты скорее всего забыл сохранить файл, потому что привык работать в IDE, которые делают это за тебя.
VS Code тоже умеет сохранять изменения автоматически: в главном меню открой File
и поставь галочку Auto Save
.
Если Git Extensions все равно не показывает изменения, то проверь имя созданного файла: должно быть init.md
.
-
Введи в качестве сообщения к коммиту
Add init.md
и сделай коммит кнопкойCommit
-
Убедись, что коммит появился в истории коммитов
-
Создай файл
commit.md
со следующим содержимым:
## S2. Хранятся состояния директории, постепенная сборка коммита
#### Хранятся файлы, разница вычисляется на лету
#### Commit index для сборки коммита
-
Выбери в истории коммитов
Working directory
и убедись, что там не появились изменения в файлеcommit.md
. А все потому что есть файл.gitignore
, который сейчас заставляет Git игнорировать все файлы с расширением.md
, кромеinit.md
. -
Удали правило
*.md
из.gitignore
и сохрани изменения -
Снова выбери в истории коммитов
Working directory
и убедись, что там теперь есть изменения в файлах.gitignore
иcommit.md
-
Открой окно коммита и переведи
.gitignore
иcommit.md
вCommit index
и закрой окно коммита -
Выбери в истории коммитов
Commit index
и убедись, что измененные файлы.gitignore
иcommit.md
теперь находится там -
Замени содержимое
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>` — удалить файл из индекса, чтобы перестать хранить его историю в репозитории
-
Посмотри историю коммитов. Убедись, что
commit.md
изменен как в вWorking directory
, так и вCommit index
-
Открой окно коммита и убедись, что
commit.md
находится как в верхней части окна, так и в нижней, причем содержимое у файлов разное и при выбореcommit.md
в верхней части показывается отличия отCommit index
, а не предыдущего коммита -
Выполни коммит с сообщением
Add commit.md header
-
В истории коммитов найди только что созданный коммит и убедись, что в него попали только изменения из
Commit index
-
Закоммить оставшиеся в
Working directory
изменения с сообщениемChange commit.md
. Здесь и далее под фразой «закоммить изменения» будет подразумеваться добавление изменений вCommit index
и само выполнение коммита.
Теперь история коммитов должна выглядеть так:
-
Выбери в дереве коммитов последний коммит и создай в нем тег
v0.1
с помощью контекстного меню -
Перейди на
Initial commit
с помощью командыCheckout this commit
в контекстном меню -
Используй пункт главного меню
Commands / Checkout revision
, чтобы вернуться обратно на помеченный тегом коммит. Для этого введи имя тегаv0.1
в поле для ввода ревизии. -
Выполни
Checkout branch
на веткуmaster
с помощью контекстного меню на текущем коммите
Теперь история коммитов должна выглядеть так:
- Создай новый файл
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
-
Ой! Эти же изменения надо было делать в новой ветке! Теперь придется исправлять! Сейчас ветка
master
находится на коммитеAdd branch.md
, а должна находиться на коммитеChange commit.md
. А на коммитеAdd branch.md
должна быть новая веткаbranch-feature
, которую надо было создать. Убедись, что в истории коммитов все именно так, как описано, и осознай проблему. -
То, что ветка
branch-feature
не была создана сразу — это не проблема. Просто возьми и создай новую веткуbranch-feature
с помощью контекстного меню на текущем коммите. Git Extensions автоматически сделает checkout на нее. -
Теперь надо вернуть
master
на коммитChange commit.md
. С этим может помочь командаreset
, которая не просто перемещаетHEAD
, но также перемещает ветку, на которуюHEAD
указывает. Но текущая ветка — этоbranch-feature
, а нужно, чтобы текущей былmaster
. ВыполниCheckout branch
на веткуmaster
с помощью контекстного меню на текущем коммите. -
Наконец, выбери в истории коммит
Change commit.md
, найди в контекстном меню командуReset current branch to here...
, в открывшемся диалоговом окне выбериHard
, а затемOK
. ПеремещениеHEAD
иmaster
должно произойти. -
Теперь
master
на месте и, чтобы продолжить развиватьbranch-feature
, надо было бы перейти на нее с помощьюCheckout branch
. Но делать это не надо, ведь сейчас надо будет сделать новую фичу в новой ветке относительноmaster
. -
Используя контекстное меню создай ветку
bullet-feature
-
Во всех доступных md-файлах замени нумерованные списки на ненумерованные списки. На примере
init.md
это выглядит следующим образом. Было:
## S1. Все локально
#### Все данные хранятся в локальных репозиториях, изменения между ними можно синхронизировать
1. `git init` — создать пустой репозиторий
2. `git clone <url>` — склонировать репозиторий в новую директорию
Стало:
## S1. Все локально
#### Все данные хранятся в локальных репозиториях, изменения между ними можно синхронизировать
- `git init` — создать пустой репозиторий
- `git clone <url>` — склонировать репозиторий в новую директорию
Аналогично сделай для commit.md
.
-
Закоммить изменения с сообщением
Replace with bullets
-
Перейди назад на ветку
master
, используя контекстное меню -
Замени содержимое
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
-
Обрати внимание, что история коммитов стала похожа на дерево, а на концах веток этого дерева расположены метки
master
,branch-feature
,bullet-feature
. А вот тегv0.1
, остался на своем месте.
Теперь история коммитов должна выглядеть так:
-
Начни вливать
bullet-feature
вmaster
:HEAD
уже находится наmaster
, поэтому укажи наbullet-feature
и с помощью контекстного меню выбериMerge into current branch
. Но выполнениеMerge
закончится конфликтом в файлеcommit.md
. Конфликт произошел, потому что в этот файл вносились изменения и вbullet-feature
и вmaster
. -
Git Extensions предложит сразу перейти ко второй части слияния — разрешению конфликтов. Согласись. Откроется окно
Resolve merge conflicts
со списком файлов с конфликтами. В списке будет только один файл —commit.md
. Конфликт произошел, потому что в этот файл вносились изменения и вbullet-feature
и вmaster
. Нажми на кнопкуOpen in vscode
и в качестве инструмента для объединения изменений откроется VS Code. Часто конфликты разрешаются выбором варианта из одной из веток, но это не тот случай. Придется объединять изменения аккуратно вручную. Сначала выбериAccept Both Changes
— теперь текст обоих изменений станет доступен для редактирования. Затем напиши правильную версию блока. В ней должна быть командаgit show
и перед каждой командой должны быть дефисы. Когда закончишь редактирование сохрани изменения (как обычноCtrl+S
), закрой файл в VS Code (вкладку с файлом или полностью VS Code) и переключись на Git Extensions. Важно! Если вкладку с файлом в VS Code не закрыть, то Git Extensions не будет реагировать, т.к. будет продолжать ждать завершения разрешения конфликтов. -
Git Extensions сообщит, что все конфликты разрешены и предложит перейти к третьей части слияния — коммиту. Согласись. Откроектся знакомое окно коммита, в котором в
Commit index
будут показаны все изменения относительноHEAD
. ВCommit message
будет указано хорошее сообщение: его можно не менять. Закоммить результаты merge. -
Убедись, что в результате твоих действий был создан новый коммит, объединяющий две ветви изменений.
HEAD
сдвинулся на него, аmaster
сдвинулся заHEAD
.
Теперь история коммитов должна выглядеть так:
Задание 7. Hidden Conflict
-
Начни вливать
branch-feature
вmaster
, как и в прошлый раз. Конфликтов в этот раз не будет, поэтому шаг разрешения конфликтов будет пропущен. А еще Git Extensions автоматически сделает commit. Таким образом слияние будет выполнено. -
Хоть «настоящих» конфликтов нет, после слияния появился «логический» конфликт. Дело в том, что файл
branch.md
до сих пор содержит нумерованный список. Замени числа в нем на дефисы, аналогично другим файлам. -
Теперь пришло время добавить в историю эти изменения. Но чтобы было понятно, что эти изменения относятся к слиянию, хочется их добавить не в новый коммит, а в предыдущий. Это можно сделать с помощью
Amend Commit
. Эта команда позволяет дополнить последний коммит дополнительными изменениями. Открой окно коммита, выбери опциюAmend Commit
: вCommit message
появится сообщение из предыдущего коммита, затем добавь вCommit index
файлbranch.md
и сделай 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
и перейди на нее. Используй сочетаниеCtrl+B
, чтобы вызвать диалог создания ветки: так быстрее! -
Создай файл
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
. Воспользуйся сочетаниемCtrl+Space
, чтобы открыть окно коммита: так быстрее! -
Замени содержимое
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
. ИспользуйCtrl+Space
. -
Перейди на ветку
master
. ИспользуйCtrl+.
. -
Замени содержимое
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
. ИспользуйCtrl+Space
. -
Открой в главном меню пункт
Commands
. У большинства команд задано сочетание клавиш. Ты можешь запомнить те из них, которые используешь часто, чтобы применять эти команды быстрее. -
Установи тег
old-rebase-feature
на коммит, на который ссылаетсяrebase-feature
-
Перейди на ветку
rebase-feature
-
Выполни rebase
rebase-feature
наmaster
:HEAD
уже находится наrebase-feature
, поэтому укажи наmaster
и с помощью контекстного меню выбериRebase current branch on
, а затемSelected commit
. При rebase возникнет конфликт. -
Первый коммит
Add rebase.md
успешно скопирован, а вотChange branch.md
по понятным причинам порождает конфликты. Нажми кнопкуSolve conflicts
, чтобы разрешить конфликты в VS Code. Несмотря на то, что файлы были созданы в разных ветках, Git видит, что первые строчки совпадают и по ним конфликта нет. А вот оставшиеся строчки конфликтуют. Так как в веткеrebase-feature
был правильный текст, нажмиAccept Incoming Change
, затем сохрани изменения, закрой файл в VS Code (важно!), перейди в Git Extensions и нажмиContinue rebase
. Раз оба коммита были успешно скопированы, rebase на этом будет закончен. -
Обрати внимание, что в результате rebase были созданы коммиты
Add rebase.md
иChange branch.md
. Хоть они похожи на исходные, все же это новые коммиты с новыми ревизиями. Веткаrebase-feature
была перемещена и теперь ссылается на новый коммит. Старые коммиты остались в репозитории и на последний из них все еще ссылается тегold-rebase-feature
. -
Перейди на ветку
master
и влей в нее изменения изrebase-feature
. Влитие получится в режиме fast-forward.
Теперь история коммитов должна выглядеть так:
-
Удали тег
old-rebase-feature
. Коммит, на который он ссылался будет скрыт, но продолжит существовать в репозитории. -
Выбери пункт главного меню
Commands / Show reflog
. В результате ты увидишь список коммитов, по которым передвигалсяHEAD
. Найди в списке действиеcommit: Change branch.md
и выполниCopy SHA-1
из контекстного меню. Ревизия этого коммита скопируется в буфер обмена. -
Используй пункт главного меню
Commands / Checkout revision
, чтобы перейти на коммит с ревизией из буфера обмена. -
Убедись, что скрытый коммит найден и снова виден. По крайней мере пока на него ссылается
HEAD
.
Теперь история коммитов должна выглядеть так:
- Перейди на
master
Теперь история коммитов должна выглядеть так:
-
Добавь новый репозиторий для синхронизации.
Для этого в меню слева найдиRemotes
и в контекстном меню выбериManage
.
В открывшемся окнеRemote repositories
нажми плюс и введи параметры репозитория.
Name: ext
Url: https://github.com/kontur-courses/git-rules-ext
Сохрани изменения с помощьюSave changes
.
После сохранения Git Extensions сам предложит выполнить fetch из добавленного репозитория. Соглашайся. Если не справился с GUI, то то же самое можно сделать через консоль одной командой:
git remote add ext https://github.com/kontur-courses/git-rules-ext
И убедиться, что удаленные репозиторий был добавлен с помощью командыgit remote -v
-
Для тренировки выполни fetch вручную. Выбери пункт главного меню
Commands / Pull/Fetch
. Откроется диалоговое окноFetch
. В нем в качествеRemote
выбериext
. Также убедись, что вMerge options
выбран пунктDo not merge, only fetch remote changes
. Нажми на кнопкуFetch
, чтобы получить изменения из удаленного репозитория. Так как fetch уже был выполнен ранее, новых изменений не добавится. -
Убедись, что в истории появилась ветка
ext/sheet-feature
из удаленного репозитория, а также несколько новых коммитов.
Теперь история коммитов должна выглядеть так:
-
Выполни
Checkout branch
на веткуext/sheet-feature
. Git Extensions предложить создать связанную локальную ветку с именемsheet-feature
. Согласись на это. В удаленную ветку нельзя коммитить, поэтому создание локальной ветки чаще всего необходимо. Но не обязательно. -
Выполни интерактивный rebase
sheet-feature
наmaster
: укажи наmaster
и с помощью контекстного меню выбериRebase current branch to
, а затемSelected commit interactively
. Откроется текстовый редактор. -
В текстовом редакторе описан сценарий действий для rebase. Сейчас он заключается в том, что надо взять и переместить на новое место все коммиты последовательно: сначала первый, затем второй и т.д. Все как обычно. Ниже сценария приведены комментарии по возможным действиям с коммитами. Прочитай, что делает
reword
,squash
иfixup
. -
В первой строчке файла замени
pick
наreword
, а последующих строчках замениpick
наfixup
. Сохрани изменения и закрой файл со сценарием. После чего сценарий начнет выполняться. -
Сразу же редактор откроется снова, потому что команде
reword
требуется новое сообщение для коммита. В открывшемся редакторе замени текущее сообщениеSheet markup
на новое сообщениеExtension
и закрой файл. -
Убедись, что ветка
sheet-feature
теперь ссылается на новый коммит с названиемExtension
. А внутри этого коммита объединены все изменения скопированных коммитов. -
Перейди на ветку
master
и влей в него изменения изsheet-feature
. Влитие получится в режиме fast-forward. -
Удали ветку
sheet-feature
используя контекстное меню. При удалении выбериForce delete
, потому что эта ветка связана сext/sheet-feature
, которая вmaster
не влита.
Теперь история коммитов должна выглядеть так:
-
Надо достать для ветки
master
изменения из коммитаAdd runner
из веткиsolved
. В этом случае нужен только один коммит, который находится между другими — значит подойдетcherry-pick
. Достань эту вишенку с помощью командыCherry pick this commit
в контекстном меню. В диалоговом окне команды выбери пунктAutomatically create a commit
. Хотя можно ее не нажимать, а сделать коммит самостоятельно сразу после cherry pick. -
Убедись, что в ветке
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
с помощьюCommands / 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
, чтобы не создавать лишний коммит. -
Обрати внимание, что старый коммит остался видимым, ведь на него ссылается
origin/master
Теперь история коммитов должна выглядеть так:
- Если сейчас выполнить push, то он завешится ошибкой, т.к. навозможно продвинуть
origin/master
вперед по истории так, чтобы он стал ссылаться на коммит, на который ссылаетсяmaster
. Поэтому выполни push с опциейForce With Lease
. Чтобы ее выбрать в диалоговом окне команды Push нажми на ссылкуShow options
и выбери эту опцию.
Теперь история коммитов должна выглядеть так:
-
Создай ветку
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 Extensions предупредит, что ветки в удаленном репозитории еще нет. Надо согласиться. Затем Git Extensions предупредит, что у ветки
upstream-feature
еще нет связи с удаленной веткой и предложит ее установить. Тоже надо согласиться. В результате Git Extensions выполнит примерно такую команду:push -u origin upstream-feature:upstream-feature
. То же самое можно сделать через консоль такой командой:push -u origin HEAD
Теперь история коммитов должна выглядеть так:
-
Перейди на ветку
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
, поэтому придется прервать работу. Выбери пункт главного менюCommands / Manage stashes
. Откроется окноStash
для управления сохраненными изменениями. НажмиStash all changes
, чтобы создать новый stash. Закрой окно. Обрати внимание, что вWorking directory
изменения пропали. -
Перейди на ветку
master
, влей в нее веткуupstream-feature
, сделай push -
Перейди назад на ветку
reset-feature
-
Верни изменения из stash. Для этого выбери пункт главного меню
Commands / Manage stashes
. Так как пока сохранен только один stash, просто нажмиApply Selected Stash
. Изменения попадут вWorking directory
. -
Закоммить изменения с сообщением
Change reset.md
-
Похоже разработка в ветке
reset-feature
закончена, поэтому можно влить в нееmaster
и отдать в тестирование. Влейmaster
.
Теперь история коммитов должна выглядеть так:
-
К сожалению, ты забыл добавить некоторые изменения в
reset-feature
. Придется отменить merge. Хорошо, чтоreset-feature
еще не запушен. -
Выбери коммит
Change reset.md
и с помощью контекстного меню выполниReset current branch to here
. В открывшемся окне выбери опциюHard
, чтобы полностью затереть все изменения, и выполни reset. -
Замени содержимое
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
и перейди на нее -
Выбери начальный коммит
Initial commit
и с помощью контекстного меню выполниReset current branch to here
. В открывшемся окне выбери опциюSoft
, чтобы вся разница между коммитами оказалась вCommit index
, и выполни reset. -
Все изменения уже в
Commit index
. Поэтому просто закоммить их с сообщениемSolved
-
Сделай push