Работа с собственным репозиторием
Обычная работа с репозиторием это периодическое сохранение накопленных изменений и работа с текущим состоянием файлов. Однако, иногда нам надо вернуться к предыдущим состояниям, например, для того чтобы откатиться к последней стабильной версии в случае каких-то ошибок в текущем состоянии, или для того чтобы начать разрабатывать новые функции в текущей стабильной версии, не затрагивая основной поток разработки. Звучит сложновато, но сейчас мы все пройдем на практике.
Для начала создадим несколько коммитов:
Напишем текущее время в README.md
nano README.md
Добавим изменения файла README.md в коммит.
git add .
Теперь создадим второй коммит с этими изменениями.
git commit - m "second commit"

Отправим наш коммит на GitHub
git push
Как и в прошлый раз надо ввести e-mail и токен.

Давайте перейдем на сайт GitHub и посмотрим на изменения.

Текущее состояние репозитория изменилось. Файл README.md соответствует тем изменениям, которые мы в него внесли. И обратите внимание, что в истории коммитов появился третий коммит - это наш текущий "второй" коммит, а "третий" он потому, что как мы говорили ранее, самый первый коммит сделал за нас сам git, когда создавал репозиторий.
Давайте сделаем еще пару коммитов и затем перейдем к навигации по ним.
Изменим файл README.md снова актуализировав время, добавим его в коммит и создатим третий коммит.
nano README.md
git add .
git commit -m "thrid commit"
И сразу не отправляя изменения на удаленный репозиторий сделаем и четвертый коммит.
nano README.md
git add .
git commit -m "4th commit"
А вот после этого уже отправим (запушим) изменения.
git push
Посмотрим на сайте GitHub что изменилось.

Все так как мы и ожидали, текущее состояние репозитория это то состояние файла README.md которое мы изменили последним. Однако не смотря на то, что git push мы делали только один раз, после "четвертого" коммита, коммитов стало пять. Т.е. в один push вошло сразу два коммита "третий" и "четвертый". Это связано с тем, что git push не добавляет ничего в состояние репозитория, а только синхорнизирует локального клона репозитория с удаленным клоном. Т.е. мы можем накапливать коммиты в течение рабочего дня, а затем одним пушем отправить их на GitHub, перед тем как пойти домой.
Посмотрим как выглядят текущие коммиты у нас в локальном репозитории. Введем:
git log

Обратите внимание, что сами коммиты называются не так как мы их откомментировали при создании, а по hash строке. Именно так в дальнейшем можно с ними работать эту hash строку мы и будем вводить когда захотим например перейти на какой-то другой коммит.
Кроме того обратите внимание что последний коммит имеет название HEAD - голова.
Теперь давайте перейдем к какому-нибудь из прошлых коммитов. Это делается командой git checkout hash <строка коммита>. Перейдем, например, к третьему коммиту.
git checkout 89453ef440149e38a3f397415c1b7b58deec9c16

Давайте посмотрим какое сейчас содержание файла README.md
nano README.md

как вы видите, указано время "12:10" что соответствует нашему третьему коммиту т.е. все так как мы и хотели. Однако логика команды git checkout состоит в том после переключения на старый коммит, он создает новую ветку, с новым HEAD, и нам надо что-то с этим делать. Или продолжить эту новую ветку и работать в ней, или вернуться на свою старую ветку main и продолжить работу там.
Давайте рассмотрим оба эти случая.
Вернемся на начальную ветку командой:
git checkout main
посмотрим на лог
git log

Лог такой же как и был до этого. Т.е. все вернулось к 4му коммиту. Теперь мы можем продолжать работать как и было и все новые коммиты будут пристыковываться к 4-му.
Теперь давайте сделаем сложную операцию. Вернемся в наш второй коммит, начнем работать с новой веткой, т.е. положим туда новые коммиты, а старую ветку от второго коммита и выше - удалим.
Для того чтобы удалить коммиты выше определенного, надо ввести команду:
git reset <hash коммита>
Введем hash второго коммита и получим:

Теперь давайте запушим эти изменения на GitHub, обратите внимание что делать это надо с опцией force
git push --force
Теперь на GitHub у нас следующая картина:

Т.е. все соответствует локальному репозиторию, а все коммиты новее второго удалены. Обратите внимание, что команду git reset надо делать из HEAD, а не после git checkout. Т.е. можно сначала найти правильный коммит при помощи git checkout, потом надо вернуться обратно в HEAD, и только потом отрезать новые коммиты командой git reset.
Теперь все наши следующие коммиты будут выстраиваться дальше в основную ветку main.
Основные моменты работы с git мы изучили. Нам осталось разобраться с ветками. Давайте продолжим. Введем git branch

Как вы видите у нас есть только одна ветка main в которую и будут попадать все наши текущие коммиты. Давайте создадим еще одну ветку в которой мы будем "править ошибки", назовем ее new
git branch new

Теперь у нас две ветки main и new. Давайте переключимся в ветку new, сделаем там пару коммитов и зальем все на удаленный репозиторий.
Переключим ветку:
git checkout new
Сделаем два изменения времени в файле README.md и закоммитим их последовательными коммитами
nano README.md

git add .
git commit -m "first commit in new branch"
nano README.md

git add .
git commit -m "second commit in new branch"
И зальем на удаленный репозиторий
git push --set-upstream origin new
Обратите внимание, что git сам подскажет правильную команду

Перейдем на github и посмотрим как там все это выглядит.

В списке веток появилась ветка new, и в ней все сделанные коммиты на текущий момент.
Давайте переключимся обратно на ветку main и сделаем коммит в ней.
git checkout main
nano README.md

git add .
git commit -m "commit from main branch"

Посмотрим как ветка main выглядит на GitHub

Далее мы можем вести разработку и создавать коммиты неограниченно долгое время и у нас будут две ветки развивающиеся параллельно. И последний прием, который часто используется, это слияние веток обратно, к примеру, после того как все ошибки исправлены и фиксы надо влить обратно в ветку разработки. Давайте вольем ветку new в ветку main.
git checkout main
git merge new
Так как в обоих ветках находится файл README.md, и он различается в каждой из веток, то git не знает какой из них брать, то вы получите какое-то сообщение о невозможности слить ветки. Кроме того во всех файлах где git увидит конфликты будут выделены конфликтные области.

Существуют различные способы решения данного конфликта, и пытливые учащиеся могут самостоятельно поискать эти способы, но мы поступим достаточно прямолинейно. Отредактируем файл README.md в nano, оставив ту версию, которая нам больше нравится

Оставим, к примеру, 14-00.

Теперь создадим коммит в который включим наш отредактированный файл.
git add .
git commit -m "README.md merge confilct solved"
И все что нам остается сделать это запушить все изменения в удаленный репозиторий.
git push
Перейдем на сайт GitHub и посмотрим как наш merge выглядит там

Ну вот, все коммиты сохранены, ветки слиты. Текущее значение времени в README.md 14-00. Все как мы хотели.
Ну и напоследок скажем, что данный урок не исчерпывающий и git гораздо глубже и более функционален, кроме те кто немного запутался в ветках и слияниях, могут немного расслабиться так как ветки и слияния это то с чем обычный разработчик сталкивается НЕ каждый день. И обычно в компаниях есть принятая политика создания веток и их слияния, так что придумывать всю логику вам скорее всего не придется.
На этом мы закончим наш пример работы с git. Переходите к изучению базового курса по ROS.