Материал подготовлен командой Simple-Server для администраторов VPS и выделенных серверов. Команды и пути проверяйте на тестовой машине перед production.
Кратко о задаче
Сперва подготовим отдельный каталог для тестового проекта в Git:
После чего перейдем в него:
Наконец, выполним инициализацию репозитория Git:
После этого нам станут доступны все команды по управлению как ветками, так и репозиторием в целом.**
**
2. Создание файла и выполнение коммита
Чтобы понять, как переключение веток влияет на рабочий каталог (и репозиторий целикоv), мы подготовим импровизированный файл исходника проекта с тривиальным содержимым внутри:
Наполнение файла будет следующим:
Давайте проверим состояние рабочего каталога:
Существует только один файл:
Теперь проиндексируем изменения:
После чего выполним коммит:
git commit -m "First commit"По ходу этого руководства мы будем наблюдать за тем, как работа с ветками влияет на содержимое рабочего каталога — в частности на файлы, которые мы создаем или редактируем.**
**
Предположим, мы решили внедрить в наш проект новую фичу, но пока что до конца не уверены в ее необходимости или эффективности. По сути, мы хотим проверить некую гипотезу с возможностью отката изменений до основной стабильной версии проекта.
В этих целях Git предоставляет возможность создания отдельных веток и переключения между ними. Таким образом мы всегда сможем проверить работоспособность проекта как с фичей, так и без нее.
Однако для начала давайте узнаем, на какой ветке мы находимся сейчас:
В консоли появится вывод с подсвеченной активной веткой master:
Именно в эту ветку мы совершили предыдущий коммит. Это значит, что в этой ветке находился ранее созданный файл file_m.
Теперь мы попробуем создать отдельную ветку под внедряемую нами импровизированную фичу. Для этих целей используется та же самая команда, но с указанием имени новой ветки:
Однако важно помнить, что git branch не выполняет автоматическое переключение на созданную ветку.
Мы можем убедиться в этом, снова проверив список существующих веток:
Можно заметить, что к списку добавилась ветка feature1, однако активной веткой (то есть помеченной с помощью зеленого цвета и символа звездочки) по прежнему является master:
Теперь у нас есть несколько веток, между которыми мы можем переключаться.**
**
4. Переключение на существующую ветку
Для того, чтобы вручную переключиться на уже существующую ветку, необходимо выполнить команду checkout, указав название ветки:
В консоли появится сообщение об успешном переключении:
Switched to branch 'feature1'Снова проверим список существующих веток:
Как видно, активной веткой теперь является feature1:
Давайте снова проверим состояние рабочего каталога:
В нем по-прежнему один файл, который был «унаследован» из ветки master:
Так как отдельная ветка feature1 нужна для модификации проекта, мы создадим еще один файл:
Его содержимое пусть будет таким:
Проиндексируем изменения:
git commit -m "Commit from feature1"Снова проверим рабочий каталог:
Можно убедиться, что файлов теперь несколько:
Теперь переключимся снова на главную ветку:
После этого в рабочем каталоге останется только один файл:
Каждый раз, когда мы переключаемся между ветками, файлы в рабочем каталоге обновляются до состояния тех коммитов, которые существуют в активной ветке.**
**
5. Переключение на новую ветку
Предположим, мы решили добавить в наш проект еще одну фичу, а значит, хотим выделить под нее новую ветку.
Сперва убедимся, что мы находимся на master:
А теперь попробуем переключиться на еще не созданную ветку feature2:
Закономерно, мы получим ошибку:
error: pathspec 'feature2' did not match any file(s) known to gitОднако команда checkout позволяет создавать новые ветки в момент переключения на них. Для этого необходимо добавить флаг -b:
В консоли появится сообщение об успешном переключении:
Switched to a new branch 'feature2'По сути, команда checkout с флагом -b эквивалентна двум вызовам:
git branch feature2
git checkout feature2Снова проверим список существующих веток:
Теперь у нас есть ветка feature2, которая стала активной сразу после своего создания:
feature1
* feature2
masterНовая ветка создается на основе той ветки (ее рабочего каталога и списка коммитов), которая была активной. Перед созданием ветки feature2 мы переключились на ветку master, а значит в рабочем каталоге должен быть только файл file_m, но не файл file_f1.**
**
Удалить ветку, которая является активной, невозможно:
Флаг -d указывает на запрос удаления указанной ветки. В консоли появится сообщение об ошибке:
error: Cannot delete branch 'feature2' checked out at '/root/project'Поэтому нам сперва нужно переключиться на любую другую ветку:
После чего выполнить непосредственно удаление:
На этот раз в консоли появится сообщение об успешном удалении ветки:
Deleted branch feature2 (was 24c65ff).Список существующих веток станет таким:
7. Создание ветки из другой ветки
Git позволяет явно указывать, на основе какой ветки будет создана новая ветка, без необходимости предварительного переключения.
Давайте убедимся, что мы находимся в ветке master:
На данный момент специальный указатель HEAD указывает на активную ветку master, которая, в свою очередь, является указателем на последний коммит этой ветки.
До этого мы создавали ветку feature2 из активной ветки master. Однако сейчас мы создадим ветку feature2 из ветки feature1 (а не из master) без явного переключения на нее — мы по-прежнему будем в master:
git checkout -b feature2 feature1Теперь активной веткой является feature2. Проверим содержимое рабочего каталога:
Как видно, состояние каталога такое же, как в feature1, а не в master:
Мы также можем посмотреть историю коммитов:
Как видно, ветка feature2 содержит как коммиты ветки master, так и коммиты ветки feature1:
commit fb1b1616c85c258f647df4137df535df5ac17d6c (HEAD -> feature2, feature1)
Author: root <root@2450302-yn55665.twc1.net>
Date: Tue Feb 13 02:18:02 2024 +0300
Commit from feature1
commit 24c65ffab574a5e478061034137298ca2ce33c94 (master)
Author: root <root@2450302-yn55665.twc1.net>
Date: Mon Feb 12 23:30:56 2024 +0300
First commit8. Сброс ветки до состояния другой ветки
Помимо создания ветки из другой ветки команда checkout позволяет выполнять сброс (reset) существующей ветки до состояния другой существующей ветки.
Например, мы можем сбросить ветку feature2 до состояние ветки master:
git checkout -B feature2 masterОбратите внимание, что используется флаг -B, а не -b.
В консоли появится соответствующее сообщение:
Проверим рабочий каталог:
Как видно, в нем только один файл:
При этом список «унаследованных» коммитов ветки feature2 превратиться в список коммитов ветки master:
В консольном выводе будет один единственный коммит — самый первый:
commit 24c65ffab574a5e478061034137298ca2ce33c94 (HEAD -> feature2, master)
Author: root <root@2450302-yn55665.twc1.net>
Date: Mon Feb 12 23:30:56 2024 +0300
First commit9. Просмотр истории переключений
Переключение веток — это не просто операция чтения. Смена ветки вносит изменение в репозиторий, создавая новую запись в истории переключений.
По этой причине в Git есть специальная команда, выводящая полную хронологию переключения между ветками:
Хронология операций выводится отображается снизу-вверх, то есть самые последние переключения находятся выше:
fb1b161 (HEAD -> feature2, feature1) HEAD@{1}: checkout: moving from master to feature2
24c65ff (master) HEAD@{2}: checkout: moving from feature1 to master
fb1b161 (HEAD -> feature2, feature1) HEAD@{3}: commit: Added the first feature
24c65ff (master) HEAD@{4}: checkout: moving from master to feature1
24c65ff (master) HEAD@{5}: checkout: moving from feature2 to master
24c65ff (master) HEAD@{6}: checkout: moving from feature1 to feature2
24c65ff (master) HEAD@{7}: checkout: moving from master to feature1
24c65ff (master) HEAD@{8}: commit (initial): First commit10. Переключение на удаленную ветку
Добавление удаленного репозитория
Предположим, у нас есть удаленный репозиторий GitHub, с которым мы работаем через HTTPS-соединение:
git remote add repository_remote https://github.com/USER/REPOSITORY.gitЛибо же мы могли получить к нему доступ через SSH:
git remote add repository_remote git@github.com:USER/REPOSITORY.gitВ этом случае предварительно выполняется генерация SSH-ключа:
ssh-keygen -t rsa -b 4096 -C "GITHUB_ACCOUNT_EMAIL"При этом публичный ключ (.pub), появившийся в каталоге /.ssh/known_hosts/, копируется в настройки аккаунта GitHub в раздел SSH Keys.
В нашем случае удаленным репозиторием выступит Nginx:
git remote add repository_remote https://github.com/nginx/nginxЗагрузка файлов из удаленной ветки
После добавления удаленного репозитория можно посмотреть список всех его веток:
git remote show repository_remoteПеред переключением на удаленную ветку нужно сперва извлечь подробную информацию об удаленном репозитории — ветки и теги:
git fetch repository_remoteМожно также указать сразу все удаленные репозитории:
Теперь мы можем напрямую переключиться на удаленную ветку, получив ее файлы в рабочий каталог:
git checkout branches/stable-0.5При этом в более старых версиях Git приходилось явно указывать название удаленного репозитория:
git checkout repository_remote/branches/stable-0.5Теперь, если выполнить команду:
Можно увидеть указанную удаленную ветку в статусе активной:
* branches/stable-0.5
feature2
feature1
masterПроверим состояние рабочего каталога:
Теперь в нем присутствуют следующие каталоги:
auto conf contrib docs misc srcУдаленную ветку, ровно как и локальную, можно удалить. Для этого ее сперва нужно сделать неактивной:
После чего выполнить само удаление:
git branch -D branches/stable-0.5Теперь список веток проекта станет, как прежде:
feature2
feature1
* master11. Переключение на коммит
Точно так же, как переключаться на разные ветки, вы можете переключаться на конкретные коммиты. Однако, важно отметить разницу между коммитами и ветками.
Ветки отклоняются от временной шкалы проекта, но не нарушают общую последовательность изменений. А вот коммиты больше похожи лишь на точки прогресса, содержащие определенные состояния проекта в конкретные моменты времени.
Давайте сперва переключимся на самую последнюю созданную ветку, которая содержит наибольшее число коммитов:
Чтобы переключиться на конкретный коммит, вместо имени ветки в checkout указывается хеш (ID) коммита:
git checkout fb1b1616c85c258f647df4137df535df5ac17d6cЧтобы узнать хэш, можно воспользоваться командой:
В нашем случае история коммитов выглядит примерно так — отличаться могут только хэши:
commit fb1b1616c85c258f647df4137df535df5ac17d6c (HEAD -> feature2, feature1)
Author: root <root@2450302-yn55665.twc1.net>
Date: Tue Feb 13 02:18:02 2024 +0300
Commit from feature1
commit 24c65ffab574a5e478061034137298ca2ce33c94 (master)
Author: root <root@2450302-yn55665.twc1.net>
Date: Mon Feb 12 23:30:56 2024 +0300
First commitПосле переключения на коммит можно посмотреть, какая ветка является активной:
Теперь список веток приобрел следующий вид:
* (HEAD detached at fb1b1616c)
feature2
feature1
masterЭта манипуляция приводит к состоянию отсоединенного указателя HEAD («detached HEAD»). Таким образом, все последующий коммиты не будут принадлежать ни одной из существующих веток.
Однако такой режим небезопасен — отсутствие конкретной ветки в указателе HEAD может привести к потере данных.
По этой причине выбранный коммит (тот, на который указывает HEAD) принято «оборачивать» в новую ветку, в рамках которой производятся дальнейшие модификации проекта.
Чаще всего функцию переключения на конкретный коммит используют для просмотра изменений кодовой базы, которые были внесены на определенной стадии разработки.**
**
Отличие checkout от switch
В более поздних версиях (2.23 и выше) Git есть другая команда для работы с ветками — switch.
Эти команды довольно похожи, однако switch является более специализированным вариантом:
-
git switch— новая команда, которая в большей степени ориентирована на работу с ветками. Напротив,git checkout— старая команда, которая способна делать и другие «периферийные» задачи. Например, создавать новые в ветки в момент переключения или изменять содержимое рабочего каталога до состояние конкретного коммита. -
git checkoutимеет более универсальный (и менее стандартизированный) синтаксис, нежелиgit switch. С другой стороны по этой причинеcheckoutможет казаться более сложной и запутанной, а значит, подверженной ошибкам.
git switch — новая команда, которая в большей степени ориентирована на работу с ветками. Напротив, git checkout — старая команда, которая способна делать и другие «периферийные» задачи. Например, создавать новые в ветки в момент переключения или изменять содержимое рабочего каталога до состояние конкретного коммита.
git checkout имеет более универсальный (и менее стандартизированный) синтаксис, нежели git switch. С другой стороны по этой причине checkout может казаться более сложной и запутанной, а значит, подверженной ошибкам.
Нужен сервер для практики? Арендуйте VPS/VDS в России — root-доступ, NVMe, DDoS-защита и поддержка 24/7.