Блок 16
Git — система контроля версий
> Что вас ждёт в этом блоке: мы познакомимся с Git — системой контроля версий, без которой сегодня не обходится практически ни один проект разработки программного обеспечения, а также многие процес…
Введение в блок
> Что вас ждёт в этом блоке: мы познакомимся с Git — системой контроля версий, без которой сегодня не обходится практически ни один проект разработки программного обеспечения, а также многие процессы администрирования (хранение конфигураций, скриптов, инфраструктуры как кода). Вы научитесь сохранять историю изменений файлов, работать с ветками для параллельной разработки, и синхронизировать свой код с удалёнными репозиториями на GitHub.
>
> Что нужно знать перед началом: уверенная работа с терминалом и файловой системой (Блоки 1–5), базовое понимание bash-скриптов (Блок 15) пригодится для автоматизации Git-операций, а также общее понимание SSH (Блок 13) — оно потребуется для безопасного подключения к GitHub.
Урок 16.1. Зачем нужен контроль версий
Понять проблему, которую решает система контроля версий, разобраться в базовой терминологии Git, и осознать разницу между централизованными и распределёнными системами контроля версий.
Теория
Проблема, которую решает контроль версий. Представьте, что вы работаете над важным документом или программным кодом. Со временем возникают типичные проблемы:
- Потеря истории изменений. Вы внесли изменение неделю назад, а сегодня понимаете, что оно было ошибочным — как вернуться к предыдущей версии? Без специального инструмента приходится полагаться на ручные копии файлов с именами вроде
проект_финал.txt,проект_финал_2.txt,проект_финал_ИСПРАВЛЕННЫЙ.txt— знакомая многим, но крайне ненадёжная и запутанная практика.
- Совместная работа нескольких людей. Если два человека одновременно редактируют один и тот же файл, как объединить их изменения, не потеряв ни одного? Как узнать, кто именно и когда внёс конкретное изменение?
- Эксперименты без риска. Как попробовать рискованную новую идею в коде, не боясь сломать уже работающую версию, и при необходимости быстро вернуться назад?
- Отслеживание причин ошибок. Если в коде появилась ошибка, как найти точный момент (и автора), когда она была введена, среди сотен изменений за долгое время?
Система контроля версий (Version Control System, VCS) — это программа, которая решает все перечисленные проблемы: она сохраняет полную историю изменений файлов проекта, позволяет возвращаться к любой предыдущей версии, показывает, кто и когда внёс каждое изменение, и предоставляет инструменты для безопасного объединения параллельных изменений от разных людей.
Централизованные vs распределённые системы контроля версий. Исторически существовало два основных подхода:
- Централизованные системы** (например, SVN — Subversion, CVS — более старые технологии) хранят единственную «главную» копию истории на центральном сервере. Каждый разработчик получает только текущую версию файлов, а вся история хранится централизованно — без подключения к серверу невозможно ни посмотреть историю, ни зафиксировать изменение.
- Распределённые системы (Git, Mercurial) — каждый разработчик получает полную копию** всей истории проекта на свой локальный компьютер. Это означает, что можно просматривать историю, создавать новые версии (коммиты, о которых мы поговорим ниже) и переключаться между версиями полностью автономно, без подключения к сети — синхронизация с другими копиями (например, с сервером) происходит только тогда, когда это действительно нужно.
Git — самая популярная в мире распределённая система контроля версий, созданная в 2005 году Линусом Торвальдсом (тем же человеком, который создал ядро Linux — мы упоминали его в самом начале курса, в Блоке 1, при обсуждении истории Linux). Торвальдс разработал Git специально для управления разработкой самого ядра Linux, когда предыдущая система, которую использовало сообщество, перестала быть доступной на приемлемых условиях. Сегодня Git используется практически повсеместно в разработке программного обеспечения — от небольших личных проектов до крупнейших мировых технологических компаний.
Базовая терминология Git, которую важно усвоить с самого начала:
- Репозиторий (repository, часто сокращают до «репо»)** — директория, содержимое которой отслеживается Git. Внутри репозитория Git хранит всю историю изменений в специальной скрытой поддиректории
.git/. - Коммит (commit)** — «снимок» (снапшот) состояния всех отслеживаемых файлов проекта в определённый момент времени, сохранённый в историю с сопроводительным сообщением, объясняющим, что было изменено и зачем. Коммит — это фундаментальная единица истории в Git; вся история проекта — это последовательность (точнее, граф) коммитов.
- Рабочая директория (working directory)** — обычные файлы проекта на диске, с которыми вы напрямую работаете и редактируете в любом текстовом редакторе.
- Область подготовки (staging area, или «индекс», index)** — промежуточная зона между рабочей директорией и историей коммитов. Прежде чем изменение попадёт в новый коммит, его нужно явно «подготовить» (стадировать, stage) — это позволяет точно контролировать, какие именно из накопившихся изменений войдут в следующий коммит, а какие останутся «на потом». Мы подробно разберём этот механизм в следующем уроке.
- Ветка (branch)** — независимая линия разработки внутри одного репозитория. По умолчанию у нового репозитория есть одна ветка (традиционно называемая
main, ранее частоmaster), но можно создавать дополнительные ветки для параллельной, изолированной работы над разными задачами, не мешая друг другу (подробно — в уроке 16.4). - Удалённый репозиторий (remote)** — копия репозитория, расположенная не на вашем локальном компьютере, а где-то ещё — например, на сервисе GitHub, который мы изучим в последнем уроке блока. Позволяет обмениваться изменениями между разными людьми и разными компьютерами.
- HEAD** — специальная указка (ссылка) в Git, обозначающая, на каком именно коммите (и, соответственно, в какой ветке) вы находитесь прямо сейчас.
Почему Git важен именно в контексте администрирования Linux, а не только разработки. Хотя Git ассоциируется в первую очередь с разработкой программного обеспечения, для системного администратора он не менее полезен:
- Хранение истории изменений конфигурационных файлов сервера (например,
/etc/nginx/, наши скрипты из~/scripts/) — с возможностью откатиться к рабочей версии, если новая конфигурация всё сломала. - Концепция «инфраструктура как код» (Infrastructure as Code), которую мы затронем в Блоке 20 — описание настройки серверов в виде текстовых файлов, версионируемых через Git.
- Совместная разработка и ревью (проверка) bash-скриптов автоматизации (материал Блока 15) в команде администраторов.
Практика
В этом вводном уроке мы не будем ещё непосредственно работать с Git (это начнётся в следующем уроке), а изучим общую концепцию на наглядном примере без специального инструмента — чтобы прочувствовать проблему, которую Git решает.
Шаг 1. Создайте директорию для демонстрации проблемы вручную, без Git:
```bash
mkdir -p ~/git_intro_demo
cd ~/git_intro_demo
echo "Версия 1: черновик документа" > document.txt
cat document.txt
```
Шаг 2. Смоделируйте типичный «ручной» подход к сохранению истории версий, который используют люди без систем контроля версий:
```bash
cp document.txt document_v2.txt
echo "Версия 2: добавлен раздел о целях" >> document_v2.txt
cp document_v2.txt document_v2_FINAL.txt
echo "Версия 3: исправлены опечатки" >> document_v2_FINAL.txt
cp document_v2_FINAL.txt document_v2_FINAL_ИСПРАВЛЕНО.txt
ls -la
```
Что вы увидите: уже после трёх простых изменений у нас накопилось четыре похожих файла с запутанными именами — и это без единого сообщения о том, что именно изменилось в каждой версии и почему. В реальном проекте, развивающемся месяцами, такой подход становится абсолютно неуправляемым.
[Скриншот терминала с накопившимися файлами]
Шаг 3. Задумайтесь над вопросами (запишите ответы в конспект, не выполняя команд):
- Как вы поймёте, какой из этих четырёх файлов актуальный, если пройдёт полгода?
- Что делать, если нужно узнать, какая именно строка была изменена между версией 2 и версией 3?
- Что если два человека одновременно работали над этим документом и оба создали свою «финальную» версию?
Шаг 4. Очистите демонстрационную директорию — мы вернёмся к этому же примеру уже с использованием Git в следующем уроке:
```bash
cd ~
rm -rf ~/git_intro_demo
```
Шаг 5. Проверьте, установлен ли Git в вашей системе (мы подробно установим и настроим его в следующем уроке, но полезно проверить заранее):
```bash
git --version
```
Что вы увидите: либо версию установленного Git (например, git version 2.43.0), либо сообщение о том, что команда не найдена — в таком случае мы установим Git в практике следующего урока.
Разбор команд
В этом уроке мы не вводили новых команд Git — только продемонстрировали проблему на уже знакомых нам командах работы с файлами (cp, echo >>, ls), изученных в Блоке 5.
Возможные ошибки
В этом вводном уроке практических Git-команд не выполнялось, поэтому специфичных ошибок пока не возникает — соответствующий раздел появится начиная со следующего урока, где мы начнём непосредственную работу с Git.
Практические задания
- Опишите в конспекте (текстом, без выполнения команд) реальную ситуацию из вашего опыта — учебного, рабочего или личного — когда отсутствие контроля версий привело к путанице, потере данных или сложностям при совместной работе над файлами.
- Изучите (через поиск в интернете, без необходимости входить в аккаунт) главную страницу сайта github.com и опишите в конспекте, для чего этот сервис используется, судя по описанию на главной странице — мы вернёмся к практической работе с ним в уроке 16.5.
- Найдите в интернете информацию о том, в каком году и кем был создан Git, и с какой конкретной практической проблемой было связано его создание (подсказка: поищите про инцидент с системой BitKeeper, использовавшейся ранее для разработки ядра Linux) — опишите кратко в конспекте.
Проверка знаний
Вопрос 1. В чём принципиальная разница между централизованной и распределённой системой контроля версий с точки зрения того, где хранится история изменений проекта?
Ответ: В централизованной системе (например, SVN) полная история изменений хранится только на одном центральном сервере — локально у каждого разработчика находится лишь текущая версия файлов, и без подключения к серверу невозможно ни посмотреть историю, ни зафиксировать новое изменение. В распределённой системе (Git) каждый разработчик, склонировавший репозиторий, получает полную копию всей истории на свой локальный компьютер — что позволяет работать с историей (смотреть, создавать новые версии) полностью автономно, без сетевого подключения, синхронизируясь с другими копиями только по мере необходимости.
Вопрос 2. Что такое «коммит» в терминологии Git, и чем он принципиально отличается от простого сохранения копии файла под новым именем (как в демонстрации практики этого урока)?
Ответ: Коммит — это «снимок» состояния всех отслеживаемых файлов проекта в определённый момент времени, сохранённый в формальную историю системы контроля версий вместе с сопроводительным сообщением, объясняющим суть изменения, автором и точной временной меткой. В отличие от простого копирования файла под новым именем, коммит хранится в структурированной, машиночитаемой истории, которую можно просматривать, сравнивать между собой (видеть точные различия между любыми двумя коммитами), возвращаться к любому из них, и на основе которой можно строить параллельные линии разработки (ветки) — ничего из этого невозможно при простом ручном копировании файлов с разными именами.
Итоги урока
Вы изучили: проблему, которую решает контроль версий, разницу между централизованными и распределёнными VCS, историю создания Git, ключевую терминологию (репозиторий, коммит, рабочая директория, область подготовки, ветка, удалённый репозиторий, HEAD).
Вы умеете: сформулировать, зачем нужен контроль версий, объяснить его практическую ценность на конкретном примере.
В следующем уроке потребуется: понимание терминологии этого урока — теперь мы установим Git и настроим его для реальной работы.
Урок 16.2. Установка и настройка Git
Установить Git в системе, выполнить обязательную первоначальную настройку (имя пользователя, email), изучить систему уровней конфигурации Git и научиться проверять текущие настройки.
Теория
Установка Git в Ubuntu. Git обычно доступен через стандартный менеджер пакетов APT (детально изученный в Блоке 9), как и подавляющее большинство программного обеспечения в Ubuntu.
Обязательная первоначальная настройка. Прежде чем создавать свои первые коммиты, Git требует настроить как минимум два параметра: имя и email пользователя. Эта информация будет автоматически прикрепляться к каждому создаваемому вами коммиту, формируя часть постоянной истории проекта — то есть каждый коммит «подписывается» именем и email автора, что критически важно при совместной работе (чтобы понимать, кто именно внёс каждое изменение).
Три уровня конфигурации Git. Настройки Git могут применяться на разных уровнях, с разной областью действия — эта концепция напоминает уже знакомую нам из Блока 14 идею о конфигурационных файлах разного уровня приоритета:
--system** — системный уровень, применяется ко всем пользователям данного компьютера. Файл настроек:/etc/gitconfig. Требует прав root для изменения.--global** — глобальный уровень, применяется ко всем репозиториям текущего пользователя на этом компьютере. Файл настроек:~/.gitconfig(в домашней директории пользователя). Это наиболее часто используемый уровень для персональных настроек, таких как имя и email.--local** (используется по умолчанию, если не указан флаг явно) — локальный уровень, применяется только к конкретному репозиторию, в котором вы сейчас находитесь. Файл настроек хранится внутри.git/configэтого конкретного репозитория. Полезно, например, если для рабочих проектов вы хотите использовать рабочий email, а для личных — личный, отличающийся от глобальной настройки.
Приоритет: локальные настройки (--local) переопределяют глобальные (--global), которые, в свою очередь, переопределяют системные (--system) — точно та же логика приоритета «более специфичное перекрывает более общее», которую мы уже видели в SSH-конфигурации (Блок 13) и файле ~/.ssh/config.
Основная команда настройки — git config:
```bash
git config --global user.name "Ваше Имя"
git config --global user.email "ваш@email.com"
```
Просмотр текущих настроек:
```bash
git config --list # все настройки, объединённые из всех уровней
git config --list --show-origin # то же самое, но с указанием, из какого файла взята каждая настройка
git config user.name # конкретное значение конкретной настройки
```
Дополнительные полезные настройки, которые стоит установить сразу:
init.defaultBranch** — имя ветки по умолчанию для новых репозиториев. Исторически по умолчанию использовалось имяmaster, но с 2020 года сообщество Git постепенно перешло наmainкак более нейтральное название, и многие современные инструменты (включая GitHub) используютmainпо умолчанию для новых репозиториев:
```bash
git config --global init.defaultBranch main
```
core.editor** — какой текстовый редактор использовать, когда Git сам открывает редактор (например, для написания более развёрнутого сообщения коммита). Установимnano, который мы подробно изучали в Блоке 7 — многим начинающим он привычнее, чем редактор по умолчанию (часто этоvim, требующий отдельного изучения, которое не входит в этот курс):
```bash
git config --global core.editor "nano"
```
color.ui** — включить цветной вывод команд Git в терминале (обычно включено по умолчанию в современных версиях, но полезно знать о существовании этой настройки):
```bash
git config --global color.ui auto
```
Где физически хранится глобальная конфигурация. Файл ~/.gitconfig — это простой текстовый файл в специальном формате INI (секции в квадратных скобках, пары ключ-значение внутри), который можно при желании просмотреть или даже отредактировать напрямую любым текстовым редактором, хотя обычно предпочтительнее использовать именно команду git config, которая гарантирует правильный синтаксис.
Практика
Шаг 1. Проверьте, установлен ли Git:
```bash
git --version
```
Шаг 2. Если Git не установлен — установите его через APT:
```bash
sudo apt update
sudo apt install git
```
Проверьте успешность установки:
```bash
git --version
```
[Скриншот терминала с версией Git]
Шаг 3. Настройте обязательные параметры — имя и email (используйте свои реальные данные, или учебные, если предпочитаете не использовать личную информацию в рамках практики курса):
```bash
git config --global user.name "Иван Петров"
git config --global user.email "ivan.petrov@example.com"
```
Шаг 4. Настройте ветку по умолчанию и редактор:
```bash
git config --global init.defaultBranch main
git config --global core.editor "nano"
```
Шаг 5. Проверьте все установленные глобальные настройки:
```bash
git config --list --global
```
Что вы увидите: список всех настроенных параметров — user.name, user.email, init.defaultbranch, core.editor и, возможно, другие, если Git или дистрибутив уже установили какие-то значения по умолчанию.
[Скриншот терминала со списком настроек]
Шаг 6. Проверьте конкретное значение отдельной настройки:
```bash
git config user.name
git config user.email
```
Шаг 7. Изучите файл конфигурации напрямую (используя уже знакомую нам команду cat):
```bash
cat ~/.gitconfig
```
Что вы увидите: содержимое файла в формате INI — секции [user], [init], [core] и так далее, с соответствующими значениями внутри каждой секции.
[Скриншот содержимого файла ~/.gitconfig]
Шаг 8. Продемонстрируйте --show-origin, чтобы увидеть, откуда именно берётся каждая настройка (полезно, когда одна и та же настройка задана на нескольких уровнях, и непонятно, какая из них реально применяется):
```bash
git config --list --show-origin | head -10
```
Что вы увидите: перед каждой парой ключ-значение указан путь к файлу, откуда эта настройка была прочитана — например, file:/home/ваш_пользователь/.gitconfig.
Шаг 9. Изучите справку по команде git config для полноты картины:
```bash
git config --help
```
(Нажмите q для выхода из просмотра справки, как мы делали с man-страницами в Блоке 2 — git --help использует тот же механизм постраничного просмотра.)
Разбор команд
Команда git config
- Назначение:** просмотр и изменение настроек Git на разных уровнях (system/global/local).
- Синтаксис:**
git config [--system|--global|--local] ключ значениедля установки;git config [--system|--global|--local] ключдля просмотра одного значения;git config --list [--global|...] [--show-origin]для просмотра всех настроек. - Основные настраиваемые ключи:**
user.name— имя, прикрепляемое к коммитам.user.email— email, прикрепляемый к коммитам.init.defaultBranch— имя ветки по умолчанию для новых репозиториев.core.editor— редактор по умолчанию для текстовых сообщений Git.color.ui— цветной вывод в терминале.- Уровни (от наименее к наиболее приоритетному):**
--system→--global→--local(по умолчанию, если не указан явный флаг и вы находитесь внутри репозитория).
Возможные ошибки
- Ошибка:** попытка создать коммит без предварительной настройки
user.name/user.email(эта ситуация возникнет уже в следующем уроке, но полезно знать заранее).
Почему возникает: Git обязательно требует эти данные для каждого коммита и отказывается создавать коммит без них.
Как определить: Git выведет сообщение с инструкцией настроить user.name и user.email через git config.
Как исправить/избежать: выполнить настройку, описанную в практике этого урока, до первой попытки создать коммит.
- Ошибка:** настройка, установленная на уровне
--localв одном репозитории, неожиданно не действует в другом репозитории.
Почему возникает: это ожидаемое поведение — --local настройки специфичны для конкретного репозитория (хранятся в .git/config именно этого репозитория) и не переносятся на другие репозитории автоматически.
Как исправить/избежать: для настроек, которые должны применяться ко всем вашим репозиториям, использовать --global; --local использовать осознанно только для настроек, специфичных именно для одного конкретного проекта (например, другой email для рабочего проекта).
Практические задания
- Настройте на своей системе локальную конфигурацию email, отличающуюся от глобальной, для тестовой директории (создайте директорию, инициализируйте её как git-репозиторий командой
git init, которую подробно разберём в следующем уроке, но можно попробовать уже сейчас —git initсоздаёт пустой репозиторий), выполнитеgit config --local user.email "другой@email.com"внутри неё, и убедитесь черезgit config --list --show-origin, что локальная настройка действительно перекрывает глобальную именно в этой директории, но не влияет на другие. - Изучите (через
git config --helpили поиск в интернете) настройкуcredential.helper, которая управляет тем, как Git запоминает учётные данные для удалённых репозиториев — опишите в конспекте, для чего она может быть полезна (мы вернёмся к этой теме подробнее в контексте GitHub в уроке 16.5). - Сравните содержимое файла
~/.gitconfigдо и после выполнения практики этого урока (если вы сохранили его исходное содержимое, или просто опишите разницу на основе того, что вы уже знаете о выполненных изменениях) — запишите в конспект, какие именно строки появились в файле в результате командgit config --global.
Проверка знаний
Вопрос 1. Зачем Git требует обязательной настройки user.name и user.email перед созданием коммитов, и где эта информация впоследствии используется?
Ответ: Эта информация автоматически прикрепляется к каждому создаваемому коммиту как метаданные об авторе — постоянная часть истории проекта. Это критически важно при совместной работе нескольких людей над одним репозиторием: именно по этим данным можно точно определить, кто и когда внёс конкретное изменение, что необходимо для координации работы команды, разбора причин ошибок и общей прозрачности процесса разработки.
Вопрос 2. В чём разница между настройками уровня --global и --local, и в какой ситуации имеет смысл использовать --local вместо --global?
Ответ: --global применяется ко всем репозиториям текущего пользователя на данном компьютере (хранится в ~/.gitconfig), тогда как --local применяется только к одному конкретному репозиторию, в котором была выполнена команда (хранится в .git/config этого репозитория), и переопределяет глобальную настройку именно для этого репозитория. --local уместен, когда для конкретного проекта нужны отличающиеся от обычных настройки — например, использование рабочего email для рабочих проектов при том, что глобально настроен личный email для остальных, личных проектов.
Итоги урока
Вы изучили: процесс установки Git через APT, обязательность настройки user.name/user.email, три уровня конфигурации (system/global/local) и их приоритет, дополнительные полезные настройки (init.defaultBranch, core.editor).
Вы умеете: устанавливать Git, настраивать глобальную и локальную конфигурацию, просматривать текущие настройки и определять их источник.
В следующем уроке потребуется: настроенный и готовый к работе Git — теперь мы создадим свой первый репозиторий и научимся базовому циклу работы с коммитами.
Урок 16.3. Базовый цикл работы: `init`, `add`, `commit`, `status`, `log`
Освоить фундаментальный рабочий цикл Git: создание репозитория, отслеживание изменений файлов, подготовку изменений к коммиту, создание коммитов с осмысленными сообщениями, и просмотр истории проекта.
Теория
Три состояния файлов в Git — концептуальная основа рабочего цикла. Чтобы понять базовый цикл работы, важно осмыслить, что любой отслеживаемый Git файл в репозитории может находиться в одном из нескольких состояний, соответствующих трём областям, которые мы упомянули в уроке 16.1:
- Рабочая директория (working directory) — обычные файлы на диске, которые вы редактируете любым способом (например, через
nanoили другой редактор). - Область подготовки / индекс (staging area) — промежуточная зона, куда вы явно «добавляете» изменения, которые хотите включить в следующий коммит.
- История коммитов (репозиторий,
.git/) — постоянная, зафиксированная история, куда изменения попадают только после создания коммита.
Дополнительно файлы в рабочей директории могут быть:
- Неотслеживаемые (untracked)** — новый файл, о существовании которого Git ещё не знает (никогда не был добавлен).
- Отслеживаемые, но изменённые (modified)** — файл, который Git уже знает, но в него внесены изменения после последнего коммита, ещё не подготовленные к следующему коммиту.
- Подготовленные (staged)** — изменения, добавленные в область подготовки, готовые войти в следующий коммит.
- Зафиксированные (committed)** — изменения, уже сохранённые в истории коммитов.
Команда git init — создание нового репозитория.
```bash
git init
```
Выполненная внутри директории, эта команда превращает обычную директорию в Git-репозиторий, создавая внутри неё скрытую поддиректорию .git/, где Git будет хранить всю служебную информацию — историю коммитов, настройки, ветки и так далее. Директория .git/ — это, по сути, «сердце» репозитория; если её удалить, вся история Git будет безвозвратно потеряна (хотя сами файлы рабочей директории, в их текущем состоянии на момент удаления, останутся нетронутыми).
Команда git status — просмотр текущего состояния. Одна из самых часто используемых команд Git — показывает, какие файлы изменены, какие подготовлены к коммиту, какие вообще не отслеживаются:
```bash
git status
```
Хорошая практика — выполнять git status практически на каждом шаге работы с Git, особенно пока вы только осваиваетесь с инструментом, чтобы всегда чётко понимать текущее состояние.
Команда git add — подготовка изменений (staging).
```bash
git add имя_файла # добавить конкретный файл в область подготовки
git add файл1 файл2 # добавить несколько конкретных файлов
git add . # добавить ВСЕ изменённые и новые файлы в текущей директории и поддиректориях
git add *.txt # добавить все файлы, соответствующие шаблону (glob-паттерн, знакомый нам из Блока 5 и урока 15.5)
```
Важно осмыслить: git add не «сохраняет» изменение в истории — он лишь помечает изменение как готовое к включению в следующий коммит. Это позволяет очень гибко контролировать содержимое каждого коммита: например, если вы изменили пять разных файлов по разным, логически не связанным причинам, вы можете создать несколько отдельных, тематически осмысленных коммитов, добавляя (git add) в каждый только те файлы, которые относятся к конкретному изменению, вместо одного большого «коммита всего подряд».
Команда git commit — создание коммита.
```bash
git commit -m "Осмысленное сообщение о том, что было изменено"
```
Флаг -m («message») позволяет указать сообщение коммита прямо в команде. Без -m Git откроет текстовый редактор (тот, что мы настроили в предыдущем уроке через core.editor) для ввода более развёрнутого сообщения — это часто используется для более сложных коммитов, требующих подробного описания в несколько строк.
Как писать хорошие сообщения коммитов — важная практика, а не формальность. Сообщение коммита — это не просто техническая необходимость, а способ коммуникации с будущими читателями истории проекта (включая вас самих через полгода). Общепринятые рекомендации:
- Пишите в повелительном наклонении настоящего времени: «Исправить ошибку в скрипте бэкапа», а не «Исправил ошибку» (это негласное соглашение большей части сообщества Git, хотя строгого технического требования нет).
- Первая строка — краткая суть изменения (традиционно рекомендуется укладываться в 50 символов, хотя это не жёсткое ограничение).
- Если нужны подробности — оставьте первую строку короткой, пропустите пустую строку, и добавьте развёрнутое описание ниже (это требует использования интерактивного редактора, а не одной строки через
-m). - Избегайте бессмысленных сообщений вроде «изменения», «фикс», «работает» — они не несут никакой информации при просмотре истории спустя время.
Команда git log — просмотр истории коммитов.
```bash
git log
```
Выводит список всех коммитов текущей ветки, от самого нового к самому старому, показывая для каждого: уникальный идентификатор коммита (хеш, о котором чуть ниже), автора, дату, и сообщение.
Полезные модификаторы git log:
```bash
git log --oneline # компактный вывод, по одной строке на коммит
git log -n 5 # только последние 5 коммитов
git log --oneline --graph # с визуализацией разветвлений истории (особенно полезно после изучения веток в уроке 16.4)
git log -p # показать полное содержимое каждого изменения (diff, детально в разборе команд)
git log --author="Имя" # только коммиты конкретного автора
```
Хеш коммита. Каждый коммит в Git идентифицируется уникальным хешем — длинной шестнадцатеричной строкой (например, a1b2c3d4e5f6...), вычисляемой на основе содержимого самого коммита (изменённых файлов, сообщения, автора, времени, и ссылки на предыдущий коммит) с помощью криптографической хеш-функции SHA-1. Это гарантирует, что каждый коммит имеет абсолютно уникальный идентификатор, и что любое, даже минимальное изменение содержимого коммита привело бы к совершенно другому хешу — это фундаментальный механизм, обеспечивающий целостность истории Git. На практике для ссылки на коммит обычно достаточно первых 7-8 символов хеша — этого практически всегда достаточно для однозначной идентификации в пределах одного репозитория.
Команда git diff — просмотр конкретных различий.
```bash
git diff # различия между рабочей директорией и областью подготовки (то есть неподготовленные изменения)
git diff --staged # различия между областью подготовки и последним коммитом (то есть что попадёт в следующий коммит)
```
Это чрезвычайно полезная команда для проверки именно того, что вы собираетесь зафиксировать, прежде чем реально создавать коммит — хорошая практика перед каждым git commit.
Файл .gitignore — исключение файлов из отслеживания. Часто в проекте есть файлы, которые не должны попадать под контроль версий: временные файлы, логи, файлы с чувствительными данными (пароли, ключи), файлы, генерируемые автоматически. Специальный файл .gitignore в корне репозитория содержит шаблоны имён файлов, которые Git должен игнорировать — они не будут показываться как «неотслеживаемые» в git status и не будут случайно добавлены командой git add .:
```
*.log
*.tmp
секретный_файл.txt
/temp/
```
Практика
Шаг 1. Создайте новый учебный репозиторий:
```bash
mkdir -p ~/git_practice
cd ~/git_practice
git init
```
Что вы увидите: сообщение вида Initialized empty Git repository in /home/ваш_пользователь/git_practice/.git/.
[Скриншот терминала]
Шаг 2. Изучите созданную скрытую директорию .git/ (используя знакомые нам из Блока 5 приёмы работы со скрытыми файлами):
```bash
ls -la
ls -la .git/
```
Что вы увидите: внутреннюю структуру Git-репозитория — директории для объектов, ссылок, файл конфигурации и другие служебные элементы.
Шаг 3. Проверьте статус только что созданного, пустого репозитория:
```bash
git status
```
Что вы увидите: сообщение о том, что ветка main не имеет коммитов, и нет файлов для отслеживания — репозиторий полностью пуст.
Шаг 4. Создайте первый файл проекта и снова проверьте статус:
```bash
echo "# Мой первый проект" > README.md
git status
```
Что вы увидите: файл README.md теперь отображается в разделе «Untracked files» (неотслеживаемые файлы) — Git видит файл, но пока не отслеживает его историю.
[Скриншот терминала с untracked файлом]
Шаг 5. Добавьте файл в область подготовки и снова проверьте статус:
```bash
git add README.md
git status
```
Что вы увидите: файл переместился в раздел «Changes to be committed» (изменения, готовые к коммиту) — он подготовлен, но ещё не зафиксирован в истории.
[Скриншот терминала со staged файлом]
Шаг 6. Создайте первый коммит:
```bash
git commit -m "Добавить файл README с описанием проекта"
```
Что вы увидите: сообщение о созданном коммите с указанием ветки, кратким хешем и статистикой изменённых файлов.
[Скриншот терминала с результатом коммита]
Шаг 7. Проверьте статус ещё раз — теперь всё должно быть «чисто»:
```bash
git status
```
Что вы увидите: nothing to commit, working tree clean — все изменения зафиксированы, рабочая директория полностью соответствует последнему коммиту.
Шаг 8. Посмотрите историю коммитов:
```bash
git log
```
Шаг 9. Внесите изменение в файл и создайте ещё несколько коммитов для практики, применяя весь цикл add → status → commit:
```bash
echo "" >> README.md
echo "Этот проект создан в рамках изучения Git." >> README.md
git status
git diff
```
Что покажет git diff: построчное сравнение — какие строки были добавлены (обычно отмечены + и зелёным цветом в терминале, если поддерживается) по сравнению с последним коммитом.
[Скриншот вывода git diff]
```bash
git add README.md
git diff --staged
```
Что покажет git diff --staged: то же самое изменение, но теперь как «то, что попадёт в следующий коммит» (поскольку мы уже выполнили git add).
```bash
git commit -m "Добавить описание проекта в README"
```
Шаг 10. Создайте ещё один файл — простой bash-скрипт (используем знания Блока 15):
```bash
cat > hello.sh << 'EOF'
#!/bin/bash
echo "Привет из моего первого Git-проекта!"
EOF
chmod +x hello.sh
git status
git add hello.sh
git commit -m "Добавить приветственный скрипт"
```
Шаг 11. Посмотрите итоговую историю в компактном виде:
```bash
git log --oneline
```
Что вы увидите: три строки — по одной на каждый созданный коммит, с кратким хешем и сообщением.
[Скриншот истории коммитов]
Шаг 12. Создайте файл .gitignore и продемонстрируйте его работу:
```bash
echo "секретный лог: $(date)" > debug.log
git status
```
Что вы увидите: debug.log появился как неотслеживаемый файл.
```bash
echo "*.log" > .gitignore
git status
```
Что вы увидите: debug.log больше не отображается среди неотслеживаемых файлов — он теперь игнорируется благодаря шаблону в .gitignore. Сам .gitignore при этом отображается как новый файл — его как раз стоит добавить и закоммитить, чтобы этот же список игнорируемых файлов применялся при работе с этим репозиторием на любом другом компьютере или другим человеком:
```bash
git add .gitignore
git commit -m "Добавить .gitignore для исключения лог-файлов"
```
[Скриншот терминала с работающим .gitignore]
Шаг 13. Изучите полную историю ещё раз, теперь уже с четырьмя коммитами:
```bash
git log --oneline
```
Разбор команд
Команда git init
- Назначение:** создать новый Git-репозиторий в текущей директории.
- Синтаксис:**
git init [имя_директории]— без аргумента инициализирует текущую директорию, с аргументом — создаёт новую директорию с указанным именем и инициализирует репозиторий в ней.
Команда git status
- Назначение:** показать текущее состояние рабочей директории и области подготовки относительно последнего коммита.
- Синтаксис:**
git status [опции];git status -s(short) — компактный однострочный формат вывода.
Команда git add
- Назначение:** добавить изменения (новые или изменённые файлы) в область подготовки для включения в следующий коммит.
- Синтаксис:
git add файл1 [файл2 ...];git add .— все изменения в текущей директории и поддиректориях;git add -p— интерактивный режим, позволяющий выбирать, какие именно части** изменённого файла добавить (продвинутая техника, полезная для очень точного контроля содержимого коммитов).
Команда git commit
- Назначение:** зафиксировать подготовленные изменения как новый коммит в истории.
- Синтаксис:
git commit -m "сообщение"; без-mоткрывается текстовый редактор для ввода сообщения;git commit -am "сообщение"— комбинация, которая автоматически добавляет в подготовку (add) все уже отслеживаемые (но не новые) изменённые файлы и сразу коммитит — удобное сокращение, но не подготавливает новые**, ранее не отслеживаемые файлы.
Команда git log
- Назначение:** показать историю коммитов.
- Синтаксис:**
git log [опции];--oneline,-n N,--graph,-p,--author="имя"— см. теорию.
Команда git diff
- Назначение:** показать построчные различия между разными состояниями файлов.
- Синтаксис:**
git diff(рабочая директория vs область подготовки),git diff --staged(область подготовки vs последний коммит),git diff коммит1 коммит2(различия между двумя произвольными коммитами).
Возможные ошибки
- Ошибка:**
nothing added to commit but untracked files presentпри попыткеgit commit.
Почему возникает: попытка закоммитить, когда есть неотслеживаемые (новые) файлы, но ни один из них не был предварительно добавлен через git add.
Как исправить: сначала выполнить git add файл (или git add . для всех) для нужных файлов, затем git commit.
- Ошибка:** случайно закоммичен файл, который не должен был попасть в историю (например, файл с чувствительными данными).
Почему возникает: файл не был вовремя добавлен в .gitignore, и был по невнимательности добавлен через git add ..
Как определить: файл виден в git log -p или через git show для соответствующего коммита.
Как исправить: это отдельная и не самая тривиальная задача — если коммит ещё не был отправлен на удалённый сервер (материал урока 16.5), можно исправить последний коммит через git commit --amend; если уже был отправлен — потребуются более продвинутые техники переписывания истории, которые выходят за рамки этого вводного курса, и в случае действительно чувствительных данных (паролей, ключей) главная рекомендация — считать их скомпрометированными и немедленно сменить, независимо от того, удастся ли «вычистить» их из истории Git.
Как избежать: всегда настраивать .gitignore до первого коммита нового проекта, особенно для директорий, где могут появиться файлы с чувствительными данными; внимательно проверять git status и git diff --staged перед каждым git commit.
Практические задания
- Создайте новый учебный репозиторий, добавьте в него минимум три файла разного типа (текстовый файл, bash-скрипт, файл с расширением, которое вы решите добавить в
.gitignore) с отдельными, осмысленными коммитами для каждого логического изменения. - Изучите вывод
git log -pдля одного из ваших коммитов — найдите в выводе строки, начинающиеся с+и-, и объясните в конспекте, что они означают. - Намеренно измените файл, но не добавляйте изменение в область подготовки (
git add), и изучите разницу между выводомgit diff(без флага) иgit diff --stagedв этой ситуации — объясните в конспекте, почемуgit diff --stagedв данном случае покажет пустой вывод.
Проверка знаний
Вопрос 1. В чём смысл существования отдельного шага git add перед git commit — почему нельзя просто сразу коммитить любые изменения в рабочей директории?
Ответ: Область подготовки (staging area), заполняемая через git add, даёт точный контроль над тем, что именно попадёт в следующий коммит. Если вы изменили несколько файлов по разным, логически не связанным причинам, можно разделить их на отдельные, тематически осмысленные коммиты, добавляя в каждый коммит только относящиеся к нему файлы — вместо того чтобы быть вынужденным фиксировать все накопившиеся изменения одним большим, малопонятным коммитом.
Вопрос 2. Что делает файл .gitignore, и почему рекомендуется настраивать его в самом начале работы над проектом, а не когда уже возникла проблема?
Ответ: .gitignore содержит шаблоны имён файлов, которые Git должен полностью игнорировать — они не появляются как «неотслеживаемые» в git status и не попадают под действие git add .. Настройка его заранее предотвращает случайное включение в историю нежелательных файлов — временных, автоматически генерируемых, или (что особенно важно) содержащих чувствительные данные вроде паролей или ключей. Если такие данные всё же попали в историю коммитов до настройки .gitignore, их удаление из истории — гораздо более сложная задача, чем простое предотвращение проблемы заранее, особенно если история уже была передана на удалённый сервер и, возможно, другим людям.
Итоги урока
Вы изучили: три состояния файлов и три области Git (рабочая директория, область подготовки, история), команды init/status/add/commit/log/diff, принципы написания хороших сообщений коммитов, назначение .gitignore.
Вы умеете: создавать репозиторий, отслеживать и подготавливать изменения, создавать осмысленные коммиты, просматривать историю проекта и конкретные различия между версиями.
В следующем уроке потребуется: понимание базового цикла работы — теперь мы научимся работать с несколькими параллельными линиями разработки через ветки.
Урок 16.4. Ветки: `branch`, `checkout`, `merge`
Понять концепцию веток в Git, научиться создавать новые ветки, переключаться между ними, и объединять изменения из разных веток обратно в основную линию разработки.
Теория
Зачем нужны ветки. Представьте, что вы работаете над стабильным, рабочим проектом, и хотите попробовать рискованное экспериментальное изменение — новую функциональность, крупный рефакторинг, или просто идею, в успехе которой не уверены. Если вносить такие изменения прямо в основную линию разработки, вы рискуете сломать стабильную, рабочую версию, пока эксперимент не будет доведён до конца (или отменён). Ветки (branches) решают эту проблему: они позволяют создать полностью независимую линию разработки, работать в ней сколько угодно, не затрагивая основную ветку, и либо впоследствии объединить (merge) успешный результат обратно, либо просто удалить неудачную ветку без каких-либо последствий для основной линии.
Ветка технически — это просто указатель (ссылка) на конкретный коммит. Это важное концептуальное упрощение: ветка в Git — не «копия» всех файлов проекта (как можно было бы интуитивно предположить), а лёгкий, крайне дешёвый в создании указатель на определённый коммит в истории. Когда вы создаёте новый коммит, находясь в определённой ветке, указатель этой ветки автоматически «продвигается» вперёд, начиная указывать на новый коммит. Именно поэтому создание веток в Git — операция, выполняющаяся практически мгновенно, независимо от размера проекта — в отличие от некоторых других систем контроля версий, где ветвление могло быть весьма ресурсоёмкой операцией.
Ветка main (или исторически master) — ветка, создаваемая автоматически при инициализации нового репозитория (git init), обычно используемая как основная, стабильная линия разработки.
Команда git branch — управление ветками:
```bash
git branch # список всех локальных веток, текущая отмечена звёздочкой *
git branch имя_новой_ветки # создать новую ветку (но не переключиться на неё автоматически!)
git branch -d имя_ветки # удалить ветку (безопасно — только если она уже слита с текущей)
git branch -D имя_ветки # принудительно удалить ветку, даже если изменения не слиты (используйте осторожно!)
```
Команда git checkout — переключение между ветками.
```bash
git checkout имя_ветки
```
Переключает HEAD (указатель на «текущее место», о котором мы говорили в уроке 16.1) на указанную ветку — все файлы в рабочей директории автоматически изменяются, чтобы соответствовать состоянию последнего коммита этой ветки.
Комбинированная команда — создать и сразу переключиться:
```bash
git checkout -b имя_новой_ветки
```
Флаг -b («branch») создаёт новую ветку и одновременно переключается на неё — это наиболее часто используемый способ начать работу над новой веткой, объединяющий две отдельные операции (git branch + git checkout) в одну команду.
Современная альтернатива — команда git switch. В относительно недавних версиях Git (начиная с версии 2.23) была добавлена более специализированная команда git switch, предназначенная исключительно для переключения между ветками (в отличие от git checkout, которая исторически выполняет также и другие, не связанные с ветками операции, что иногда приводило к путанице):
```bash
git switch имя_ветки # переключиться на существующую ветку
git switch -c имя_новой_ветки # создать новую ветку и переключиться на неё (аналог checkout -b)
```
В этом курсе мы будем использовать преимущественно git checkout как исторически более распространённую и всё ещё повсеместно используемую команду, но полезно знать о существовании более новой и, по мнению многих, более понятной альтернативы git switch.
Команда git merge — объединение веток.
```bash
git checkout main # сначала переключитесь на ветку, В КОТОРУЮ хотите влить изменения
git merge имя_другой_ветки # влить изменения из указанной ветки в текущую
```
Два основных сценария слияния:
- Fast-forward merge («перемотка вперёд»). Если с момента создания вашей ветки в основной ветке (
main) не было сделано никаких новых коммитов, Git может просто «передвинуть» указательmainвперёд, к последнему коммиту вашей ветки — без создания какого-либо специального «коммита слияния». Это самый простой случай слияния.
- Три-way merge (трёхстороннее слияние, с созданием коммита слияния). Если в обеих ветках были сделаны независимые изменения после точки их расхождения, Git создаёт специальный коммит слияния (merge commit) — коммит с двумя «родителями» (ссылками на последние коммиты обеих объединяемых веток), фиксирующий сам факт объединения и результат совмещения изменений.
Конфликты слияния (merge conflicts) — неизбежная часть работы с ветками. Если одна и та же часть одного и того же файла была изменена по-разному в обеих объединяемых ветках, Git не может автоматически решить, какое из двух изменений правильное — это называется конфликтом слияния. В этом случае Git приостанавливает процесс слияния и явно помечает конфликтующие места прямо в содержимом файла специальными маркерами:
```
<<<<<<< HEAD
Это содержимое из текущей ветки (main)
=======
Это содержимое из вливаемой ветки
>>>>>>> имя_другой_ветки
```
Разработчик должен вручную открыть файл, изучить оба варианта, отредактировать файл до желаемого финального состояния (удалив служебные маркеры <<<<<<<, =======, >>>>>>>), а затем явно подтвердить разрешение конфликта:
```bash
git add файл_с_разрешённым_конфликтом
git commit
```
(В случае конфликта Git обычно автоматически подготавливает сообщение коммита слияния — часто достаточно просто сохранить его, если явно не открыт -m при коммите разрешения конфликта.)
Просмотр графа веток. Мы уже упоминали в предыдущем уроке git log --oneline --graph — эта команда особенно полезна именно после появления нескольких веток, поскольку визуально показывает, где ветки расходились и объединялись, в виде текстового «графа» из символов *, |, \, /.
Практика
Шаг 1. Продолжим работу в репозитории ~/git_practice из предыдущего урока (если вы его удалили — заново инициализируйте с парой коммитов по аналогии с практикой урока 16.3):
```bash
cd ~/git_practice
git log --oneline
```
Шаг 2. Посмотрите текущие ветки:
```bash
git branch
```
Что вы увидите: единственная ветка main (или master, в зависимости от настроек), отмеченная звёздочкой как текущая.
Шаг 3. Создайте и сразу переключитесь на новую ветку для эксперимента:
```bash
git checkout -b experiment-new-feature
```
Что вы увидите: сообщение Switched to a new branch 'experiment-new-feature'.
[Скриншот терминала]
Шаг 4. Убедитесь, что вы действительно на новой ветке:
```bash
git branch
```
Что вы увидите: теперь звёздочкой отмечена experiment-new-feature, а не main.
Шаг 5. Внесите изменения именно в этой экспериментальной ветке:
```bash
echo "" >> README.md
echo "## Экспериментальная функция" >> README.md
echo "Это описание пробной функции, которая может не войти в основную версию." >> README.md
git add README.md
git commit -m "Добавить описание экспериментальной функции"
```
Шаг 6. Создайте ещё один файл, специфичный для этой ветки:
```bash
echo "Это экспериментальный код" > experiment.txt
git add experiment.txt
git commit -m "Добавить экспериментальный файл"
```
Шаг 7. Переключитесь обратно на main и заметьте, что изменений, сделанных в экспериментальной ветке, здесь не видно:
```bash
git checkout main
ls
cat README.md
```
Что вы увидите: файла experiment.txt не существует в текущей директории, а README.md не содержит раздела про экспериментальную функцию — потому что вы находитесь в ветке main, где этих изменений никогда не было; они существуют только в ветке experiment-new-feature.
[Скриншот терминала, демонстрирующий изоляцию веток]
Шаг 8. Переключитесь обратно на экспериментальную ветку, чтобы убедиться, что изменения там на месте:
```bash
git checkout experiment-new-feature
ls
cat README.md
```
Что вы увидите: файл experiment.txt снова присутствует, и README.md содержит добавленный ранее раздел.
Шаг 9. Убедите себя, что эксперимент удался, и слейте его обратно в main. Сначала переключитесь на main (ветку-назначение, куда вливаем):
```bash
git checkout main
```
Шаг 10. Выполните слияние:
```bash
git merge experiment-new-feature
```
Что вы увидите: поскольку main не изменялась с момента создания экспериментальной ветки, произойдёт fast-forward слияние — Git просто «передвинет» указатель main вперёд.
[Скриншот терминала с результатом слияния]
Шаг 11. Проверьте, что изменения из экспериментальной ветки теперь присутствуют и в main:
```bash
ls
cat README.md
git log --oneline
```
Шаг 12. Удалите ставшую ненужной экспериментальную ветку (её история уже слита в main, сама ветка как отдельный указатель больше не нужна):
```bash
git branch -d experiment-new-feature
git branch
```
Что вы увидите: снова только одна ветка — main, экспериментальная ветка удалена (но её коммиты остались в истории main, поскольку были слиты).
Шаг 13. Теперь смоделируйте ситуацию с настоящим конфликтом слияния. Создайте новую ветку:
```bash
git checkout -b conflict-demo
echo "Версия строки: из ветки conflict-demo" >> README.md
git add README.md
git commit -m "Изменение в ветке conflict-demo"
```
Шаг 14. Переключитесь на main и внесите другое изменение в ту же примерную область файла:
```bash
git checkout main
echo "Версия строки: из ветки main" >> README.md
git add README.md
git commit -m "Изменение прямо в main"
```
Шаг 15. Попробуйте слить conflict-demo в main — на этот раз возникнет конфликт:
```bash
git merge conflict-demo
```
Что вы увидите: сообщение CONFLICT (content): Merge conflict in README.md — Git не смог автоматически объединить изменения.
[Скриншот терминала с конфликтом]
Шаг 16. Изучите файл с конфликтом:
```bash
cat README.md
```
Что вы увидите: специальные маркеры <<<<<<< HEAD, =======, >>>>>>> conflict-demo, разделяющие два конфликтующих варианта содержимого.
Шаг 17. Разрешите конфликт вручную — откройте файл в редакторе:
```bash
nano README.md
```
Найдите конфликтующий участок, решите, какую версию (или комбинацию обеих) оставить, и удалите служебные маркеры <<<<<<<, =======, >>>>>>> полностью. Например, оставьте только:
```
Версия строки: объединённая версия из обеих веток
```
Сохраните файл.
Шаг 18. Подтвердите разрешение конфликта:
```bash
git status
```
Что вы увидите: README.md отмечен как «both modified» — конфликт есть, но не разрешён формально до git add.
```bash
git add README.md
git commit -m "Разрешить конфликт слияния между main и conflict-demo"
```
(Git обычно уже подготавливает сообщение коммита для слияния — можно просто оставить его как есть при использовании интерактивного редактора, либо явно указать своё через -m, как в примере выше.)
Шаг 19. Убедитесь, что конфликт разрешён и история корректна:
```bash
git log --oneline --graph
git branch -d conflict-demo
```
[Скриншот итоговой истории с визуализацией слияния]
Разбор команд
Команда git branch
- Назначение:** просмотр, создание и удаление веток.
- Синтаксис:**
git branch(список),git branch имя(создать, без переключения),git branch -d имя(удалить, безопасно),git branch -D имя(удалить принудительно).
Команда git checkout
- Назначение:** переключение между ветками (а также, в более широком смысле, между разными состояниями рабочей директории — включая, например, отдельные коммиты, что выходит за рамки этого вводного курса).
- Синтаксис:**
git checkout имя_ветки;git checkout -b имя_новой_ветки— создать и сразу переключиться.
Команда git switch (современная альтернатива)
- Назначение:** переключение между ветками — более специализированная и однозначная по смыслу команда, чем многофункциональный
git checkout. - Синтаксис:**
git switch имя_ветки;git switch -c имя_новой_ветки.
Команда git merge
- Назначение:** объединить изменения из указанной ветки в текущую ветку (ту, на которой вы находитесь в момент выполнения команды).
- Синтаксис:
git merge имя_ветки(выполняется, находясь на ветке-назначении**, куда должны попасть изменения). - Fast-forward** — простое передвижение указателя, без коммита слияния (когда история не разошлась).
- Три-way merge** — создание коммита слияния с двумя родителями (когда обе ветки имели независимые новые коммиты).
- Конфликт слияния** — требует ручного разрешения, если одна и та же часть файла была изменена по-разному в обеих ветках.
Возможные ошибки
- Ошибка:** внесение изменений в файлы, находясь «не в той» ветке, по невнимательности.
Почему возникает: забыли проверить текущую ветку через git branch или git status (последняя тоже показывает текущую ветку в первой строке вывода) перед началом работы.
Как определить: изменения появляются не там, где ожидалось — или наоборот, ожидаемые изменения из другой ветки «отсутствуют».
Как исправить/избежать: взять за привычку проверять текущую ветку (git branch или первая строка git status) в начале каждой рабочей сессии, особенно при работе с несколькими параллельными задачами.
- Ошибка:** попытка переключиться на другую ветку (
git checkout), когда в текущей ветке есть незакоммиченные изменения, конфликтующие с состоянием целевой ветки.
Почему возникает: Git не позволяет потерять несохранённые изменения при переключении, если целевая ветка отличается в тех же местах файла.
Как определить: сообщение вида error: Your local changes to the following files would be overwritten by checkout.
Как исправить: либо закоммитить текущие изменения (git add + git commit) перед переключением, либо (более продвинутая техника, не разбираемая подробно в этом курсе) временно «отложить» изменения через git stash, переключиться, и затем вернуть их обратно позже.
- Ошибка:** конфликт слияния пугает начинающих и воспринимается как «поломка» репозитория.
Почему возникает: непонимание того, что конфликт — это совершенно нормальная, ожидаемая часть работы с ветками, а не признак ошибки или проблемы в самом Git.
Как исправить/избежать: спокойно следовать процедуре разрешения конфликта, описанной в практике этого урока — изучить оба варианта, отредактировать файл до желаемого состояния, удалить служебные маркеры, git add + git commit. Ничего не «сломано» — Git просто корректно распознал ситуацию, требующую человеческого решения, которое не может быть принято автоматически.
Практические задания
- Создайте новую ветку
feature-logging, добавьте в ней новый файлlogger.shс простым скриптом логирования (можно использовать материал Блока 15), закоммитьте изменение, затем слейте ветку обратно вmainи удалите использованную ветку. - Намеренно создайте ситуацию с конфликтом слияния между двумя новыми ветками (не с
main), разрешите конфликт, и опишите в конспекте пошагово, что именно вы делали на каждом этапе, как если бы объясняли процесс коллеге, впервые столкнувшемуся с конфликтом. - Изучите (через
git log --oneline --graph --all, где флаг--allпоказывает все ветки, а не только текущую) визуализацию истории вашего репозитория~/git_practiceпосле выполнения практики этого урока — опишите в конспекте, что означают символы*,|и точки схождения линий на этом графе.
Проверка знаний
Вопрос 1. Что технически представляет собой «ветка» в Git, и почему создание новой ветки — практически мгновенная операция независимо от размера проекта?
Ответ: Ветка — это лёгкий указатель (ссылка) на определённый коммит в истории, а не полная копия всех файлов проекта. Создание новой ветки — это просто создание нового указателя, ссылающегося на текущий коммит; сами файлы и история при этом не копируются и не дублируются физически. Именно поэтому эта операция выполняется мгновенно даже в очень больших проектах — Git не нужно копировать никакие данные, только создать новую, крошечную по объёму ссылку.
Вопрос 2. Что такое конфликт слияния, когда он возникает, и как правильно его разрешить?
Ответ: Конфликт слияния возникает, когда одна и та же часть одного и того же файла была изменена по-разному в обеих объединяемых ветках, и Git не может автоматически определить, какое из изменений должно «победить». Git приостанавливает слияние и помечает конфликтующие участки специальными маркерами (<<<<<<<, =======, >>>>>>>) прямо внутри файла. Разработчик должен вручную отредактировать файл до желаемого финального состояния (решив, какую версию оставить или как их объединить), удалить служебные маркеры, а затем выполнить git add для файла и git commit, чтобы явно завершить и зафиксировать разрешение конфликта.
Итоги урока
Вы изучили: концепцию веток как лёгких указателей на коммиты, команды git branch/git checkout/git switch/git merge, разницу между fast-forward и three-way слиянием, механизм и процедуру разрешения конфликтов слияния.
Вы умеете: создавать ветки для изолированной разработки, переключаться между ними, объединять их обратно в основную линию, разрешать возникающие конфликты слияния.
В последнем уроке этого блока потребуется: понимание локальной работы с ветками и коммитами — теперь мы научимся синхронизировать репозиторий с удалённым сервером, в первую очередь с GitHub.
Урок 16.5. Удалённые репозитории: `clone`, `push`, `pull`, GitHub
Понять концепцию удалённых репозиториев, освоить команды clone/push/pull/fetch, настроить безопасное подключение к GitHub через SSH-ключи (материал Блока 13), и выполнить полный цикл работы с удалённым репозиторием.
Теория
Зачем нужны удалённые репозитории. Всё, что мы изучали в предыдущих уроках, происходило исключительно на вашем локальном компьютере. Но реальная ценность распределённой системы контроля версий раскрывается при совместной работе: нескольким людям нужен единый, доступный всем участникам источник истины (хотя, как мы помним из урока 16.1, полная копия истории есть у каждого), и способ обмениваться изменениями друг с другом. Удалённый репозиторий (remote) — это ещё одна копия того же самого репозитория, расположенная на другом компьютере — обычно на специализированном сервере, доступном через сеть.
GitHub — крупнейшая в мире платформа для хостинга Git-репозиториев. Важно чётко разделять две разные вещи: Git — это сама технология контроля версий (программа, работающая локально на вашем компьютере), тогда как GitHub — это отдельный, коммерческий веб-сервис (принадлежащий компании Microsoft), предоставляющий удобное место для хранения Git-репозиториев в сети, с дополнительными возможностями для совместной работы (обсуждения, отслеживание задач, автоматизация и многое другое, выходящее за рамки этого вводного урока). Существуют и альтернативные сервисы того же назначения — GitLab, Bitbucket, Codeberg, — но GitHub на сегодняшний день наиболее популярен и широко используется в индустрии.
Клонирование существующего репозитория — команда git clone.
```bash
git clone URL_репозитория
```
«Клонирование» — это создание полной локальной копии удалённого репозитория, включая всю его историю коммитов (вспомните принцип распределённых систем контроля версий из урока 16.1). После клонирования у вас появляется полностью самостоятельный, независимый локальный репозиторий, автоматически «знающий» об удалённом источнике, из которого он был клонирован.
Два основных способа подключения к GitHub: HTTPS и SSH.
- HTTPS** — URL вида
https://github.com/пользователь/репозиторий.gitgit push`, отправка изменений на сервер), потребуется либо ввод пароля при каждой операции (что современный GitHub на самом деле уже не поддерживает напрямую, требуя вместо простого пароля специальный «персональный токен доступа»), либо настройка специального механизма запоминания учётных данных..Для операций, требующих аутентификации (например, - SSH** — URL вида
git@github.com:пользователь/репозиторий.git. Использует уже подробно изученный нами в Блоке 13 механизм SSH-ключей — вы настраиваете пару ключей один раз, добавляете публичный ключ в свой аккаунт GitHub, и дальше все операции (включаяpush) проходят автоматически, без необходимости вводить пароль или токен при каждой операции — точно так же, как настроенный беспарольный вход на сервер по SSH-ключу, который мы делали в уроке 13.3.
В этом курсе мы будем использовать SSH-подключение к GitHub, поскольку это и более безопасный, и более удобный вариант, а материал для его настройки мы уже полностью изучили в Блоке 13.
Команда git remote — управление связями с удалёнными репозиториями.
```bash
git remote -v # показать настроенные удалённые репозитории (с URL)
git remote add origin URL_репозитория # добавить связь с удалённым репозиторием, назвав её "origin"
```
origin — общепринятое, стандартное (хотя технически не обязательное) название для «основного» удалённого репозитория, с которым связан локальный репозиторий — это просто удобное короткое имя (алиас) вместо необходимости каждый раз писать полный URL.
Команда git push — отправка локальных коммитов на удалённый репозиторий.
```bash
git push origin main
```
Отправляет коммиты из вашей локальной ветки main в ветку main удалённого репозитория с именем origin. После первого выполнения этой команды с флагом -u (см. ниже), для последующих отправок в эту же связку локальной и удалённой ветки достаточно просто git push.
```bash
git push -u origin main
```
Флаг -u (--set-upstream) устанавливает связь по умолчанию между вашей текущей локальной веткой и указанной удалённой веткой — это нужно выполнить один раз для новой ветки, после чего Git запоминает эту связку, и все последующие git push/git pull для этой ветки можно выполнять без явного указания origin main.
Команда git pull — получение изменений с удалённого репозитория.
```bash
git pull
```
git pull фактически выполняет две операции подряд: сначала «скачивает» (fetch) новые коммиты с удалённого репозитория, затем автоматически пытается «влить» (merge) их в вашу текущую локальную ветку — то есть это, по сути, комбинация git fetch + git merge, о которых чуть ниже.
Команда git fetch — только получение, без слияния.
```bash
git fetch
```
В отличие от git pull, команда git fetch только «скачивает» новую информацию с удалённого репозитория (новые коммиты, ветки), но не пытается автоматически слить их с вашей текущей рабочей веткой. Это позволяет сначала изучить, что именно изменилось на удалённом сервере (например, через git log origin/main), и только затем осознанно решить, сливать эти изменения или нет — более осторожный подход по сравнению с git pull, который сразу пытается слияние.
Типичный полный рабочий процесс с удалённым репозиторием:
- Клонировать репозиторий (один раз, в начале работы над проектом):
git clone. - Периодически получать чужие изменения:
git pull. - Вносить свои изменения локально: обычный цикл
add/commit, изученный в уроке 16.3. - Отправлять свои изменения на сервер:
git push. - Повторять шаги 2–4 по мере продолжения работы.
Настройка SSH-ключа для GitHub — практическое применение материала Блока 13. Процесс полностью аналогичен тому, что мы делали для SSH-доступа к собственным серверам в уроке 13.3, с той разницей, что публичный ключ добавляется не в файл authorized_keys на сервере, а через веб-интерфейс настроек GitHub в вашем аккаунте.
Практика
Шаг 1. Если у вас ещё нет SSH-ключа (или вы хотите создать отдельный специально для GitHub — распространённая практика, позволяющая использовать разные ключи для разных сервисов), сгенерируйте его (детально разобрано в уроке 13.3):
```bash
ls -la ~/.ssh/
```
Если ключа id_ed25519 ещё нет, создайте его:
```bash
ssh-keygen -t ed25519 -C "мой email для GitHub"
```
(Нажмите Enter трижды, принимая значения по умолчанию, как мы делали в уроке 13.3, для учебных целей.)
Шаг 2. Выведите содержимое публичного ключа и скопируйте его (весь текст целиком, начиная с ssh-ed25519 и до конца строки):
```bash
cat ~/.ssh/id_ed25519.pub
```
[Скриншот терминала с публичным ключом]
Шаг 3. Перейдите на сайт github.com в браузере, войдите в свой аккаунт (или зарегистрируйте новый, если у вас его ещё нет — это бесплатно для базового использования), откройте раздел настроек Settings → SSH and GPG keys → New SSH key, вставьте скопированный публичный ключ, дайте ему понятное название (например, «Мой учебный компьютер, курс Linux») и сохраните.
Шаг 4. Проверьте, что подключение к GitHub через SSH работает корректно:
```bash
ssh -T git@github.com
```
Что вы увидите: при первом подключении — вопрос о подтверждении fingerprint сервера GitHub (аналогично тому, что мы видели при первом SSH-подключении в уроке 13.2) — введите yes. После этого должно появиться приветственное сообщение вида Hi ваш_логин! You've successfully authenticated, but GitHub does not provide shell access. — это ожидаемое сообщение, подтверждающее, что аутентификация прошла успешно (сам GitHub действительно не предоставляет полноценный shell-доступ, только Git-операции).
[Скриншот успешной проверки подключения]
Шаг 5. Создайте новый пустой репозиторий на GitHub через веб-интерфейс (кнопка New repository на главной странице аккаунта), назвав его, например, linux-course-practice. Не добавляйте автоматически создаваемый README на этом этапе (оставьте репозиторий полностью пустым) — это упростит первую синхронизацию с уже существующим локальным репозиторием.
Шаг 6. Скопируйте с сайта GitHub SSH-адрес созданного репозитория (обычно доступен через кнопку Code на странице репозитория, вкладка SSH) — он будет выглядеть примерно так: git@github.com:ваш_логин/linux-course-practice.git.
Шаг 7. Свяжите ваш уже существующий локальный репозиторий ~/git_practice (из предыдущих уроков) с новым удалённым репозиторием на GitHub:
```bash
cd ~/git_practice
git remote add origin git@github.com:ваш_логин/linux-course-practice.git
```
Шаг 8. Проверьте, что связь установлена корректно:
```bash
git remote -v
```
Что вы увидите: две строки — для fetch и для push — обе указывающие на один и тот же удалённый URL.
[Скриншот терминала с настроенным remote]
Шаг 9. Отправьте всю накопленную локальную историю на GitHub впервые:
```bash
git push -u origin main
```
Что вы увидите: процесс передачи данных (объектов Git) на сервер, с итоговым сообщением об успешной отправке и установленной связке между локальной и удалённой веткой main.
[Скриншот успешной первой отправки]
Шаг 10. Обновите страницу репозитория на сайте GitHub в браузере — теперь вы должны увидеть все ваши файлы (README.md, hello.sh, .gitignore и другие, созданные в практике предыдущих уроков) и полную историю коммитов, доступную через веб-интерфейс.
Шаг 11. Смоделируйте изменение, сделанное «на другом компьютере» (или другим человеком) — для практики внесите изменение прямо через веб-интерфейс GitHub: откройте файл README.md на сайте, нажмите на иконку редактирования (карандаш), добавьте строку текста, и сохраните изменение (закоммитьте прямо через веб-интерфейс, с сообщением коммита по вашему выбору).
Шаг 12. Вернитесь в терминал и получите это «удалённое» изменение в свой локальный репозиторий:
```bash
git pull
```
Что вы увидите: сообщение об успешном слиянии, и командой cat README.md вы сможете убедиться, что изменение, сделанное через веб-интерфейс, теперь присутствует и в вашей локальной копии файла.
```bash
cat README.md
git log --oneline
```
[Скриншот терминала с полученным изменением]
Шаг 13. Продемонстрируйте типичный полный цикл работы — внесите ещё одно, уже локальное изменение, и отправьте его на GitHub:
```bash
echo "" >> README.md
echo "Изменение, сделанное локально после git pull." >> README.md
git add README.md
git commit -m "Добавить локальное изменение после синхронизации"
git push
```
Обратите внимание: на этот раз мы использовали просто git push без явного указания origin main — потому что связка уже была установлена флагом -u при первой отправке в шаге 9.
Шаг 14. Проверьте итоговое состояние на сайте GitHub — обновите страницу репозитория в браузере и убедитесь, что последнее изменение появилось там же.
Разбор команд
Команда git clone
- Назначение:** создать полную локальную копию существующего удалённого репозитория, включая всю его историю.
- Синтаксис:**
git clone URL [имя_локальной_директории]— без второго аргумента имя директории берётся из названия репозитория.
Команда git remote
- Назначение:** управление связями между локальным репозиторием и удалёнными репозиториями.
- Синтаксис:**
git remote -v(список с URL),git remote add имя URL(добавить новую связь),git remote remove имя(удалить связь).
Команда git push
- Назначение:** отправить локальные коммиты на удалённый репозиторий.
- Синтаксис:**
git push [имя_удалённого] [ветка];git push -u origin main— с установкой связки по умолчанию для последующих упрощённых вызовов.
Команда git pull
- Назначение:** получить и автоматически слить изменения с удалённого репозитория в текущую локальную ветку. Фактически комбинация
git fetch+git merge. - Синтаксис:**
git pull [имя_удалённого] [ветка].
Команда git fetch
- Назначение:** только получить (скачать) новую информацию с удалённого репозитория, без автоматического слияния.
- Синтаксис:**
git fetch [имя_удалённого].
Команда ssh -T git@github.com
- Назначение:** проверить корректность SSH-аутентификации к GitHub, не выполняя никакой реальной Git-операции.
- Разбор:** флаг
-Tотключает выделение псевдотерминала для этого SSH-соединения (поскольку GitHub не предоставляет интерактивную оболочку, как отмечено в теории) — технический нюанс именно для этого специфического диагностического сценария.
Возможные ошибки
- Ошибка:**
Permission denied (publickey)при попыткеgit pushилиgit cloneпо SSH.
Почему возникает: SSH-ключ не был добавлен в аккаунт GitHub, либо используется неправильный (не тот) ключ, либо ключ не был сгенерирован вовсе.
Как определить: проверить через ssh -T git@github.com (шаг 4 практики) — если ошибка возникает уже здесь, проблема на уровне SSH, а не Git.
Как исправить: убедиться, что публичный ключ (именно .pub файл!) добавлен в настройки GitHub, и что используется соответствующий приватный ключ (при наличии нескольких ключей может понадобиться явно настроить ~/.ssh/config, как мы делали в уроке 13.4, указав IdentityFile для хоста github.com).
- Ошибка:**
git pushотклоняется с сообщениемUpdates were rejected because the remote contains work that you do not have locally.
Почему возникает: на удалённом репозитории появились новые коммиты (например, от другого участника, или, как в практике этого урока, сделанные через веб-интерфейс), которых нет в вашей локальной копии — Git не позволяет «перезаписать» удалённую историю, не будучи уверенным, что вы её видели.
Как исправить: сначала выполнить git pull, чтобы получить и слить (или разрешить конфликт, если он возникнет) недостающие изменения, и только затем повторить git push.
Как избежать: взять за привычку выполнять git pull в начале каждой рабочей сессии, особенно при совместной работе с другими людьми над одним репозиторием.
- Ошибка:** попытка
git cloneпо HTTPS URL с ожиданием, что пароль GitHub-аккаунта сработает напрямую при последующемgit push.
Почему возникает: современный GitHub больше не принимает обычный пароль аккаунта для Git-операций по HTTPS — требуется либо специальный персональный токен доступа (Personal Access Token), либо переход на SSH-аутентификацию.
Как исправить/избежать: использовать SSH-подключение (как в практике этого урока), что и является рекомендуемым подходом в данном курсе, либо, если по каким-то причинам предпочтителен HTTPS, создать и использовать персональный токен доступа через настройки GitHub (эта тема выходит за рамки данного вводного урока).
Практические задания
- Создайте на GitHub второй тестовый репозиторий и потренируйтесь клонировать его на свой локальный компьютер командой
git cloneв отдельную директорию (например,~/git_clone_test) — изучите, что содержимое сразу появляется в рабочем состоянии, а история коммитов доступна черезgit log, даже если исходно репозиторий не был создан локально вами. - Изучите разницу между
git fetch+ последующий вручнуюgit mergeи одной командойgit pull— сделайте на GitHub небольшое изменение через веб-интерфейс, затем в терминале сначала выполнитеgit fetch(без слияния) и командойgit log main..origin/main(специальный синтаксис для просмотра коммитов, которые есть вorigin/main, но ещё не в вашей локальнойmain) посмотрите на «неполученные» изменения, и только затем выполнитеgit merge origin/mainдля их применения. - Опишите в конспекте пошаговый план (без обязательного практического выполнения, если у вас нет второго компьютера или аккаунта для тестирования) того, как два разных человека могли бы совместно работать над одним репозиторием на GitHub: как получить доступ к чужому репозиторию, как избежать конфликтов при параллельной работе, и какую роль в этом процессе играют ветки (материал предыдущего урока) в сочетании с
push/pull.
Проверка знаний
Вопрос 1. В чём принципиальная разница между Git и GitHub, и почему важно чётко разделять эти два понятия?
Ответ: Git — это сама технология распределённого контроля версий, программа, работающая локально на компьютере, полностью независимая от какого-либо конкретного сервера или сервиса. GitHub — это отдельный коммерческий веб-сервис, предоставляющий удобное место для хостинга Git-репозиториев в сети вместе с дополнительными инструментами для совместной работы. Git может использоваться полностью автономно, без какого-либо подключения к GitHub или любому другому подобному сервису — GitHub лишь один из нескольких способов организовать удалённое хранение и совместный доступ к Git-репозиториям (наравне с GitLab, Bitbucket и другими).
Вопрос 2. Чем git pull отличается от git fetch, и в какой ситуации предпочтительнее использовать именно git fetch?
Ответ: git fetch только скачивает новую информацию (коммиты, ветки) с удалённого репозитория, не пытаясь автоматически слить её с текущей локальной веткой — вы можете затем изучить полученные изменения (например, через git log) и решить, сливать их или нет, осознанно выполнив git merge отдельно. git pull выполняет обе операции сразу — скачивание и немедленное автоматическое слияние. git fetch предпочтительнее, когда важно сначала изучить, что именно изменилось на удалённом сервере, прежде чем автоматически сливать эти изменения со своей текущей работой — более осторожный, контролируемый подход, особенно ценный при работе над важными или сложными изменениями.
Итоги урока
Вы изучили: концепцию удалённых репозиториев, различие между Git и GitHub, два способа подключения (HTTPS и SSH), команды clone/remote/push/pull/fetch, настройку SSH-ключа для GitHub.
Вы умеете: подключать локальный репозиторий к GitHub через SSH, отправлять и получать изменения, выполнять полный цикл совместной работы с удалённым репозиторием.
В следующем блоке потребуется: общее понимание работы с терминалом и системами — Блок 17 про виртуализацию и контейнеры не требует напрямую Git, но многие современные рабочие процессы разработки и развёртывания программного обеспечения (включая создание Docker-образов) тесно связаны именно с Git-репозиториями, откуда берётся исходный код для сборки.
Мини-проект блока
Задача: создать полноценный, реальный Git-репозиторий для хранения и версионирования bash-скриптов, написанных в Блоке 15, применяя весь материал этого блока — от инициализации до синхронизации с GitHub.
Что нужно сделать:
- Создайте новый репозиторий
~/admin-scriptsи инициализируйте его черезgit init.
- Настройте
.gitignore, исключив временные файлы, логи и любые файлы с потенциально чувствительными данными (например,.log,.tmp).
- Перенесите в этот репозиторий несколько реальных скриптов, написанных в Блоке 15 (например,
security_check.sh,backup_system.sh,log_analyzer.sh— или любые другие на ваш выбор), с отдельными, осмысленными коммитами для каждого добавленного скрипта.
- Создайте ветку
feature-improvements, и внутри неё внесите улучшение в один из скриптов (например, добавьте новую функцию, улучшите обработку ошибок используя материал урока 15.7). Закоммитьте изменение в этой ветке.
- Слейте ветку
feature-improvementsобратно вmain, используяgit merge.
- Создайте новый репозиторий на GitHub, подключите к нему локальный репозиторий через
git remote add origin, и отправьте всю историю черезgit push -u origin main.
- Добавьте файл
README.mdс кратким описанием репозитория (что это за скрипты, для чего они нужны, как ими пользоваться) — если он ещё не был создан, добавьте его сейчас, закоммитьте и отправьте на GitHub отдельным коммитом.
- Смоделируйте совместную работу: внесите небольшое изменение через веб-интерфейс GitHub (например, исправление опечатки в README), затем выполните
git pullлокально, чтобы синхронизировать изменение.
Критерий готовности: у вас есть реальный, рабочий репозиторий на GitHub с несколькими коммитами, отражающими историю разработки, минимум одной веткой, которая была создана и успешно слита обратно, и полностью синхронизированной историей между локальной и удалённой копией.
Контрольные вопросы
- Объясните, в чём разница между централизованной и распределённой системой контроля версий, и к какому из этих двух типов относится Git.
- Опишите три состояния, в которых может находиться отслеживаемый Git файл (с точки зрения рабочей директории, области подготовки и истории коммитов), и какая команда переводит файл из одного состояния в другое.
- Почему сообщение коммита важно писать осмысленным и информативным, а не формальным («изменения», «фикс»)? Приведите пример хорошего и плохого сообщения коммита.
- Что технически представляет собой ветка в Git, и почему создание новой ветки — очень дешёвая операция?
- Опишите, что такое конфликт слияния, когда он возникает, и какие шаги нужно предпринять для его разрешения.
- В чём разница между Git и GitHub?
- Объясните разницу между
git fetchиgit pull— что делает каждая из этих команд. - Зачем нужен файл
.gitignore, и почему важно настраивать его в самом начале работы над проектом?
Выводы по блоку
Git — это один из тех навыков, без которых невозможно представить современную разработку программного обеспечения и всё чаще — современное системное администрирование. Вы прошли путь от понимания фундаментальной проблемы (как надёжно отслеживать изменения файлов со временем и координировать совместную работу) до практического владения полным рабочим циклом: создание репозиториев, фиксация изменений через осмысленные коммиты, параллельная разработка через ветки, разрешение конфликтов, и синхронизация с удалённым сервером через GitHub с использованием защищённого SSH-подключения.
Важно осознавать, что Git — очень глубокий инструмент, и этот блок дал вам прочный фундамент, но далеко не исчерпывающее знание всех возможностей (продвинутые техники вроде git rebase, git stash, git cherry-pick, интерактивного добавления изменений через git add -p и многое другое остаются за рамками этого вводного курса). Тем не менее, освоенного материала более чем достаточно для полноценной, продуктивной повседневной работы — как с личными проектами, так и в качестве участника команды.
Материал этого блока будет применяться в оставшейся части курса: в Блоке 17 (Docker) исходный код приложений для сборки образов чаще всего берётся именно из Git-репозиториев; в Блоке 20 (серверное администрирование) концепция версионирования конфигурации сервера через Git — стандартная практика современного администрирования («инфраструктура как код»); а в финальном практическом проекте Блока 21 умение работать с Git может пригодиться для документирования и версионирования всего процесса развёртывания итогового проекта.
Список изученных тем
- Проблема, решаемая контролем версий; централизованные vs распределённые VCS; терминология (репозиторий, коммит, рабочая директория, область подготовки, ветка, remote, HEAD).
- Установка Git, три уровня конфигурации (system/global/local), команда
git config, обязательные настройкиuser.name/user.email. - Базовый цикл:
git init,git status,git add,git commit,git log(с модификаторами),git diff, файл.gitignore. - Ветки:
git branch,git checkout/git switch,git merge, fast-forward vs three-way merge, конфликты слияния и их разрешение. - Удалённые репозитории: разница Git/GitHub, SSH vs HTTPS подключение,
git clone,git remote,git push,git pull,git fetch, настройка SSH-ключа для GitHub.
Рекомендации перед переходом
Убедитесь, что вы умеете:
- Инициализировать репозиторий и провести файл через полный цикл: изменение →
add→commit, с осмысленным сообщением. - Создать ветку, поработать в ней изолированно, и слить её обратно в
main, включая уверенное разрешение возникшего конфликта слияния. - Подключить локальный репозиторий к GitHub через SSH и выполнить полный цикл
push/pullдля синхронизации изменений в обе стороны.
В Блоке 17 мы существенно сменим тему — займёмся виртуализацией и контейнерами, в первую очередь Docker. Вы обнаружите, что многие концепции, изученные в этом блоке (снимки состояния, история изменений, ветвление для экспериментов), находят интересные параллели в мире контейнеров — а сами Dockerfile (файлы конфигурации для сборки образов), которые мы будем создавать, отлично подходят для хранения и версионирования именно в Git-репозиториях, как мы только что научились делать.