Материал открыт для чтения

Войдите, чтобы сохранять прогресс и результаты.

Войти
Git: Основы

Ветвление, теги и продвинутая история

чтение ~10 минУрок 10 из 15

Ветвление, теги и продвинутая история

module git basics Image02

К этому моменту ты уже знаешь базовый цикл Git: изменить файл, добавить в index, сделать commit, создать ветку, слить ветку и отправить изменения на remote. Дальше начинается рабочая часть Git: как команда организует ветки, как помечает релизы, как временно откладывает изменения, как безопасно отменяет плохие коммиты и как читает сложную историю.


Стратегии ветвления

Стратегия ветвления - это договорённость команды о том, какие ветки существуют и как изменения попадают в стабильную версию.

Git технически не заставляет использовать конкретный процесс. Можно коммитить прямо в main, можно создавать десятки веток, можно делать релизные ветки. Но без общей договорённости история быстро становится непонятной.


Git Flow

Git Flow - классический подход для проектов с выраженным релизным циклом:

main          --------o-----------o-----------
               \      ^           ^
develop   -----o------o-----o-----o-----o-----
              \          \   \       \
feature/A      o--o       \   feature/C
                           feature/B

Основные ветки:

  • main - только стабильные релизы;
  • develop - интеграционная ветка разработки;
  • feature/* - разработка функциональности;
  • release/* - подготовка релиза;
  • hotfix/* - срочные исправления от production-версии.

Плюс Git Flow в явной структуре. Минус - много долгоживущих веток и больше merge-сложности. Для больших enterprise-проектов он всё ещё встречается, но для быстрых CI/CD-команд часто тяжеловат.


Trunk-Based Development

Trunk-Based Development строится вокруг короткоживущих веток и частого попадания изменений в main.

main  ---o---o---o---o---o---o---o---
          \     \       \
feature    o     o       o

Идея: маленькие изменения вливаются быстро, CI постоянно проверяет main, незавершённую функциональность прячут за feature flags.

Плюсы:

  • меньше долгих расхождений истории;
  • меньше больших конфликтов;
  • быстрее feedback от CI/CD;
  • проще деплоить часто.

Минус: нужна дисциплина. Коммиты должны быть маленькими, тесты быстрыми, main нельзя ломать.


GitHub Flow / GitLab Flow

Упрощённый процесс, который часто используют с Pull Request или Merge Request:

  1. Обновить main.
  2. Создать ветку от main.
  3. Сделать небольшую порцию изменений.
  4. Запушить ветку.
  5. Открыть Pull Request.
  6. Пройти CI и code review.
  7. Слить в main.

Типовые команды:

git switch main
git pull origin main
git switch -c feature/add-healthcheck

# работа, коммиты
git add .
git commit -m "Add healthcheck endpoint"

git push -u origin feature/add-healthcheck

Этот подход проще Git Flow и хорошо сочетается с защищённой веткой main.


git log: продвинутые возможности

git log - главный инструмент чтения истории.

Граф всех веток:

git log --oneline --graph --all --decorate

Коммиты конкретного автора:

git log --author="student" --oneline

История конкретного файла:

git log -- README.md
git log --oneline -- README.md

Поиск по сообщению:

git log --grep="fix" --oneline

Изменения за период:

git log --since="1 week ago" --oneline
git log --until="2026-05-01" --oneline

Формат с датой:

git log --format="%h %ad %s" --date=short

Для финального графа с датами удобно:

git log --oneline --graph --all --decorate --date=short --format="%h %ad %d %s"

Сохранять вывод можно обычным перенаправлением:

git log --oneline --graph --all --decorate > /root/branch_graph.txt

Диапазоны: main..develop

В Git часто используются диапазоны вида:

git log main..develop
git diff main..develop

Смысл зависит от команды, но направление важно.

Для git log main..develop это обычно означает: показать коммиты, которые есть в develop, но недостижимы из main.

Для git diff main..develop это означает: показать, как состояние develop отличается от состояния main.

Поменять порядок - значит поменять направление сравнения:

git diff main..develop
git diff develop..main

Список изменённых файлов между ветками:

git diff --name-only main..develop

Это удобно, когда нужен не полный diff, а только перечень затронутых файлов.


git show и git diff

Показать конкретный коммит:

git show abc1234

git show выведет метаданные коммита и patch: какие строки были добавлены или удалены.

Разница между двумя коммитами:

git diff abc1234..def5678

Разница между ветками:

git diff main..feature/my-feature

Только имена файлов:

git diff --name-only main..HEAD

HEAD означает текущую позицию. Если ты находишься на feature-ветке, main..HEAD покажет отличие текущей ветки от main.


git blame: кто написал строку

git blame показывает, какой коммит последний раз менял каждую строку файла:

git blame src/app.py
git blame -L 10,20 src/app.py

Это не инструмент для поиска виноватого человека. Его нормальная цель - найти контекст: когда появилась строка, какой коммит её добавил, с каким сообщением и рядом с какими изменениями.

Частый порядок:

git blame app.py
git show <commit>

Сначала находишь коммит по строке, потом смотришь полный контекст через git show.


Теги

Тег - это имя для конкретного коммита. Чаще всего тегами помечают релизы:

v1.0.0 -> commit abc1234
v1.1.0 -> commit def5678

Lightweight tag - просто указатель:

git tag v1.0.0

Annotated tag хранит автора, дату и сообщение:

git tag -a v1.0.0 -m "First release"

Для релизов предпочтительнее annotated tags, потому что они дают больше информации для аудита.

Список тегов:

git tag
git tag -l "v1.*"

Показать тег:

git show v1.0.0

Отправить тег на remote:

git push origin v1.0.0
git push origin --tags

Теги не всегда пушатся вместе с обычным git push, поэтому релизный тег часто нужно отправлять явно.


git stash: временно отложить работу

git stash сохраняет незакоммиченные изменения во временное хранилище и очищает working tree.

Типичный сценарий: ты работаешь в feature/payment, но нужно срочно переключиться на main для hotfix.

git status
git stash push -m "wip payment form"
git switch main

# делаешь hotfix, commit

git switch feature/payment
git stash pop

Основные команды:

git stash
git stash push -m "message"
git stash list
git stash pop
git stash apply
git stash drop
git stash clear

Разница между pop и apply:

  • git stash pop применяет изменения и удаляет запись из stash;
  • git stash apply применяет изменения, но оставляет запись в stash.

После stash pop всегда проверяй:

git status

Stash - временный инструмент, а не полноценная замена коммитам. Если работу нужно сохранить надолго или передать команде, делай commit.


git revert: безопасная отмена

git revert создаёт новый коммит, который отменяет изменения старого коммита.

git revert HEAD
git revert abc1234
git revert --no-edit abc1234

--no-edit использует стандартное сообщение и не открывает редактор. Это удобно в автоматизированных или учебных сценариях.

Почему revert безопасен для shared branches:

A -- B -- C -- R

Коммит C остаётся в истории, а новый коммит R отменяет его изменения. История не переписывается, поэтому коллеги не получают конфликт из-за исчезнувших коммитов.

Это отличается от git reset, который двигает указатель ветки назад.


reset: когда осторожно

git reset меняет положение текущей ветки и состояние index/working tree в зависимости от режима.

Отменить последний коммит, но оставить изменения в working tree:

git reset HEAD~1

Это --mixed по умолчанию.

Сохранить изменения в staging:

git reset --soft HEAD~1

Полностью сбросить состояние:

git reset --hard HEAD~1

--hard удаляет незакоммиченные изменения из working tree. На общей ветке и в production-репозитории это опасная команда. В shared history обычно выбирай git revert, а не reset.


git cherry-pick

git cherry-pick берёт один конкретный коммит из другой ветки и применяет его поверх текущей ветки.

Типичный сценарий: в ветке hotfix есть один нужный коммит, и его нужно перенести в main, но всю ветку сливать не надо.

git switch main
git log --oneline hotfix
git cherry-pick abc1234

После cherry-pick в main появится новый коммит с теми же изменениями. Хеш будет другим, потому что у коммита новый родитель и новая позиция в истории.

Можно взять последний коммит ветки:

git cherry-pick hotfix

Но в учебных и production-сценариях часто лучше явно посмотреть git log и выбрать конкретный хеш.

Риск cherry-pick: если тот же коммит позже попадёт через merge, история может стать дублированной или конфликтной. Поэтому cherry-pick используют точечно, когда понятно, как изменения будут интегрироваться дальше.


commit --amend

Если ты только что сделал коммит и заметил ошибку в сообщении:

git commit --amend -m "Better message"

Если забыл добавить файл:

git add forgotten_file.txt
git commit --amend --no-edit

amend переписывает последний коммит: создаётся новый коммит вместо старого. Это нормально для локальной ветки до push. После push в общую ветку используй осторожно, потому что история уже могла попасть к коллегам.


Короткая памятка

Задача Команда
Граф всех веток git log --oneline --graph --all --decorate
Коммиты автора git log --author="student" --oneline
История файла git log -- README.md
Изменённые файлы между ветками git diff --name-only main..develop
Annotated tag git tag -a v1.0.0 -m "First release"
Список тегов git tag
Спрятать изменения git stash push -m "message"
Вернуть stash git stash pop
Безопасно отменить коммит git revert --no-edit <commit>
Перенести один коммит git cherry-pick <commit>

Продвинутый Git - это не набор редких команд ради красоты. Это умение читать историю и выбирать операцию, которая не сломает работу команды.

Материал изучен?

Войдите, чтобы сохранить прогресс и перейти к практической лаборатории.

Войти и продолжить