-
Создай папку
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» на странице репозитория. Если настраивал SSH для GitHub, то в меню, открывшемся после нажатия на кнопку, выбери вкладку SSH и используй адрес из этой вкладки! НЕ СПУТАЙ: это НЕ репозиторий с презентацией и текстом этого задания!
-
В склонированной папке найди файлы
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. Часто конфликты разрешаются выбором варианта из одной из веток, но это не тот случай. В VS Code нажмиCompare Changes
и убедись, что поменялось все. Придется объединять изменения аккуратно вручную. Сначала выбери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