Всем привет, меня зовут Сергей Прощаев. Я руковожу направлением Java‑разработки в FinTech, а ещё помогаю начинающим специалистам осваивать тонкости профессии на курсах Отус. Сегодня поговорим о Git. Точнее, о том, как перестать его бояться и начать использовать так, чтобы коллеги (и вы сами) не краснели, глядя на историю ваших изменений.
Почему я решил написать эту статью? На любом курсе по разработке в Отус есть блок вебинаров по работе с Git. И в большинстве случаев основная сложность начинается здесь. Ветки называются «asdasd», коммиты — «правки», «ы», «апдейт», а в пулл‑реквесте висит 50 файлов с изменениями, половина из которых — случайно попавший туда мусор. И самое грустное, что многие даже не понимают, в чём проблема. «Ну работает же, чего вы придираетесь?»
Но в реальной команде такой подход приведёт к хаосу. Представьте, что вам нужно откатить изменение, которое сломало тесты, а все коммиты подписаны «fix» — попробуй найди нужный. Или вы мержите ветку, а там конфликты, которые не распутать, потому что никто не заботился об актуальности своей ветки. Git — это не просто хранилище кода, это инструмент коммуникации. И сегодня я покажу, как сделать эту коммуникацию эффективной.
Git — это не страшно, это просто граф
Прежде чем лезть в консоль, давайте договоримся о терминах. Git хранит историю проекта как граф коммитов. Каждый коммит — это снапшот состояния файлов, у него есть автор, дата, уникальный хэш и сообщение. Ветка — это просто указатель на конкретный коммит. Когда вы делаете новый коммит, указатель ветки автоматически перемещается на него.
Посмотрите на эту схему (я специально нарисовал её в Mermaid, чтобы вы могли вставить код в любой редактор и увидеть живой граф):

На рисунке 1 изображен пример графа коммитов: на main сделан начальный коммит, от него отходит ветка feature/login, в ней два коммита, затем на main добавлен ещё один коммит (исправление опечатки) и выполнено слияние feature/login.
Здесь всё просто: main (или master) — основная ветка, с которой обычно работают пользователи. feature/login — ветка для разработки новой функциональности. После того как фича готова, её вливают обратно в main. Именно так выглядит изолированная работа: вы не мешаете другим, другие не мешают вам.
Какими бывают ветки
В учебных проектах или на небольших задачах часто хватает одной основной ветки и нескольких тематических. Но в серьёзной разработке сложились модели ветвления, самая известная из которых — Git Flow. Она предписывает иметь долгоживущие ветки main и develop, а также временные: feature/*, release/*, hotfix/*.
main — всегда содержит стабильный, готовый к выкладке код
develop — ветка интеграции, куда сливаются все новые фичи
feature/* — каждая новая функциональность разрабатывается в своей ветке от develop
release/* — подготовка к релизу (исправление багов, документация)
hotfix/* — срочные исправления на main
Звучит сложно, но на практике для новичка главное понять разницу между долгоживущей(main, develop) и временной веткой (ваша задача). Временная ветка живёт ровно столько, сколько вы делаете задачу. Как только её вмержили, ветку можно (и нужно) удалить — и локально, и на сервере.
На курсах «OTUS» мы обычно используем упрощённый вариант: есть main и от неё отходят ветки для домашних заданий с префиксом homework/. Например: homework/lesson1-git-basics. Это сразу говорит, что в ветке, и облегчает жизнь ментору.
Создаём ветку: от слов к делу
Давайте сделаем небольшую тренировку и пройдемся по основным шагам, через которые проходит любой начинающий разработчик на курсах OTUS.
Допустим, вы клонировали репозиторий курса. Убедитесь, что вы находитесь на актуальном main:
git checkout main git pull origin main
Теперь создаём новую ветку для своего задания. Рекомендую сразу переключиться на неё:
git checkout -b homework/lesson1-git-basics
Флаг -b создаёт ветку и переключает на неё. Если хотите сделать то же самое по шагам:
git branch homework/lesson1-git-basics # создали ветку git checkout homework/lesson1-git-basics # переключились
Современный Git (версии 2.23+) предлагает более понятные команды:
git switch -c homework/lesson1-git-basics
Как назвать ветку — вопрос договорённости в команде. Встречал разные стили: feature/JIRA-123, bugfix/issue-description, username/task-name.
Главные правила: никаких кириллицы и пробелов, используйте дефисы или слеши для разделения слов. Например: feature/add-user-service, hotfix/fix-npe, homework/03-junit-tests.
Коммиты: каждый шаг должен быть осмыслен
Итак, вы написали код для своего задания. Например, простой класс User:
package ru.otus; public class User { private String name; private String email; public User(String name, String email) { this.name = name; this.email = email; } // ... }
Как сохранить изменения в Git? Сначала добавляем файлы в индекс (staging area):
git add src/main/java/ru/otus/User.java
Можно добавить все изменённые файлы сразу:
git add .
но будьте осторожны — так вы можете случайно захватить временные файлы или мусор. Лучше явно перечислить то, что должно попасть в коммит.
Теперь создаём коммит:
git commit -m "Add User class with name and email"
Но давайте остановимся и подумаем: хорошее ли это сообщение? Оно отвечает на вопрос «Что сделано?» — добавлен класс User. Но не отвечает на вопрос «Почему?». Если коммит маленький и очевидный, можно ограничиться одной строкой. Но представьте, что вы возвращаетесь к этому коду через полгода и видите сообщение «Add User class». Вы уже не вспомните, зачем понадобился этот класс и почему поля именно такие.
Поэтому в сообщениях коммитов придерживайтесь best practices:
Заголовок (первая строка) — не длиннее 50 символов, пишется в повелительном наклонении («Add», «Fix», «Update»), без точки в конце. Это как тема письма.
Если нужно больше деталей, после пустой строки идёт тело сообщения. В нём можно описать мотивацию изменений, ссылки на задачи, важные технические нюансы. Ширина строки тела — до 72 символов для удобства чтения в консоли.
Хороший тон — привязывать коммит к задаче в трекере (например, JIRA-123: Add validation for email).
Пример хорошего сообщения (вводится через git commit без флага -m, чтобы открылся редактор):
Add User class for authentication module - User stores name and email - Email must be unique in the system (will be enforced by DB) - This class is part of the new login flow described in #TASK-456 The previous implementation used a separate profile class, but we need a single entry point for user data.
Есть и более формальный подход — Conventional Commits. Он предписывает использовать префиксы типа feat:, fix:, docs:, style:, refactor:, test:, chore:. Это особенно полезно, если вы потом автоматически генерируете changelog. Для домашнего задания это может быть избыточно, но на работе такой стиль часто входит в стандарт команды.
Основная идея: сообщение коммита начинается с префикса, который обозначает тип изменения, затем двоеточие и пробел, а после – краткое описание. Иногда можно добавить область (scope) в скобках после типа, например feat(api): add new endpoint.
Вот расшифровка самых частых префиксов и примеры к ним:
Префикс | Когда использовать | Пример сообщения |
feat: | Добавление новой функциональности для пользователя (новая фича, новый модуль, новый метод в публичном API) | feat: add password recovery by email |
fix: | Исправление ошибки (бага). | fix: handle division by zero in calculator |
docs: | Изменения только в документации (README, Javadoc, комментарии в коде). | docs: update project setup guide |
style: | Правки форматирования, отступов, лишних пробелов, точек с запятой – всё, что не меняет логику кода. | style: reformat code according to google style guide |
refactor: | Изменение кода, которое не исправляет ошибку и не добавляет новую функциональность (например, переименование переменной, выделение метода). | refactor: extract email validation to separate method |
test: | Добавление или изменение тестов (юнит-тесты, интеграционные тесты). | test: add negative scenarios for login |
chore: | Обновление вспомогательных инструментов, зависимостей, конфигурации сборки – всё, что не относится напрямую к коду приложения. | chore: update maven compiler plugin to 3.8.1 |
Эти префиксы – ядро, но есть и другие: perf: (улучшение производительности), ci:(изменения в CI/CD), build: (изменения в системе сборки), revert: (откат коммита). Для начала достаточно освоить основные семь.
Как это выглядит на практике?
Допустим, вы пишете домашнее задание и добавляете класс User. Логично сделать коммит типа feat. Но если вы потом заметили, что забыли обработать пустой email, и исправляете – это fix. А если просто перенесли метод в другой класс без изменения логики – refactor.
git commit -m "feat: add User class with name and email" git commit -m "fix: validate email format in User constructor" git commit -m "refactor: move email validation to EmailUtils"
Теперь, взглянув на историю, любой сразу поймёт, что происходило. А если подключить инструмент вроде standard-version, он на основе этих префиксов автоматически увеличит версию и сгенерирует красивый changelog.
Однажды потратил полдня, разбираясь, почему упал билд после мержа. Оказалось, коллега сделал коммит с сообщением «правки» и случайно удалил важную зависимость в pom.xml. Если бы он написал «Remove unused dependency», я бы даже не открывал тот коммит, потому что «unused» не должно ломать сборку. А так пришлось вручную перебирать все «правки». С тех пор я требую от команды осмысленных сообщений.
Pull Request: как показать результат
Вы сделали несколько коммитов в своей ветке, всё проверили локально. Теперь нужно отправить задание на проверку преподавателю. Для этого вы пушите ветку в удалённый репозиторий:
git push origin homework/lesson1-git-basics
Если ветки на сервере ещё нет, Git создаст её. Теперь идём на сайт GitHub (или GitLab, Bitbucket) и видим красивую кнопку «Create pull request», как показано на рисунке 2 и нажимаем.

Важно! Перед созданием PR убедитесь, что ваша ветка не отстала от основной. Пока вы писали код, в main могли добавиться новые коммиты. Если не подтянуть их, после мержа могут возникнуть конфликты. Поэтому я всегда делаю перед пушем:
git fetch origin git rebase origin/main
Эта команда переставляет ваши коммиты поверх последних изменений в main. Если есть конфликты, вы решаете их локально, а не в PR. Это правило профессионалов.
Теперь заполняем описание PR. Оно должно быть информативным: что сделано, как проверить, есть ли особенности. Пример:
Название PR: Homework 1: Git basics (User class)
Описание:
Реализован класс User с полями name, email.
Добавлены тесты (если были).
Задание выполнено согласно требованиям: ...
Как проверить:
Запустить тесты: mvn test
Убедиться, что код компилируется.
В PR вы можете указать ревьюера (преподавателя), добавить метки, прикрепить скриншоты. Главное — не оставляйте описание пустым.
Что еще запомнить?
Перед коммитом всегда проверяй, что попадает в индекс (git status).
Не забывай про .gitignore — туда нужно добавить папки IDE, результаты сборки (target/, build/), логи.
Описание PR должно быть понятным, чтобы ревьюеру не приходилось гадать, что ты хотел сделать.
И главное: ревью — это не критика, а помощь. Комментарии преподавателя делают код лучше.
Git — это не просто команды, это культура разработки.
Что дальше? Конфликты, rebase, работа в команде
В этой статье затронул лишь базу, но её достаточно, чтобы начать уверенно выполнять домашние задания и не пугать коллег. Однако в реальной работе вас ждут и конфликты при слиянии, и перебазирование, и работа с несколькими удалёнными репозиториями, и многое другое.

На курсе «Автоматизация тестирования на Java. Базовый уровень» как раз разбирается база: Java, автотесты для интерфейса и API, ключевые шаблоны и инструменты, с которыми тестирование становится воспроизводимым и внятным. Для знакомства с форматом обучения и экспертами приходите на бесплатные уроки:
19 марта, 20:00. «Основы многопоточности в Java. Асинхронные методы». Записаться
23 марта, 20:00. «ИИ в автотестах: помощник или угроза?». Записаться
Полный список бесплатных уроков марта по всем ИТ-направлениям смотрите в дайджесте.
